diff --git a/BUILD.gn b/BUILD.gn
index a1249ed..3e48915 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1055,6 +1055,7 @@
       "//third_party/blink/public/mojom:mojom_platform_js_data_deps",
       "//third_party/blink/renderer/core/html:js_files_for_form_controls_web_tests",
       "//third_party/blink/renderer/core/script:js_files_for_web_tests",
+      "//third_party/catapult/third_party/typ",
       "//third_party/mesa_headers",
       "//tools/imagediff",
     ]
diff --git a/DEPS b/DEPS
index 7f106c3..6798433 100644
--- a/DEPS
+++ b/DEPS
@@ -167,11 +167,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': 'c34e434df0d79047e7ddae69fbdbbe9e91bc2a52',
+  'skia_revision': 'a4828a13c27a0bbd2a2b9169916a0b4d58853df4',
   # 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': '71bbf6321fea2c9e274f1886342ef2e4c1ae1752',
+  'v8_revision': 'e20a46d98b931f30e20fcb1928a0522cd3dd2f57',
   # 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.
@@ -179,7 +179,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'fede5cb664d96da6ea6acc0bc208d32a14431f32',
+  'angle_revision': 'da1f90aa77b4fc5dcb6a5d17def690d3b01e9c1d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -194,7 +194,7 @@
   #
   # Note this revision should be updated with
   # third_party/boringssl/roll_boringssl.py, not roll-dep.
-  'boringssl_revision': '6a2609dae219e4300dfc62b2a37f10b5c845547b',
+  'boringssl_revision': 'bc4c09df6416a3a0d0cf321c6c13023c77e2fec4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -230,7 +230,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': 'c7af59115ee3cadd28fa6804eac403c3f57d7844',
+  'catapult_revision': '0b3653782e33551b03ff5aead895016e6ec82c68',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -302,11 +302,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '9e64afcb91f74e75a16fa5639d272c5c2a536bc6',
+  'dawn_revision': 'b6acae6d353d3a4b9b9054a72239144ead122f8d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '5843bfd652048b9961316a62dbf1cad68e7a55ac',
+  'quiche_revision': 'f76cf2ae5e7a6711418a1e256bdb78121e6f4adb',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -862,7 +862,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '1c834ea5451cb00bd23628733bb4d7a53993d4af',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9bc8545214f911371665a3cfa9f0cf93aac9f25d',
       'condition': 'checkout_linux',
   },
 
@@ -887,7 +887,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '5abb9b7c5d0c0a5f81f4a0da741680df9b9d128c',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '033004652fafc4d03325d5ec5dd415ddf72462a1',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1280,7 +1280,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '6529b908a53e6c9f37ab2d36750a2b675293bf9a',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '8dda56311c7ded002f01dcb15bfe5310888ff5b8',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
diff --git a/android_webview/browser/aw_web_contents_delegate.cc b/android_webview/browser/aw_web_contents_delegate.cc
index 376d1600..3e676195 100644
--- a/android_webview/browser/aw_web_contents_delegate.cc
+++ b/android_webview/browser/aw_web_contents_delegate.cc
@@ -289,7 +289,7 @@
 void AwWebContentsDelegate::EnterFullscreenModeForTab(
     content::WebContents* web_contents,
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   WebContentsDelegateAndroid::EnterFullscreenModeForTab(web_contents, origin,
                                                         options);
   is_fullscreen_ = true;
diff --git a/android_webview/browser/aw_web_contents_delegate.h b/android_webview/browser/aw_web_contents_delegate.h
index 719b6e95..0d9b7d8 100644
--- a/android_webview/browser/aw_web_contents_delegate.h
+++ b/android_webview/browser/aw_web_contents_delegate.h
@@ -69,7 +69,7 @@
   void EnterFullscreenModeForTab(
       content::WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override;
+      const blink::FullScreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
   bool IsFullscreenForTabOrPending(
       const content::WebContents* web_contents) override;
diff --git a/apps/load_and_launch_browsertest.cc b/apps/load_and_launch_browsertest.cc
index bd35115..de73e18 100644
--- a/apps/load_and_launch_browsertest.cc
+++ b/apps/load_and_launch_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/process/launch.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/test_switches.h"
 #include "base/test/test_timeouts.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
@@ -65,7 +66,7 @@
   new_cmdline.AppendSwitchNative(apps::kLoadAndLaunchApp,
                                  app_path.value());
 
-  new_cmdline.AppendSwitch(content::kLaunchAsBrowser);
+  new_cmdline.AppendSwitch(switches::kLaunchAsBrowser);
   base::Process process =
       base::LaunchProcess(new_cmdline, base::LaunchOptionsForTest());
   ASSERT_TRUE(process.IsValid());
@@ -105,7 +106,7 @@
 
   new_cmdline.AppendSwitchNative(apps::kLoadAndLaunchApp,
                                  app_path.value());
-  new_cmdline.AppendSwitch(content::kLaunchAsBrowser);
+  new_cmdline.AppendSwitch(switches::kLaunchAsBrowser);
   new_cmdline.AppendArgPath(test_file_path);
 
   base::Process process =
diff --git a/ash/system/message_center/unified_message_center_bubble.cc b/ash/system/message_center/unified_message_center_bubble.cc
index 4b1d8c6e..ed39f9d 100644
--- a/ash/system/message_center/unified_message_center_bubble.cc
+++ b/ash/system/message_center/unified_message_center_bubble.cc
@@ -93,6 +93,10 @@
   return tray_->FocusQuickSettings(reverse);
 }
 
+bool UnifiedMessageCenterBubble::IsMessageCenterVisible() {
+  return message_center_view_->GetVisible();
+}
+
 TrayBackgroundView* UnifiedMessageCenterBubble::GetTray() const {
   return tray_;
 }
diff --git a/ash/system/message_center/unified_message_center_bubble.h b/ash/system/message_center/unified_message_center_bubble.h
index 6d0bf39..d9e44f9 100644
--- a/ash/system/message_center/unified_message_center_bubble.h
+++ b/ash/system/message_center/unified_message_center_bubble.h
@@ -38,6 +38,9 @@
   // Relinquish focus and transfer it to the quick settings widget.
   bool FocusOut(bool reverse);
 
+  // Returns true if notifications are shown.
+  bool IsMessageCenterVisible();
+
   // TrayBubbleBase:
   TrayBackgroundView* GetTray() const override;
   TrayBubbleView* GetBubbleView() const override;
diff --git a/ash/system/message_center/unified_message_center_bubble_unittest.cc b/ash/system/message_center/unified_message_center_bubble_unittest.cc
index 9539c22b..ac47430 100644
--- a/ash/system/message_center/unified_message_center_bubble_unittest.cc
+++ b/ash/system/message_center/unified_message_center_bubble_unittest.cc
@@ -249,4 +249,36 @@
             GetLastQuickSettingsFocusable());
 }
 
+TEST_F(UnifiedMessageCenterBubbleTest, FocusCycleWithNoNotifications) {
+  EnableMessageCenterRefactor();
+  GetPrimaryUnifiedSystemTray()->ShowBubble(true);
+
+  views::Widget* quick_settings_widget =
+      GetSystemTrayBubble()->GetBubbleWidget();
+  views::Widget* message_center_widget =
+      GetMessageCenterBubble()->GetBubbleWidget();
+
+  // First tab should focus the first element in the quick settings bubble.
+  DoTab();
+  EXPECT_TRUE(quick_settings_widget->IsActive());
+  EXPECT_FALSE(message_center_widget->IsActive());
+  EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(),
+            GetFirstQuickSettingsFocusable());
+
+  // Keep tabbing until we reach the last focusable element in the quick
+  // settings bubble.
+  while (quick_settings_widget->GetFocusManager()->GetFocusedView() !=
+         GetLastQuickSettingsFocusable()) {
+    DoTab();
+  }
+
+  // Tab at the last element in the quick settings bubble should move focus to
+  // the first element in the quick settings bubble.
+  DoTab();
+  EXPECT_TRUE(quick_settings_widget->IsActive());
+  EXPECT_FALSE(message_center_widget->IsActive());
+  EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(),
+            GetFirstQuickSettingsFocusable());
+}
+
 }  // namespace ash
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc
index 9c70fd7..d5e658a 100644
--- a/ash/system/unified/unified_system_tray.cc
+++ b/ash/system/unified/unified_system_tray.cc
@@ -178,7 +178,7 @@
 
 bool UnifiedSystemTray::IsMessageCenterBubbleShown() const {
   if (message_center_bubble_)
-    return !!message_center_bubble_->GetBubbleWidget();
+    return message_center_bubble_->IsMessageCenterVisible();
 
   return false;
 }
diff --git a/base/android/library_loader/library_prefetcher.cc b/base/android/library_loader/library_prefetcher.cc
index bab0171..a268fd32 100644
--- a/base/android/library_loader/library_prefetcher.cc
+++ b/base/android/library_loader/library_prefetcher.cc
@@ -23,7 +23,6 @@
 #include "base/format_macros.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/process_metrics.h"
 #include "base/strings/string_util.h"
@@ -189,9 +188,8 @@
   }
 }
 
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-// Used for "LibraryLoader.PrefetchDetailedStatus".
+// These values were used in the past for recording
+// "LibraryLoader.PrefetchDetailedStatus".
 enum class PrefetchStatus {
   kSuccess = 0,
   kWrongOrdering = 1,
@@ -269,9 +267,6 @@
 #endif
 
   PrefetchStatus status = ForkAndPrefetch(ordered_only);
-  UMA_HISTOGRAM_BOOLEAN("LibraryLoader.PrefetchStatus",
-                        status == PrefetchStatus::kSuccess);
-  UMA_HISTOGRAM_ENUMERATION("LibraryLoader.PrefetchDetailedStatus", status);
   if (status != PrefetchStatus::kSuccess) {
     LOG(WARNING) << "Cannot prefetch the library. status = "
                  << static_cast<int>(status);
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index cf2c9fe..a8c3f4f 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8899641024057349936
\ No newline at end of file
+8899615264992318816
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index abe84f5..c8bde10 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8899648435901939984
\ No newline at end of file
+8899615546258949840
\ No newline at end of file
diff --git a/build/toolchain/win/rc/rc.py b/build/toolchain/win/rc/rc.py
index 2eff7d2..a01a5ab 100755
--- a/build/toolchain/win/rc/rc.py
+++ b/build/toolchain/win/rc/rc.py
@@ -162,7 +162,7 @@
   rc_cmd.append('/fo' + flags.output)
   if is_utf8:
     rc_cmd.append('/utf-8')
-  # TODO(thakis): rc currently always prints full paths for /showIncludes,
+  # TODO(thakis): cl currently always prints full paths for /showIncludes,
   # but clang-cl /P doesn't.  Which one is right?
   if flags.show_includes:
     rc_cmd.append('/showIncludes')
@@ -172,9 +172,65 @@
   rc_cmd += flags.includes
   p = subprocess.Popen(rc_cmd, stdin=subprocess.PIPE)
   p.communicate(input=preprocessed_output)
+
+  if flags.show_includes and p.returncode == 0:
+    # Since tool("rc") can't have deps, add deps on this script and on rc.py
+    # and its deps here, so that rc edges become dirty if rc.py changes.
+    print('Note: including file: ../../build/toolchain/win/tool_wrapper.py')
+    print('Note: including file: ../../build/toolchain/win/rc/rc.py')
+    print(
+        'Note: including file: ../../build/toolchain/win/rc/linux64/rc.sha1')
+    print('Note: including file: ../../build/toolchain/win/rc/mac/rc.sha1')
+    print(
+        'Note: including file: ../../build/toolchain/win/rc/win/rc.exe.sha1')
+
   return p.returncode
 
 
+def CompareToMsRcOutput(preprocessed_output, is_utf8, flags):
+  msrc_in = flags.output + '.preprocessed.rc'
+
+  # Strip preprocessor line markers.
+  preprocessed_output = re.sub(r'^#.*$', '', preprocessed_output, flags=re.M)
+  if is_utf8:
+    preprocessed_output = preprocessed_output.decode('utf-8').encode('utf-16le')
+  with open(msrc_in, 'wb') as f:
+    f.write(preprocessed_output)
+
+  msrc_out = flags.output + '_ms_rc'
+  msrc_cmd = ['rc', '/nologo', '/fo' + msrc_out]
+
+  # Make sure rc-relative resources can be found. rc.exe looks for external
+  # resource files next to the file, but the preprocessed file isn't where the
+  # input was.
+  # Note that rc searches external resource files in the order of
+  # 1. next to the input file
+  # 2. relative to cwd
+  # 3. next to -I directories
+  # Changing the cwd means we'd have to rewrite all -I flags, so just add
+  # the input file dir as -I flag. That technically gets the order of 1 and 2
+  # wrong, but in Chromium's build the cwd is the gn out dir, and generated
+  # files there are in obj/ and gen/, so this difference doesn't matter in
+  # practice.
+  if os.path.dirname(flags.input):
+    msrc_cmd += [ '-I' + os.path.dirname(flags.input) ]
+
+  # Microsoft rc.exe searches for referenced files relative to -I flags in
+  # addition to the pwd, so -I flags need to be passed both to both
+  # the preprocessor and rc.
+  msrc_cmd += flags.includes
+
+  # Input must come last.
+  msrc_cmd += [ msrc_in ]
+
+  rc_exe_exit_code = subprocess.call(msrc_cmd)
+  # Assert Microsoft rc.exe and rc.py produced identical .res files.
+  if rc_exe_exit_code == 0:
+    import filecmp
+    assert filecmp.cmp(msrc_out, flags.output)
+  return rc_exe_exit_code
+
+
 def main():
   # This driver has to do these things:
   # 1. Parse flags.
@@ -185,7 +241,17 @@
   flags = ParseFlags()
   rc_file_data, is_utf8 = ReadInput(flags.input)
   preprocessed_output = Preprocess(rc_file_data, flags)
-  return RunRc(preprocessed_output, is_utf8, flags)
+  rc_exe_exit_code = RunRc(preprocessed_output, is_utf8, flags)
+
+  # 5. On Windows, we also call Microsoft's rc.exe and check that we produced
+  #   the same output.
+  # Since Microsoft's rc has a preprocessor that only accepts 32 characters
+  # for macro names, feed the clang-preprocessed source into it instead
+  # of using ms rc's preprocessor.
+  if sys.platform == 'win32' and rc_exe_exit_code == 0:
+    rc_exe_exit_code = CompareToMsRcOutput(preprocessed_output, is_utf8, flags)
+
+  return rc_exe_exit_code
 
 
 if __name__ == '__main__':
diff --git a/build/toolchain/win/tool_wrapper.py b/build/toolchain/win/tool_wrapper.py
index 3834cf2..e5cc81b 100644
--- a/build/toolchain/win/tool_wrapper.py
+++ b/build/toolchain/win/tool_wrapper.py
@@ -212,46 +212,11 @@
   def ExecRcWrapper(self, arch, *args):
     """Converts .rc files to .res files."""
     env = self._GetEnv(arch)
-
-    # We run two resource compilers:
-    # 1. A custom one at build/toolchain/win/rc/rc.py which can run on
-    #    non-Windows, and which has /showIncludes support so we can track
-    #    dependencies (e.g. on .ico files) of .rc files.
-    # 2. On Windows, regular Microsoft rc.exe, to make sure rc.py produces
-    #    bitwise identical output.
-
-    # 1. Run our rc.py.
-    # Also pass /showIncludes to track dependencies of .rc files.
     args = list(args)
     rcpy_args = args[:]
     rcpy_args[0:1] = [sys.executable, os.path.join(BASE_DIR, 'rc', 'rc.py')]
-    rcpy_res_output = rcpy_args[-2]
-    assert rcpy_res_output.startswith('/fo')
-    assert rcpy_res_output.endswith('.res')
-    rc_res_output = rcpy_res_output + '_ms_rc'
-    args[-2] = rc_res_output
     rcpy_args.append('/showIncludes')
-    rc_exe_exit_code = subprocess.call(rcpy_args, env=env)
-    if rc_exe_exit_code == 0:
-      # Since tool("rc") can't have deps, add deps on this script and on rc.py
-      # and its deps here, so that rc edges become dirty if rc.py changes.
-      print('Note: including file: ../../build/toolchain/win/tool_wrapper.py')
-      print('Note: including file: ../../build/toolchain/win/rc/rc.py')
-      print(
-          'Note: including file: ../../build/toolchain/win/rc/linux64/rc.sha1')
-      print('Note: including file: ../../build/toolchain/win/rc/mac/rc.sha1')
-      print(
-          'Note: including file: ../../build/toolchain/win/rc/win/rc.exe.sha1')
-
-    # 2. Run Microsoft rc.exe.
-    if sys.platform == 'win32' and rc_exe_exit_code == 0:
-      rc_exe_exit_code = subprocess.call(args, shell=True, env=env)
-      # Assert Microsoft rc.exe and rc.py produced identical .res files.
-      if rc_exe_exit_code == 0:
-        import filecmp
-        # Strip "/fo" prefix.
-        assert filecmp.cmp(rc_res_output[3:], rcpy_res_output[3:])
-    return rc_exe_exit_code
+    return subprocess.call(rcpy_args, env=env)
 
   def ExecActionWrapper(self, arch, rspfile, *dirname):
     """Runs an action command line from a response file using the environment
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index 219f7506..c3503cc4 100755
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -29,6 +29,11 @@
   ('2017', '15.0'),
 ])
 
+# List of preferred VC toolset version based on MSVS
+MSVC_TOOLSET_VERSION = {
+   '2019' : 'VC142',
+   '2017' : 'VC141',
+}
 
 def SetEnvironmentAndGetRuntimeDllDirs():
   """Sets up os.environ to use the depot_tools VS toolchain with gyp, and
@@ -241,14 +246,19 @@
   exist, but the target directory does exist."""
   if target_cpu == 'arm64':
     # Windows ARM64 VCRuntime is located at {toolchain_root}/VC/Redist/MSVC/
-    # {x.y.z}/[debug_nonredist/]arm64/Microsoft.VC141.CRT/.
+    # {x.y.z}/[debug_nonredist/]arm64/Microsoft.VC14x.CRT/.
+    # Select VC toolset directory based on Visual Studio version
     vc_redist_root = FindVCRedistRoot()
     if suffix.startswith('.'):
+      vc_toolset_dir = 'Microsoft.{}.CRT' \
+         .format(MSVC_TOOLSET_VERSION[GetVisualStudioVersion()])
       source_dir = os.path.join(vc_redist_root,
-                                'arm64', 'Microsoft.VC141.CRT')
+                                'arm64', vc_toolset_dir)
     else:
+      vc_toolset_dir = 'Microsoft.{}.DebugCRT' \
+         .format(MSVC_TOOLSET_VERSION[GetVisualStudioVersion()])
       source_dir = os.path.join(vc_redist_root, 'debug_nonredist',
-                                'arm64', 'Microsoft.VC141.DebugCRT')
+                                'arm64', vc_toolset_dir)
   for file_part in ('msvcp', 'vccorlib', 'vcruntime'):
     dll = dll_pattern % file_part
     target = os.path.join(target_dir, dll)
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index a0e7bf3..f072f9b6 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -438,14 +438,7 @@
   "javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorTest.java",
   "javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java",
   "javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java",
-  "javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetCardsUiCaptureTest.java",
-  "javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetNoTilesUiCaptureTest.java",
-  "javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetTilesUiCaptureTest.java",
-  "javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetUiCaptureTest.java",
   "javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java",
-  "javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTest.java",
-  "javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTestRule.java",
-  "javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetUiCaptureTest.java",
   "javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java",
   "javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java",
   "javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index 8e62f8e..9233b76a 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -138,6 +138,11 @@
     "java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantTermsSection.java",
     "java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantVerticalExpander.java",
     "java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantVerticalExpanderAccordion.java",
+    "java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSection.java",
+    "java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSectionContainer.java",
+    "java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSectionFactory.java",
+    "java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantStaticTextSection.java",
+    "java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantTextInputSection.java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
@@ -202,6 +207,7 @@
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantOverlayUiTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataTestHelper.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java",
+    "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTextUtilsTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinatorTest.java",
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_static_text_section.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_static_text_section.xml
new file mode 100644
index 0000000..c99f130
--- /dev/null
+++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_static_text_section.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="@dimen/autofill_assistant_bottombar_horizontal_spacing"
+    android:paddingEnd="@dimen/autofill_assistant_bottombar_horizontal_spacing">
+
+  <TextView android:id="@+id/section_title"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:textAppearance="@style/TextAppearance.BlackTitle2"
+      android:paddingBottom="@dimen/autofill_assistant_payment_request_title_padding"/>
+
+  <TextView
+      android:id="@+id/text"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java
index 941bd74..1b06ae4 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java
@@ -73,6 +73,10 @@
         return mBottomBarCoordinator;
     }
 
+    AssistantKeyboardCoordinator getKeyboardCoordinator() {
+        return mKeyboardCoordinator;
+    }
+
     /**
      * Show the Chrome feedback form.
      */
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantKeyboardCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantKeyboardCoordinator.java
index 38b75ec..4cda497 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantKeyboardCoordinator.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantKeyboardCoordinator.java
@@ -35,6 +35,16 @@
         });
     }
 
+    /** Returns whether the keyboard is currently shown. */
+    boolean isKeyboardShown() {
+        return mKeyboardDelegate.isKeyboardShowing(mActivity, mActivity.getCompositorViewHolder());
+    }
+
+    /** Hides the keyboard. */
+    void hideKeyboard() {
+        mKeyboardDelegate.hideKeyboard(mActivity.getCompositorViewHolder());
+    }
+
     /**
      * Enable or disable the soft keyboard.
      */
@@ -60,7 +70,7 @@
     // shown. We should improve it and prevent from the showing in the first place.
     private void onKeyboardVisibilityChanged(boolean isShowing) {
         if (isShowing && !mAllowShowingSoftKeyboard) {
-            mKeyboardDelegate.hideKeyboard(mActivity.getCompositorViewHolder());
+            hideKeyboard();
         }
     }
 }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantTextUtils.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantTextUtils.java
index b286bc8..3891e3f 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantTextUtils.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantTextUtils.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.autofill_assistant;
 
+import android.graphics.Typeface;
 import android.text.method.LinkMovementMethod;
 import android.text.style.StyleSpan;
 import android.widget.TextView;
@@ -28,6 +29,9 @@
     /** Bold tags of the form <b>...</b>. */
     private static final SpanApplier.SpanInfo BOLD_SPAN_INFO =
             new SpanApplier.SpanInfo("<b>", "</b>", new StyleSpan(android.graphics.Typeface.BOLD));
+    /** Italic tags of the form <i>...</i>. */
+    private static final SpanApplier.SpanInfo ITALIC_SPAN_INFO =
+            new SpanApplier.SpanInfo("<i>", "</i>", new StyleSpan(Typeface.ITALIC));
     /** Links of the form <link0>...</link0>. */
     private static final Pattern LINK_PATTERN = Pattern.compile("<link(\\d+)>");
 
@@ -44,6 +48,9 @@
         if (text.contains("<b>")) {
             spans.add(BOLD_SPAN_INFO);
         }
+        if (text.contains("<i>")) {
+            spans.add(ITALIC_SPAN_INFO);
+        }
 
         // We first collect the link IDs into a set to allow multiple links with same ID.
         Set<Integer> linkIds = new HashSet<>();
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
index e97c33c..7140e78 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -202,6 +202,16 @@
     }
 
     @CalledByNative
+    private boolean isKeyboardShown() {
+        return mCoordinator.getKeyboardCoordinator().isKeyboardShown();
+    }
+
+    @CalledByNative
+    private void hideKeyboard() {
+        mCoordinator.getKeyboardCoordinator().hideKeyboard();
+    }
+
+    @CalledByNative
     private void showSnackbar(int delayMs, String message) {
         mSnackbarController =
                 AssistantSnackbar.show(mActivity, delayMs, message, this::safeSnackbarResult);
@@ -250,7 +260,8 @@
     }
 
     /**
-     * Adds a cancel action button to the chip list, which shows the snackbar and then executes
+     * Adds a cancel action button to the chip list. If the keyboard is currently shown, it
+     * dismisses the keyboard. Otherwise, it shows the snackbar and then executes
      * {@code actionIndex}, or shuts down Autofill Assistant if {@code actionIndex} is {@code -1}.
      */
     @CalledByNative
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
index ea08204..20e68d1 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
@@ -10,6 +10,7 @@
 
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantAdditionalSectionContainer;
 import org.chromium.chrome.browser.payments.AddressEditor;
 import org.chromium.chrome.browser.payments.AutofillPaymentApp;
 import org.chromium.chrome.browser.payments.AutofillPaymentInstrument;
@@ -100,6 +101,8 @@
         private final AssistantShippingAddressSection mShippingAddressSection;
         private final AssistantTermsSection mTermsSection;
         private final AssistantTermsSection mTermsAsCheckboxSection;
+        private final AssistantAdditionalSectionContainer mPrependedSections;
+        private final AssistantAdditionalSectionContainer mAppendedSections;
         private final Object mDividerTag;
         private final Activity mActivity;
         private PersonalDataManager.PersonalDataManagerObserver mPersonalDataManagerObserver;
@@ -112,7 +115,9 @@
                 AssistantPaymentMethodSection paymentMethodSection,
                 AssistantShippingAddressSection shippingAddressSection,
                 AssistantTermsSection termsSection, AssistantTermsSection termsAsCheckboxSection,
-                Object dividerTag, Activity activity) {
+                AssistantAdditionalSectionContainer prependedSections,
+                AssistantAdditionalSectionContainer appendedSections, Object dividerTag,
+                Activity activity) {
             mRootView = rootView;
             mPaymentRequestExpanderAccordion = accordion;
             mSectionToSectionPadding = sectionPadding;
@@ -124,6 +129,8 @@
             mShippingAddressSection = shippingAddressSection;
             mTermsSection = termsSection;
             mTermsAsCheckboxSection = termsAsCheckboxSection;
+            mPrependedSections = prependedSections;
+            mAppendedSections = appendedSections;
             mDividerTag = dividerTag;
             mActivity = activity;
         }
@@ -221,6 +228,12 @@
                             : null);
             view.mDateRangeStartSection.setDelegate(dateStartDelegate);
             view.mDateRangeEndSection.setDelegate(dateEndDelegate);
+            view.mPrependedSections.setDelegate(collectUserDataDelegate != null
+                            ? collectUserDataDelegate::onKeyValueChanged
+                            : null);
+            view.mAppendedSections.setDelegate(collectUserDataDelegate != null
+                            ? collectUserDataDelegate::onKeyValueChanged
+                            : null);
         } else if (propertyKey == AssistantCollectUserDataModel.SUPPORTED_BASIC_CARD_NETWORKS) {
             updateAvailablePaymentMethods(model);
         } else if (propertyKey == AssistantCollectUserDataModel.SUPPORTED_PAYMENT_METHODS) {
@@ -308,6 +321,14 @@
             view.mDateRangeEndSection.setDateChoiceOptions(
                     model.get(AssistantCollectUserDataModel.DATE_RANGE_END));
             return true;
+        } else if (propertyKey == AssistantCollectUserDataModel.PREPENDED_SECTIONS) {
+            view.mPrependedSections.setSections(
+                    model.get(AssistantCollectUserDataModel.PREPENDED_SECTIONS));
+            return true;
+        } else if (propertyKey == AssistantCollectUserDataModel.APPENDED_SECTIONS) {
+            view.mAppendedSections.setSections(
+                    model.get(AssistantCollectUserDataModel.APPENDED_SECTIONS));
+            return true;
         }
 
         return false;
@@ -450,13 +471,33 @@
                 && (propertyKey != AssistantCollectUserDataModel.REQUEST_PAYMENT)
                 && (propertyKey != AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE)
                 && (propertyKey != AssistantCollectUserDataModel.REQUEST_DATE_RANGE)
-                && (propertyKey != AssistantCollectUserDataModel.EXPANDED_SECTION)) {
+                && (propertyKey != AssistantCollectUserDataModel.EXPANDED_SECTION)
+                && (propertyKey != AssistantCollectUserDataModel.PREPENDED_SECTIONS)
+                && (propertyKey != AssistantCollectUserDataModel.APPENDED_SECTIONS)) {
             return false;
         }
 
         // Update section paddings such that the first and last section are flush to the top/bottom,
         // and all other sections have the same amount of padding in-between them.
-        if (model.get(AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE)) {
+
+        if (!model.get(AssistantCollectUserDataModel.PREPENDED_SECTIONS).isEmpty()) {
+            view.mPrependedSections.setPaddings(
+                    0, view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mLoginSection.setPaddings(
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mContactDetailsSection.setPaddings(
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mDateRangeStartSection.setPaddings(
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mDateRangeEndSection.setPaddings(
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mPaymentMethodSection.setPaddings(
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mShippingAddressSection.setPaddings(
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mAppendedSections.setPaddings(view.mSectionToSectionPadding,
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+        } else if (model.get(AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE)) {
             view.mLoginSection.setPaddings(0, view.mSectionToSectionPadding);
             view.mContactDetailsSection.setPaddings(
                     view.mSectionToSectionPadding, view.mSectionToSectionPadding);
@@ -468,6 +509,8 @@
                     view.mSectionToSectionPadding, view.mSectionToSectionPadding);
             view.mShippingAddressSection.setPaddings(
                     view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mAppendedSections.setPaddings(view.mSectionToSectionPadding,
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
         } else if (shouldShowContactDetails(model)) {
             view.mContactDetailsSection.setPaddings(0, view.mSectionToSectionPadding);
             view.mDateRangeStartSection.setPaddings(
@@ -478,6 +521,8 @@
                     view.mSectionToSectionPadding, view.mSectionToSectionPadding);
             view.mShippingAddressSection.setPaddings(
                     view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mAppendedSections.setPaddings(view.mSectionToSectionPadding,
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
         } else if (model.get(AssistantCollectUserDataModel.REQUEST_DATE_RANGE)) {
             view.mDateRangeStartSection.setPaddings(0, view.mSectionToSectionPadding);
             view.mDateRangeEndSection.setPaddings(
@@ -486,12 +531,21 @@
                     view.mSectionToSectionPadding, view.mSectionToSectionPadding);
             view.mShippingAddressSection.setPaddings(
                     view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mAppendedSections.setPaddings(view.mSectionToSectionPadding,
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
         } else if (model.get(AssistantCollectUserDataModel.REQUEST_PAYMENT)) {
             view.mPaymentMethodSection.setPaddings(0, view.mSectionToSectionPadding);
             view.mShippingAddressSection.setPaddings(
                     view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+            view.mAppendedSections.setPaddings(view.mSectionToSectionPadding,
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
         } else if (model.get(AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS)) {
             view.mShippingAddressSection.setPaddings(0, view.mSectionToSectionPadding);
+            view.mAppendedSections.setPaddings(view.mSectionToSectionPadding,
+                    view.mSectionToSectionPadding, view.mSectionToSectionPadding);
+        } else if (!model.get(AssistantCollectUserDataModel.APPENDED_SECTIONS).isEmpty()) {
+            view.mAppendedSections.setPaddings(
+                    0, view.mSectionToSectionPadding, view.mSectionToSectionPadding);
         }
         view.mTermsSection.setPaddings(view.mSectionToSectionPadding, 0);
         view.mTermsAsCheckboxSection.setPaddings(view.mSectionToSectionPadding, 0);
@@ -505,6 +559,8 @@
                         || child.getVisibility() != View.VISIBLE;
             } else if (child.getTag() == view.mDividerTag) {
                 child.setVisibility(prevSectionIsExpandedOrInvisible ? View.GONE : View.VISIBLE);
+            } else {
+                prevSectionIsExpandedOrInvisible = false;
             }
         }
         return true;
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataCoordinator.java
index f8083def..ca3a28a 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataCoordinator.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataCoordinator.java
@@ -14,6 +14,7 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.autofill_assistant.R;
 import org.chromium.chrome.browser.autofill_assistant.AssistantTagsForTesting;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantAdditionalSectionContainer;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
 
 import java.text.DateFormat;
@@ -72,6 +73,9 @@
                 new LinearLayout.LayoutParams(
                         ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
 
+        AssistantAdditionalSectionContainer prependedSections =
+                new AssistantAdditionalSectionContainer(mActivity, paymentRequestExpanderAccordion);
+
         AssistantLoginSection loginSection =
                 new AssistantLoginSection(mActivity, paymentRequestExpanderAccordion);
         createSeparator(paymentRequestExpanderAccordion);
@@ -92,6 +96,10 @@
         AssistantShippingAddressSection shippingAddressSection =
                 new AssistantShippingAddressSection(mActivity, paymentRequestExpanderAccordion);
         createSeparator(paymentRequestExpanderAccordion);
+
+        AssistantAdditionalSectionContainer appendedSections =
+                new AssistantAdditionalSectionContainer(mActivity, paymentRequestExpanderAccordion);
+
         AssistantTermsSection termsSection = new AssistantTermsSection(
                 mActivity, paymentRequestExpanderAccordion, /* showAsSingleCheckbox= */ false);
         AssistantTermsSection termsAsCheckboxSection =
@@ -117,7 +125,7 @@
                 paymentRequestExpanderAccordion, sectionToSectionPadding, loginSection,
                 contactDetailsSection, dateRangeStartSection, dateRangeEndSection,
                 paymentMethodSection, shippingAddressSection, termsSection, termsAsCheckboxSection,
-                DIVIDER_TAG, activity);
+                prependedSections, appendedSections, DIVIDER_TAG, activity);
         AssistantCollectUserDataBinder binder = new AssistantCollectUserDataBinder();
         PropertyModelChangeProcessor.create(model, mViewHolder, binder);
 
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataDelegate.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataDelegate.java
index 8563147..b0dbf50 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataDelegate.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataDelegate.java
@@ -41,4 +41,7 @@
 
     /** The end of the date/time range has changed. */
     void onDateTimeRangeEndChanged(int year, int month, int day, int hour, int minute, int second);
+
+    /** The value of a key/value pair has changed. */
+    void onKeyValueChanged(String key, String value);
 }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataModel.java
index c0fb75b..7eaa1fb 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataModel.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataModel.java
@@ -7,6 +7,11 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantAdditionalSectionFactory;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantStaticTextSection;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputSection;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputSection.TextInputFactory;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputType;
 import org.chromium.chrome.browser.payments.AutofillAddress;
 import org.chromium.chrome.browser.payments.AutofillContact;
 import org.chromium.chrome.browser.payments.AutofillPaymentInstrument;
@@ -119,6 +124,12 @@
     public static final WritableObjectPropertyKey<String> DATE_RANGE_END_LABEL =
             new WritableObjectPropertyKey<>();
 
+    public static final WritableObjectPropertyKey<List<AssistantAdditionalSectionFactory>>
+            PREPENDED_SECTIONS = new WritableObjectPropertyKey<>();
+
+    public static final WritableObjectPropertyKey<List<AssistantAdditionalSectionFactory>>
+            APPENDED_SECTIONS = new WritableObjectPropertyKey<>();
+
     public AssistantCollectUserDataModel() {
         super(DELEGATE, WEB_CONTENTS, VISIBLE, SHIPPING_ADDRESS, PAYMENT_METHOD, CONTACT_DETAILS,
                 LOGIN_SECTION_TITLE, SELECTED_LOGIN, TERMS_STATUS, DEFAULT_EMAIL, REQUEST_NAME,
@@ -128,7 +139,7 @@
                 SUPPORTED_BASIC_CARD_NETWORKS, SUPPORTED_PAYMENT_METHODS, AVAILABLE_LOGINS,
                 EXPANDED_SECTION, REQUIRE_BILLING_POSTAL_CODE, BILLING_POSTAL_CODE_MISSING_TEXT,
                 REQUEST_DATE_RANGE, DATE_RANGE_START, DATE_RANGE_START_LABEL, DATE_RANGE_END,
-                DATE_RANGE_END_LABEL);
+                DATE_RANGE_END_LABEL, PREPENDED_SECTIONS, APPENDED_SECTIONS);
 
         /**
          * Set initial state for basic type properties (others are implicitly null).
@@ -146,6 +157,8 @@
         set(DEFAULT_EMAIL, "");
         set(DATE_RANGE_START_LABEL, "");
         set(DATE_RANGE_END_LABEL, "");
+        set(PREPENDED_SECTIONS, new ArrayList<>());
+        set(APPENDED_SECTIONS, new ArrayList<>());
     }
 
     @CalledByNative
@@ -286,4 +299,44 @@
     private void setDateTimeRangeEndLabel(String label) {
         set(DATE_RANGE_END_LABEL, label);
     }
+
+    @CalledByNative
+    private static List<AssistantAdditionalSectionFactory> createAdditionalSectionsList() {
+        return new ArrayList<>();
+    }
+
+    @CalledByNative
+    private static void appendStaticTextSection(
+            List<AssistantAdditionalSectionFactory> sections, String title, String text) {
+        sections.add(new AssistantStaticTextSection.Factory(title, text));
+    }
+
+    @CalledByNative
+    private static void appendTextInputSection(List<AssistantAdditionalSectionFactory> sections,
+            String title, List<TextInputFactory> inputs) {
+        sections.add(new AssistantTextInputSection.Factory(title, inputs));
+    }
+
+    @CalledByNative
+    private static List<TextInputFactory> createTextInputList() {
+        return new ArrayList<>();
+    }
+
+    @CalledByNative
+    private static void appendTextInput(List<TextInputFactory> inputs,
+            @AssistantTextInputType int type, String hint, String value, String key) {
+        inputs.add(new TextInputFactory(type, hint, value, key));
+    }
+
+    /** Configures the list of prepended sections. */
+    @CalledByNative
+    private void setPrependedSections(List<AssistantAdditionalSectionFactory> sections) {
+        set(PREPENDED_SECTIONS, sections);
+    }
+
+    /** Configures the list of appended sections. */
+    @CalledByNative
+    private void setAppendedSections(List<AssistantAdditionalSectionFactory> sections) {
+        set(APPENDED_SECTIONS, sections);
+    }
 }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataNativeDelegate.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataNativeDelegate.java
index e2c83f5..08e6cfb 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataNativeDelegate.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataNativeDelegate.java
@@ -118,6 +118,15 @@
         }
     }
 
+    @Override
+    public void onKeyValueChanged(String key, String value) {
+        if (mNativeAssistantCollectUserDataDelegate != 0) {
+            AssistantCollectUserDataNativeDelegateJni.get().onKeyValueChanged(
+                    mNativeAssistantCollectUserDataDelegate,
+                    AssistantCollectUserDataNativeDelegate.this, key, value);
+        }
+    }
+
     @CalledByNative
     private void clearNativePtr() {
         mNativeAssistantCollectUserDataDelegate = 0;
@@ -146,5 +155,7 @@
         void onDateTimeRangeEndChanged(long nativeAssistantCollectUserDataDelegate,
                 AssistantCollectUserDataNativeDelegate caller, int year, int month, int day,
                 int hour, int minute, int second);
+        void onKeyValueChanged(long nativeAssistantCollectUserDataDelegate,
+                AssistantCollectUserDataNativeDelegate caller, String key, String value);
     }
 }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSection.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSection.java
new file mode 100644
index 0000000..c23d1e6
--- /dev/null
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSection.java
@@ -0,0 +1,24 @@
+// 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.chrome.browser.autofill_assistant.user_data.additional_sections;
+
+import android.view.View;
+
+/** Interface for an additional section of the user data form. */
+public interface AssistantAdditionalSection {
+    /** Delegate interface for generic key/value widgets. */
+    interface Delegate {
+        void onValueChanged(String key, String value);
+    }
+
+    /** Returns the root view of the section. */
+    View getView();
+
+    /** Sets the padding for the top-most and the bottom-most view, respectively. */
+    void setPaddings(int topPadding, int bottomPadding);
+
+    /** Sets the delegate to notify for changes. */
+    void setDelegate(Delegate delegate);
+}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSectionContainer.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSectionContainer.java
new file mode 100644
index 0000000..fe61e9a
--- /dev/null
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSectionContainer.java
@@ -0,0 +1,92 @@
+// 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.chrome.browser.autofill_assistant.user_data.additional_sections;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Space;
+
+import org.chromium.chrome.autofill_assistant.R;
+import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantCollectUserDataCoordinator;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantAdditionalSection.Delegate;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/** A container for additional sections of the user data form. */
+public class AssistantAdditionalSectionContainer {
+    private final Context mContext;
+    private final ViewGroup mParent;
+    private final View mPlaceholderView;
+    private final List<AssistantAdditionalSection> mSections = new ArrayList<>();
+    private final List<View> mDividers = new ArrayList<>();
+    private Delegate mDelegate;
+
+    public AssistantAdditionalSectionContainer(Context context, ViewGroup parent) {
+        mContext = context;
+        mParent = parent;
+        mPlaceholderView = new Space(context, null);
+        parent.addView(mPlaceholderView);
+    }
+
+    public void setSections(List<AssistantAdditionalSectionFactory> sections) {
+        for (AssistantAdditionalSection section : mSections) {
+            mParent.removeView(section.getView());
+        }
+        for (View divider : mDividers) {
+            mParent.removeView(divider);
+        }
+
+        mSections.clear();
+        int index = mParent.indexOfChild(mPlaceholderView);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        for (int i = sections.size() - 1; i >= 0; i--) {
+            View divider = inflater.inflate(
+                    R.layout.autofill_assistant_payment_request_section_divider, mParent, false);
+            divider.setTag(AssistantCollectUserDataCoordinator.DIVIDER_TAG);
+            mParent.addView(divider, index);
+            AssistantAdditionalSection section =
+                    sections.get(i).createSection(mContext, mParent, index, mDelegate);
+            section.setDelegate(mDelegate);
+            mSections.add(section);
+        }
+        Collections.reverse(mSections);
+    }
+
+    /**
+     * Sets the paddings for all contained sections.
+     *
+     * @param topPadding padding for the top-most view in this container.
+     * @param sectionPadding inter-section padding, i.e., padding between one section and the next
+     *         divider, in either direction.
+     * @param bottomPadding padding for the bottom-most view in this container.
+     */
+    public void setPaddings(int topPadding, int sectionPadding, int bottomPadding) {
+        if (mSections.isEmpty()) {
+            return;
+        }
+
+        if (mSections.size() == 1) {
+            mSections.get(0).setPaddings(topPadding, bottomPadding);
+            return;
+        }
+
+        mSections.get(0).setPaddings(topPadding, sectionPadding);
+        mSections.get(mSections.size() - 1).setPaddings(sectionPadding, bottomPadding);
+        for (int i = 1; i < mSections.size() - 1; i++) {
+            mSections.get(i).setPaddings(sectionPadding, sectionPadding);
+        }
+    }
+
+    public void setDelegate(Delegate delegate) {
+        mDelegate = delegate;
+        for (AssistantAdditionalSection section : mSections) {
+            section.setDelegate(mDelegate);
+        }
+    }
+}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSectionFactory.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSectionFactory.java
new file mode 100644
index 0000000..4a7d138
--- /dev/null
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantAdditionalSectionFactory.java
@@ -0,0 +1,19 @@
+// 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.chrome.browser.autofill_assistant.user_data.additional_sections;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.view.ViewGroup;
+
+/** Interface for factories of additional user form sections. */
+public interface AssistantAdditionalSectionFactory {
+    /**
+     * Instantiates the additional section for {@code context} and adds it at position {@code
+     * index} to {@code parent}.
+     */
+    AssistantAdditionalSection createSection(Context context, ViewGroup parent, int index,
+            @Nullable AssistantAdditionalSection.Delegate delegate);
+}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantStaticTextSection.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantStaticTextSection.java
new file mode 100644
index 0000000..b0025910
--- /dev/null
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantStaticTextSection.java
@@ -0,0 +1,77 @@
+// 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.chrome.browser.autofill_assistant.user_data.additional_sections;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.chromium.chrome.autofill_assistant.R;
+import org.chromium.chrome.browser.autofill_assistant.AssistantTextUtils;
+
+/** A section which displays a simple static text message. */
+public class AssistantStaticTextSection implements AssistantAdditionalSection {
+    private final LinearLayout mRootLayout;
+    private final int mTitleToContentPadding;
+
+    /** Factory for instantiating instances of {code AssistantStaticTextSection}. */
+    public static class Factory implements AssistantAdditionalSectionFactory {
+        private final String mTitle;
+        private final String mMessage;
+        public Factory(String title, String message) {
+            mTitle = title;
+            mMessage = message;
+        }
+
+        @Override
+        public AssistantStaticTextSection createSection(
+                Context context, ViewGroup parent, int index, Delegate delegate) {
+            return new AssistantStaticTextSection(context, parent, index, mTitle, mMessage);
+        }
+    }
+
+    AssistantStaticTextSection(
+            Context context, ViewGroup parent, int index, String title, String message) {
+        mTitleToContentPadding = context.getResources().getDimensionPixelSize(
+                R.dimen.autofill_assistant_payment_request_title_padding);
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        mRootLayout = (LinearLayout) inflater.inflate(
+                R.layout.autofill_assistant_static_text_section, null);
+
+        TextView titleView = mRootLayout.findViewById(R.id.section_title);
+        AssistantTextUtils.applyVisualAppearanceTags(titleView, title, null);
+
+        TextView messageView = mRootLayout.findViewById(R.id.text);
+        AssistantTextUtils.applyVisualAppearanceTags(messageView, message, null);
+
+        parent.addView(mRootLayout, index,
+                new ViewGroup.LayoutParams(
+                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+    }
+
+    @Override
+    public View getView() {
+        return mRootLayout;
+    }
+
+    @Override
+    public void setPaddings(int topPadding, int bottomPadding) {
+        View titleView = mRootLayout.findViewById(R.id.section_title);
+        titleView.setPadding(titleView.getPaddingLeft(), topPadding, titleView.getPaddingRight(),
+                mTitleToContentPadding);
+        TextView messageView = mRootLayout.findViewById(R.id.text);
+        messageView.setPadding(messageView.getPaddingLeft(), messageView.getPaddingTop(),
+                messageView.getPaddingRight(), bottomPadding);
+    }
+
+    @Override
+    public void setDelegate(Delegate delegate) {
+        // Nothing to do.
+    }
+}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantTextInputSection.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantTextInputSection.java
new file mode 100644
index 0000000..3029889
--- /dev/null
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantTextInputSection.java
@@ -0,0 +1,191 @@
+// 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.chrome.browser.autofill_assistant.user_data.additional_sections;
+
+import static org.chromium.chrome.browser.widget.prefeditor.EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.support.v4.util.Pair;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.Space;
+import android.widget.TextView;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.Callback;
+import org.chromium.chrome.autofill_assistant.R;
+import org.chromium.chrome.browser.autofill_assistant.AssistantTextUtils;
+import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantVerticalExpander;
+import org.chromium.chrome.browser.widget.prefeditor.EditorFieldModel;
+import org.chromium.chrome.browser.widget.prefeditor.EditorTextField;
+
+import java.util.List;
+
+/** A section which displays one or multiple text inputs for the user to type in. */
+public class AssistantTextInputSection implements AssistantAdditionalSection {
+    private final AssistantVerticalExpander mSectionExpander;
+    private final ViewGroup mInputContainer;
+    private final Context mContext;
+    private Delegate mDelegate;
+    private int mTopPadding;
+    private int mBottomPadding;
+
+    /** Factory for a single text input field. */
+    public static class TextInputFactory {
+        private final @AssistantTextInputType int mType;
+        private final String mHint;
+        private final String mValue;
+        private final String mKey;
+
+        public TextInputFactory(
+                @AssistantTextInputType int type, String hint, String value, String key) {
+            mType = type;
+            mHint = hint;
+            mValue = value;
+            mKey = key;
+        }
+
+        View createView(Context context, Callback<Pair<String, String>> changedCallback) {
+            TextWatcher textWatcher = new TextWatcher() {
+                @Override
+                public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+                @Override
+                public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+                @Override
+                public void afterTextChanged(Editable s) {
+                    changedCallback.onResult(new Pair<>(mKey, s.toString()));
+                }
+            };
+            int typeHint = 0; /** == INPUT_TYPE_HINT_NONE */
+            switch (mType) {
+                case AssistantTextInputType.INPUT_TEXT:
+                    break;
+                case AssistantTextInputType.INPUT_ALPHANUMERIC:
+                    typeHint = INPUT_TYPE_HINT_ALPHA_NUMERIC;
+                    break;
+            }
+            return new EditorTextField(context,
+                    EditorFieldModel.createTextInput(typeHint, mHint, /* suggestions = */ null,
+                            /* formatter = */ null, /* validator = */ null,
+                            /* valueIconGenerator = */ null, /* requiredErrorMessage = */ null,
+                            /* invalidErrorMessage = */ null, mValue),
+                    (v, actionId, event)
+                            -> false,
+                    /* filter = */ null, textWatcher, /* observer = */ null);
+        }
+    }
+
+    /** Factory for instantiating instances of {code AssistantTextInputSection}. */
+    public static class Factory implements AssistantAdditionalSectionFactory {
+        private final String mTitle;
+        private final List<TextInputFactory> mInputs;
+        public Factory(String title, List<TextInputFactory> inputs) {
+            mTitle = title;
+            mInputs = inputs;
+        }
+
+        @Override
+        public AssistantTextInputSection createSection(
+                Context context, ViewGroup parent, int index, Delegate delegate) {
+            return new AssistantTextInputSection(context, parent, index, mTitle, mInputs, delegate);
+        }
+    }
+
+    AssistantTextInputSection(Context context, ViewGroup parent, int index, String title,
+            List<TextInputFactory> inputs, @Nullable Delegate delegate) {
+        mContext = context;
+        mDelegate = delegate;
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        mSectionExpander = new AssistantVerticalExpander(context, null);
+        View sectionTitle =
+                inflater.inflate(R.layout.autofill_assistant_payment_request_section_title, null);
+        sectionTitle.findViewById(R.id.section_title_add_button).setVisibility(View.GONE);
+        TextView titleView = sectionTitle.findViewById(R.id.section_title);
+        AssistantTextUtils.applyVisualAppearanceTags(titleView, title, null);
+
+        mInputContainer = createInputContainer();
+        int horizontalMargin = context.getResources().getDimensionPixelSize(
+                R.dimen.autofill_assistant_bottombar_horizontal_spacing);
+        for (TextInputFactory input : inputs) {
+            View inputView = input.createView(context, result -> {
+                if (mDelegate == null) {
+                    return;
+                }
+                mDelegate.onValueChanged(result.first, result.second);
+            });
+            mInputContainer.addView(inputView);
+            setHorizontalMargins(inputView, horizontalMargin, horizontalMargin);
+        }
+        mSectionExpander.setExpandedView(mInputContainer,
+                new LinearLayout.LayoutParams(
+                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+        mSectionExpander.setCollapsedView(
+                new Space(context, null), new ViewGroup.LayoutParams(0, 0));
+        mSectionExpander.setTitleView(sectionTitle,
+                new LinearLayout.LayoutParams(
+                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+        // Adjust margins such that title is indented, but expanded view is full-width.
+        setHorizontalMargins(sectionTitle, horizontalMargin, horizontalMargin);
+        setHorizontalMargins(mSectionExpander.getChevronButton(), 0, horizontalMargin);
+
+        parent.addView(mSectionExpander, index,
+                new ViewGroup.LayoutParams(
+                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+    }
+
+    @Override
+    public View getView() {
+        return mSectionExpander;
+    }
+
+    @Override
+    public void setPaddings(int topPadding, int bottomPadding) {
+        mTopPadding = topPadding;
+        mBottomPadding = bottomPadding;
+        updatePaddings();
+    }
+
+    @Override
+    public void setDelegate(Delegate delegate) {
+        mDelegate = delegate;
+    }
+
+    private void setHorizontalMargins(View view, int marginStart, int marginEnd) {
+        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
+        lp.setMarginStart(marginStart);
+        lp.setMarginEnd(marginEnd);
+        view.setLayoutParams(lp);
+    }
+
+    private void updatePaddings() {
+        View titleView = mSectionExpander.getTitleView();
+        if (mSectionExpander.isExpanded()) {
+            // Section is expanded, i.e., the expanded widget is the bottom-most widget.
+            titleView.setPadding(titleView.getPaddingLeft(), mTopPadding,
+                    titleView.getPaddingRight(), titleView.getPaddingBottom());
+        } else {
+            // Section is collapsed -> title is both top-most and bottom-most widget.
+            titleView.setPadding(titleView.getPaddingLeft(), mTopPadding,
+                    titleView.getPaddingRight(), mBottomPadding);
+        }
+    }
+
+    private ViewGroup createInputContainer() {
+        LinearLayout inputContainer = new LinearLayout(mContext, null);
+        inputContainer.setOrientation(LinearLayout.VERTICAL);
+        inputContainer.setBackgroundColor(ApiCompatibilityUtils.getColor(
+                mContext.getResources(), R.color.payments_section_edit_background));
+        return inputContainer;
+    }
+}
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataTestHelper.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataTestHelper.java
index 6a2516d..a9afb74 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataTestHelper.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataTestHelper.java
@@ -30,7 +30,9 @@
 import org.chromium.chrome.browser.payments.AutofillPaymentInstrument;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.TimeoutException;
 
 /**
@@ -102,6 +104,7 @@
         int mTermsStatus;
         @Nullable
         Integer mLastLinkClicked;
+        Map<String, String> mAdditionalValues = new HashMap<>();
 
         @Override
         public void onContactInfoChanged(@Nullable AutofillContact contact) {
@@ -144,6 +147,11 @@
                 int year, int month, int day, int hour, int minute, int second) {
             mDateRangeEnd = new AssistantDateTime(year, month, day, hour, minute, second);
         }
+
+        @Override
+        public void onKeyValueChanged(String key, String value) {
+            mAdditionalValues.put(key, value);
+        }
     }
 
     public AutofillAssistantCollectUserDataTestHelper() throws TimeoutException {
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java
index b5ba66f4..bd8f2ec 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java
@@ -6,6 +6,9 @@
 
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.action.ViewActions.replaceText;
+import static android.support.test.espresso.assertion.PositionAssertions.isAbove;
+import static android.support.test.espresso.assertion.PositionAssertions.isBelow;
 import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
 import static android.support.test.espresso.contrib.PickerActions.setDate;
@@ -13,11 +16,13 @@
 import static android.support.test.espresso.matcher.RootMatchers.isDialog;
 import static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA;
 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
 import static android.support.test.espresso.matcher.ViewMatchers.withId;
 import static android.support.test.espresso.matcher.ViewMatchers.withTagValue;
 import static android.support.test.espresso.matcher.ViewMatchers.withText;
 
 import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.nullValue;
@@ -50,13 +55,20 @@
 import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantDateTime;
 import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantLoginChoice;
 import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantTermsAndConditionsState;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantAdditionalSectionFactory;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantStaticTextSection;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputSection;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputSection.TextInputFactory;
+import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantTextInputType;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Locale;
 
 /**
@@ -131,6 +143,8 @@
         assertThat(model.get(AssistantCollectUserDataModel.TERMS_STATUS),
                 is(AssistantTermsAndConditionsState.NOT_SELECTED));
         assertThat(model.get(AssistantCollectUserDataModel.SELECTED_LOGIN), nullValue());
+        assertThat(model.get(AssistantCollectUserDataModel.APPENDED_SECTIONS), empty());
+        assertThat(model.get(AssistantCollectUserDataModel.PREPENDED_SECTIONS), empty());
 
         /* Test initial UI state. */
         AutofillAssistantCollectUserDataTestHelper
@@ -226,6 +240,26 @@
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE, true));
         onView(is(viewHolder.mLoginsSection)).check(matches(isDisplayed()));
+
+        /* Prepended section visibility test. */
+        List<AssistantAdditionalSectionFactory> prependedSections = new ArrayList<>();
+        prependedSections.add(
+                new AssistantStaticTextSection.Factory("Prepended section", "Lorem ipsum."));
+        TestThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> model.set(AssistantCollectUserDataModel.PREPENDED_SECTIONS,
+                                prependedSections));
+        /* Login section is top-most regular section. */
+        onView(withText("Prepended section")).check(isAbove(is(viewHolder.mLoginsSection)));
+
+        /* Appended section visibility test. */
+        List<AssistantAdditionalSectionFactory> appendedSections = new ArrayList<>();
+        appendedSections.add(
+                new AssistantStaticTextSection.Factory("Appended section", "Lorem ipsum."));
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> model.set(AssistantCollectUserDataModel.APPENDED_SECTIONS, appendedSections));
+        /* Shipping address is bottom-most regular section. */
+        onView(withText("Appended section")).check(isBelow(is(viewHolder.mShippingSection)));
     }
 
     /**
@@ -266,8 +300,8 @@
         onView(allOf(withId(R.id.section_title_add_button),
                        isDescendantOfA(is(viewHolder.mShippingSection))))
                 .check(matches(isDisplayed()));
-        /* ... Except for the logins and date/time section, which currently does not support adding
-         * items.*/
+        /* ... Except for logins, date/time and additional sections, which currently do not support
+         * adding items.*/
         onView(allOf(withId(R.id.section_title_add_button),
                        isDescendantOfA(is(viewHolder.mLoginsSection))))
                 .check(matches(not(isDisplayed())));
@@ -956,6 +990,79 @@
                 delegate.mDateRangeEnd.getTimeInUtcMillis(), is(newEndTime.getTimeInUtcMillis()));
     }
 
+    @Test
+    @MediumTest
+    public void testAdditionalStaticSections() throws Exception {
+        AssistantCollectUserDataModel model = new AssistantCollectUserDataModel();
+        AssistantCollectUserDataCoordinator coordinator = createCollectUserDataCoordinator(model);
+
+        List<AssistantAdditionalSectionFactory> prependedSections = new ArrayList<>();
+        prependedSections.add(
+                new AssistantStaticTextSection.Factory("Prepended section 1", "Lorem ipsum."));
+        prependedSections.add(
+                new AssistantStaticTextSection.Factory("Prepended section 2", "Lorem ipsum."));
+
+        List<AssistantAdditionalSectionFactory> appendedSections = new ArrayList<>();
+        appendedSections.add(
+                new AssistantStaticTextSection.Factory("Appended section 1", "Lorem ipsum."));
+        appendedSections.add(
+                new AssistantStaticTextSection.Factory("Appended section 2", "Lorem ipsum."));
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            model.set(AssistantCollectUserDataModel.PREPENDED_SECTIONS, prependedSections);
+            model.set(AssistantCollectUserDataModel.APPENDED_SECTIONS, appendedSections);
+            model.set(AssistantCollectUserDataModel.VISIBLE, true);
+        });
+
+        onView(withText("Prepended section 1")).check(matches(isDisplayed()));
+        onView(withText("Prepended section 2")).check(matches(isDisplayed()));
+        onView(withText("Appended section 1")).check(matches(isDisplayed()));
+        onView(withText("Appended section 2")).check(matches(isDisplayed()));
+
+        onView(withText("Prepended section 1")).check(isAbove(withText("Prepended section 2")));
+        onView(withText("Prepended section 2")).check(isAbove(withText("Appended section 1")));
+        onView(withText("Appended section 1")).check(isAbove(withText("Appended section 2")));
+    }
+
+    @Test
+    @MediumTest
+    public void testAdditionalTextInputSections() throws Exception {
+        AssistantCollectUserDataModel model = new AssistantCollectUserDataModel();
+        AssistantCollectUserDataCoordinator coordinator = createCollectUserDataCoordinator(model);
+        AutofillAssistantCollectUserDataTestHelper.MockDelegate delegate =
+                new AutofillAssistantCollectUserDataTestHelper.MockDelegate();
+
+        List<AssistantAdditionalSectionFactory> prependedSections = new ArrayList<>();
+        List<AssistantTextInputSection.TextInputFactory> textInputs = new ArrayList<>();
+        textInputs.add(new TextInputFactory(AssistantTextInputType.INPUT_ALPHANUMERIC,
+                "Discount code", "123456789", "discount"));
+        textInputs.add(new TextInputFactory(
+                AssistantTextInputType.INPUT_ALPHANUMERIC, "Loyalty code", "", "loyalty"));
+        textInputs.add(
+                new TextInputFactory(AssistantTextInputType.INPUT_TEXT, "Comment", "", "comment"));
+        prependedSections.add(
+                new AssistantTextInputSection.Factory("Discount codes title", textInputs));
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            model.set(AssistantCollectUserDataModel.DELEGATE, delegate);
+            model.set(AssistantCollectUserDataModel.PREPENDED_SECTIONS, prependedSections);
+            model.set(AssistantCollectUserDataModel.VISIBLE, true);
+        });
+
+        // Expand section
+        onView(withText("Discount codes title")).perform(click());
+
+        onView(withContentDescription("Discount code")).check(matches(isDisplayed()));
+        onView(withContentDescription("Loyalty code")).check(matches(isDisplayed()));
+        assertThat(delegate.mAdditionalValues.get("discount"), is("123456789"));
+        assertThat(delegate.mAdditionalValues.get("loyalty"), is(""));
+
+        onView(withContentDescription("Discount code")).perform(replaceText("D-742394"));
+        onView(withContentDescription("Loyalty code")).perform(replaceText("L-394834"));
+        assertThat(delegate.mAdditionalValues.get("discount"), is("D-742394"));
+        assertThat(delegate.mAdditionalValues.get("loyalty"), is("L-394834"));
+    }
+
     private View getPaymentSummaryErrorView(ViewHolder viewHolder) {
         return viewHolder.mPaymentSection.findViewById(R.id.payment_method_summary)
                 .findViewById(R.id.incomplete_error);
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTextUtilsTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTextUtilsTest.java
new file mode 100644
index 0000000..26fe6af
--- /dev/null
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTextUtilsTest.java
@@ -0,0 +1,128 @@
+// 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.chrome.browser.autofill_assistant;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.assertThat;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static org.hamcrest.Matchers.is;
+
+import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.openTextLink;
+import static org.chromium.content_public.browser.test.util.TestThreadUtils.runOnUiThreadBlocking;
+
+import android.graphics.Typeface;
+import android.support.test.filters.MediumTest;
+import android.text.SpannedString;
+import android.text.style.StyleSpan;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.Callback;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+
+/** Tests for {@code AssistantTextUtils}. */
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@RunWith(ChromeJUnit4ClassRunner.class)
+public class AutofillAssistantTextUtilsTest {
+    private LinearLayout mTestLayout;
+
+    @Rule
+    public CustomTabActivityTestRule mTestRule = new CustomTabActivityTestRule();
+
+    @Before
+    public void setUp() {
+        AutofillAssistantUiTestUtil.startOnBlankPage(mTestRule);
+        runOnUiThreadBlocking(() -> {
+            mTestLayout = new LinearLayout(mTestRule.getActivity());
+            mTestLayout.setOrientation(LinearLayout.VERTICAL);
+            AutofillAssistantUiTestUtil.attachToCoordinator(mTestRule.getActivity(), mTestLayout);
+        });
+    }
+
+    @Test
+    @MediumTest
+    public void testTextStyles() throws Exception {
+        TextView regularTextView = runOnUiThreadBlocking(() -> {
+            TextView view = new TextView(mTestRule.getActivity());
+            mTestLayout.addView(view);
+            AssistantTextUtils.applyVisualAppearanceTags(view, "Regular text", null);
+            StyleSpan[] spans =
+                    ((SpannedString) view.getText()).getSpans(0, view.length(), StyleSpan.class);
+            assertThat(spans.length, is(0));
+            return view;
+        });
+        onView(is(regularTextView)).check(matches(withText("Regular text")));
+
+        TextView boldTextView = runOnUiThreadBlocking(() -> {
+            TextView view = new TextView(mTestRule.getActivity());
+            mTestLayout.addView(view);
+            AssistantTextUtils.applyVisualAppearanceTags(view, "<b>Bold text</b>", null);
+            StyleSpan[] spans =
+                    ((SpannedString) view.getText()).getSpans(0, view.length(), StyleSpan.class);
+            assertThat(spans.length, is(1));
+            assertThat(spans[0].getStyle(), is(Typeface.BOLD));
+            return view;
+        });
+        onView(is(boldTextView)).check(matches(withText("Bold text")));
+
+        TextView italicTextView = runOnUiThreadBlocking(() -> {
+            TextView view = new TextView(mTestRule.getActivity());
+            mTestLayout.addView(view);
+            AssistantTextUtils.applyVisualAppearanceTags(view, "<i>Italic text</i>", null);
+            StyleSpan[] spans =
+                    ((SpannedString) view.getText()).getSpans(0, view.length(), StyleSpan.class);
+            assertThat(spans.length, is(1));
+            assertThat(spans[0].getStyle(), is(Typeface.ITALIC));
+            return view;
+        });
+        onView(is(italicTextView)).check(matches(withText("Italic text")));
+    }
+
+    @Test
+    @MediumTest
+    public void testTextLinks() throws Exception {
+        /* Simple helper class that keeps track of the most recent callback result. */
+        class LinkCallback implements Callback<Integer> {
+            private int mLastCallback = -1;
+
+            private int getLastCallback() {
+                return mLastCallback;
+            }
+            @Override
+            public void onResult(Integer result) {
+                mLastCallback = result;
+            }
+        }
+
+        LinkCallback linkCallback = new LinkCallback();
+        TextView multiLinkView = runOnUiThreadBlocking(() -> {
+            TextView view = new TextView(mTestRule.getActivity());
+            mTestLayout.addView(view);
+            AssistantTextUtils.applyVisualAppearanceTags(view,
+                    "Click <link1>here</link1> or <link2>there</link2> or "
+                            + "<link3>somewhere else</link3>.",
+                    linkCallback);
+            return view;
+        });
+        onView(is(multiLinkView))
+                .check(matches(withText("Click here or there or somewhere else.")));
+        onView(is(multiLinkView)).perform(openTextLink("here"));
+        assertThat(linkCallback.getLastCallback(), is(1));
+        onView(is(multiLinkView)).perform(openTextLink("somewhere else"));
+        assertThat(linkCallback.getLastCallback(), is(3));
+        onView(is(multiLinkView)).perform(openTextLink("there"));
+        assertThat(linkCallback.getLastCallback(), is(2));
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java
index 4a09dc3..89b282f 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java
@@ -12,6 +12,10 @@
 import android.support.design.widget.CoordinatorLayout;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.text.SpannableString;
+import android.text.style.ClickableSpan;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -22,6 +26,7 @@
 
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
 import org.hamcrest.TypeSafeMatcher;
 
 import org.chromium.base.Callback;
@@ -122,6 +127,41 @@
         };
     }
 
+    public static ViewAction openTextLink(String textLink) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return Matchers.instanceOf(TextView.class);
+            }
+
+            @Override
+            public String getDescription() {
+                return "Opens a textlink of a TextView";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                TextView textView = (TextView) view;
+                SpannableString spannableString = (SpannableString) textView.getText();
+                ClickableSpan[] spans =
+                        spannableString.getSpans(0, spannableString.length(), ClickableSpan.class);
+                for (ClickableSpan span : spans) {
+                    if (textLink.contentEquals(
+                                spannableString.subSequence(spannableString.getSpanStart(span),
+                                        spannableString.getSpanEnd(span)))) {
+                        span.onClick(view);
+                        return;
+                    }
+                }
+
+                throw new NoMatchingViewException.Builder()
+                        .includeViewHierarchy(true)
+                        .withRootView(textView)
+                        .build();
+            }
+        };
+    }
+
     /** Returns all views with a matching tag. */
     public static List<View> findViewsWithTag(View view, Object tag) {
         List<View> viewsWithTag = new ArrayList<>();
diff --git a/chrome/android/java/res_download/layout/download_rename_custom_dialog.xml b/chrome/android/java/res_download/layout/download_rename_custom_dialog.xml
index c6fdcd6..5d830fe8 100644
--- a/chrome/android/java/res_download/layout/download_rename_custom_dialog.xml
+++ b/chrome/android/java/res_download/layout/download_rename_custom_dialog.xml
@@ -37,7 +37,7 @@
             <org.chromium.chrome.browser.ui.widget.text.AlertDialogEditText
                 android:id="@+id/file_name"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
+                android:layout_height="48dp"
                 android:cursorVisible="true"
                 android:singleLine="true" />
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
index 93778f6b..97d3603 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
-import org.chromium.chrome.browser.dom_distiller.DomDistillerServiceFactory;
 import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils;
 import org.chromium.chrome.browser.native_page.NativePageFactory;
 import org.chromium.chrome.browser.ntp.NewTabPage;
@@ -34,7 +33,6 @@
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
-import org.chromium.components.dom_distiller.core.DomDistillerService;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
 import org.chromium.content_public.browser.WebContents;
@@ -148,16 +146,6 @@
         if (mTab.isFrozen()) return buildUrlBarData(url, formattedUrl);
 
         if (DomDistillerUrlUtils.isDistilledPage(url)) {
-            DomDistillerService domDistillerService =
-                    DomDistillerServiceFactory.getForProfile(getProfile());
-            String entryIdFromUrl = DomDistillerUrlUtils.getValueForKeyInUrl(url, "entry_id");
-            if (!TextUtils.isEmpty(entryIdFromUrl)
-                    && domDistillerService.hasEntry(entryIdFromUrl)) {
-                String originalUrl = domDistillerService.getUrlForEntry(entryIdFromUrl);
-                return buildUrlBarData(
-                        DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl));
-            }
-
             String originalUrl = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url);
             if (originalUrl != null) {
                 return buildUrlBarData(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetCardsUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetCardsUiCaptureTest.java
deleted file mode 100644
index d1f15769..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetCardsUiCaptureTest.java
+++ /dev/null
@@ -1,119 +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.
-
-package org.chromium.chrome.browser.suggestions;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.longClick;
-import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-import static org.chromium.chrome.test.BottomSheetTestRule.waitForWindowUpdates;
-
-import android.support.test.filters.MediumTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ntp.NtpUiCaptureTestData;
-import org.chromium.chrome.browser.ntp.cards.ItemViewType;
-import org.chromium.chrome.browser.ntp.snippets.CategoryStatus;
-import org.chromium.chrome.browser.ntp.snippets.KnownCategories;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
-import org.chromium.chrome.browser.test.ScreenShooter;
-import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.browser.suggestions.FakeSuggestionsSource;
-import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
-import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule.TestFactory;
-import org.chromium.ui.test.util.UiRestriction;
-
-import java.util.Collections;
-
-/**
- * Tests for the appearance of the card suggestions in the home sheet.
- */
-@DisabledTest(message = "https://crbug.com/805160")
-@RunWith(ChromeJUnit4ClassRunner.class)
-@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
-public class HomeSheetCardsUiCaptureTest {
-    @Rule
-    public SuggestionsBottomSheetTestRule mActivityRule = new SuggestionsBottomSheetTestRule();
-
-    private final TestFactory mDepsFactory = NtpUiCaptureTestData.createFactory();
-
-    @Rule
-    public SuggestionsDependenciesRule setupSuggestions() {
-        return new SuggestionsDependenciesRule(mDepsFactory);
-    }
-
-    @Rule
-    public ScreenShooter mScreenShooter = new ScreenShooter();
-
-    @Before
-    public void setup() throws InterruptedException {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.NTP_SIGNIN_PROMO_DISMISSED, true);
-        mActivityRule.startMainActivityOnBottomSheet(BottomSheet.SheetState.PEEK);
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"UiCatalogue"})
-    public void testContextMenu() {
-        mActivityRule.setSheetState(BottomSheet.SheetState.FULL, false);
-        waitForWindowUpdates();
-
-        int position = mActivityRule.getFirstPositionForType(ItemViewType.SNIPPET);
-        onView(withId(R.id.recycler_view)).perform(actionOnItemAtPosition(position, longClick()));
-        mScreenShooter.shoot("ContextMenu");
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"UiCatalogue"})
-    public void testScrolling() {
-        mActivityRule.setSheetState(BottomSheet.SheetState.FULL, false);
-        waitForWindowUpdates();
-
-        // When scrolling to a View, we wait until the View is no longer updating - when it is no
-        // longer dirty. If scroll to load is triggered, the animated progress spinner will keep
-        // the RecyclerView dirty as it is constantly updating. In addition for the UiCaptureTest
-        // we would like to get to the bottom of the CardsUI.
-
-        // We do not want to disable the Scroll to Load feature entirely because its presence
-        // effects other elements of the UI - it moves the Learn More link into the Context Menu.
-        // Removing the ScrollToLoad listener from the RecyclerView allows us to prevent scroll to
-        // load triggering while maintaining the UI otherwise.
-        mActivityRule.getRecyclerView().clearScrollToLoadListener();
-
-        mActivityRule.scrollToFirstItemOfType(ItemViewType.ACTION);
-        waitForWindowUpdates();
-        mScreenShooter.shoot("ScrolledToMoreButton");
-
-        mActivityRule.scrollToFirstItemOfType(ItemViewType.SNIPPET);
-        waitForWindowUpdates();
-        mScreenShooter.shoot("ScrolledToFirstCard");
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"UiCatalogue"})
-    public void testContentSuggestionPlaceholder() {
-        FakeSuggestionsSource source = (FakeSuggestionsSource) mDepsFactory.suggestionsSource;
-        source.setSuggestionsForCategory(KnownCategories.ARTICLES, Collections.emptyList());
-        source.setStatusForCategory(KnownCategories.ARTICLES, CategoryStatus.AVAILABLE_LOADING);
-
-        mActivityRule.setSheetState(BottomSheet.SheetState.FULL, false);
-        waitForWindowUpdates();
-
-        mScreenShooter.shoot("ContentSuggestionsPlaceholder");
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetNoTilesUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetNoTilesUiCaptureTest.java
deleted file mode 100644
index 47fefa6..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetNoTilesUiCaptureTest.java
+++ /dev/null
@@ -1,63 +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.
-
-package org.chromium.chrome.browser.suggestions;
-
-import static org.chromium.chrome.test.BottomSheetTestRule.waitForWindowUpdates;
-
-import android.support.test.filters.MediumTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.chrome.browser.ntp.NtpUiCaptureTestData;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
-import org.chromium.chrome.browser.test.ScreenShooter;
-import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
-import org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites;
-import org.chromium.ui.test.util.UiRestriction;
-
-/**
- * Tests for the appearance of the home sheet when there are no tiles.
- */
-@DisabledTest(message = "https://crbug.com/805160")
-@RunWith(ChromeJUnit4ClassRunner.class)
-@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
-public class HomeSheetNoTilesUiCaptureTest {
-    @Rule
-    public SuggestionsBottomSheetTestRule mActivityRule = new SuggestionsBottomSheetTestRule();
-
-    @Rule
-    public SuggestionsDependenciesRule setupSuggestions() {
-        SuggestionsDependenciesRule.TestFactory depsFactory = NtpUiCaptureTestData.createFactory();
-        ((FakeMostVisitedSites) depsFactory.mostVisitedSites).setTileSuggestions(new String[] {});
-        return new SuggestionsDependenciesRule(depsFactory);
-    }
-
-    @Rule
-    public ScreenShooter mScreenShooter = new ScreenShooter();
-
-    @Before
-    public void setup() throws InterruptedException {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.NTP_SIGNIN_PROMO_DISMISSED, true);
-        mActivityRule.startMainActivityOnBlankPage();
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"UiCatalogue"})
-    public void testNoTiles() {
-        mActivityRule.setSheetState(BottomSheet.SheetState.FULL, false);
-        waitForWindowUpdates();
-        mScreenShooter.shoot("NoTiles");
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetTilesUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetTilesUiCaptureTest.java
deleted file mode 100644
index 22989e9..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetTilesUiCaptureTest.java
+++ /dev/null
@@ -1,76 +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.
-
-package org.chromium.chrome.browser.suggestions;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.longClick;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
-
-import static org.chromium.chrome.test.BottomSheetTestRule.waitForWindowUpdates;
-
-import android.support.test.filters.MediumTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.chrome.browser.ntp.NtpUiCaptureTestData;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
-import org.chromium.chrome.browser.test.ScreenShooter;
-import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
-import org.chromium.chrome.test.BottomSheetTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
-import org.chromium.ui.test.util.UiRestriction;
-
-/**
- * Tests for the appearance of the tile suggestions in the home sheet.
- */
-@DisabledTest(message = "https://crbug.com/805160")
-@RunWith(ChromeJUnit4ClassRunner.class)
-@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
-public class HomeSheetTilesUiCaptureTest {
-    @Rule
-    public BottomSheetTestRule mActivityRule = new BottomSheetTestRule();
-
-    @Rule
-    public SuggestionsDependenciesRule setupSuggestions() {
-        return new SuggestionsDependenciesRule(NtpUiCaptureTestData.createFactory());
-    }
-
-    @Rule
-    public ScreenShooter mScreenShooter = new ScreenShooter();
-
-    @Before
-    public void setup() throws InterruptedException {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.NTP_SIGNIN_PROMO_DISMISSED, true);
-        mActivityRule.startMainActivityOnBlankPage();
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"UiCatalogue"})
-    public void testAppearance() {
-        mActivityRule.setSheetState(BottomSheet.SheetState.FULL, false);
-        waitForWindowUpdates();
-        mScreenShooter.shoot("Appearance");
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"UiCatalogue"})
-    public void testContextMenu() {
-        mActivityRule.setSheetState(BottomSheet.SheetState.FULL, false);
-        waitForWindowUpdates();
-        onView(withText(NtpUiCaptureTestData.getSiteSuggestions().get(0).title))
-                .perform(longClick());
-        mScreenShooter.shoot("ContextMenu");
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetUiCaptureTest.java
deleted file mode 100644
index f861a2c..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetUiCaptureTest.java
+++ /dev/null
@@ -1,75 +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.
-
-package org.chromium.chrome.browser.suggestions;
-
-import static org.chromium.chrome.test.BottomSheetTestRule.waitForWindowUpdates;
-
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.chrome.browser.ntp.NtpUiCaptureTestData;
-import org.chromium.chrome.browser.ntp.cards.ItemViewType;
-import org.chromium.chrome.browser.test.ScreenShooter;
-import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.MenuUtils;
-import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
-import org.chromium.ui.test.util.UiRestriction;
-
-/**
- * Tests for the appearance of the special states of the home sheet.
- */
-@DisabledTest(message = "https://crbug.com/805160")
-@RunWith(ChromeJUnit4ClassRunner.class)
-@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
-public class HomeSheetUiCaptureTest {
-    @Rule
-    public SuggestionsBottomSheetTestRule mActivityRule = new SuggestionsBottomSheetTestRule();
-
-    @Rule
-    public SuggestionsDependenciesRule setupSuggestions() {
-        return new SuggestionsDependenciesRule(NtpUiCaptureTestData.createFactory());
-    }
-
-    @Rule
-    public ScreenShooter mScreenShooter = new ScreenShooter();
-
-    @Before
-    public void setup() throws InterruptedException {
-        mActivityRule.startMainActivityOnBlankPage();
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"UiCatalogue"})
-    public void testSignInPromo() {
-        // Needs to be "Full" to for this to work on small screens in landscape.
-        mActivityRule.setSheetState(BottomSheet.SheetState.FULL, false);
-        waitForWindowUpdates();
-
-        mActivityRule.scrollToFirstItemOfType(ItemViewType.PROMO);
-        mScreenShooter.shoot("SignInPromo_new");
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"UiCatalogue"})
-    public void testNewTab() {
-        // Select "New tab" from the menu.
-        MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityRule.getActivity(), org.chromium.chrome.R.id.new_tab_menu_id);
-        waitForWindowUpdates();
-
-        mScreenShooter.shoot("NewTab");
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTest.java
deleted file mode 100644
index d12e4bf..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTest.java
+++ /dev/null
@@ -1,74 +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.
-
-package org.chromium.chrome.browser.suggestions;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.view.MotionEvent;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.chrome.browser.ntp.NtpUiCaptureTestData;
-import org.chromium.chrome.browser.ntp.cards.ItemViewType;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.content_public.browser.test.util.TestTouchUtils;
-import org.chromium.ui.test.util.UiRestriction;
-
-import java.util.concurrent.ExecutionException;
-
-/**
- * Instrumentation tests for {@link SuggestionsBottomSheetContent}.
- */
-@DisabledTest(message = "https://crbug.com/805160")
-@RunWith(ChromeJUnit4ClassRunner.class)
-@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
-public class SuggestionsBottomSheetTest {
-    @Rule
-    public SuggestionsBottomSheetTestRule mActivityRule = new SuggestionsBottomSheetTestRule();
-
-    @Rule
-    public SuggestionsDependenciesRule createSuggestions() {
-        return new SuggestionsDependenciesRule(NtpUiCaptureTestData.createFactory());
-    }
-
-    @Before
-    public void setUp() throws InterruptedException {
-        mActivityRule.startMainActivityOnBlankPage();
-    }
-
-    @Test
-    @RetryOnFailure
-    @MediumTest
-    public void testContextMenu() throws ExecutionException {
-        ViewHolder suggestionViewHolder =
-                mActivityRule.scrollToFirstItemOfType(ItemViewType.SNIPPET);
-        assertFalse(mActivityRule.getBottomSheet().onInterceptTouchEvent(createTapEvent()));
-
-        TestTouchUtils.performLongClickOnMainSync(
-                InstrumentationRegistry.getInstrumentation(), suggestionViewHolder.itemView);
-        assertTrue(mActivityRule.getBottomSheet().onInterceptTouchEvent(createTapEvent()));
-
-        TestThreadUtils.runOnUiThreadBlocking(mActivityRule.getActivity()::closeContextMenu);
-        assertFalse(mActivityRule.getBottomSheet().onInterceptTouchEvent(createTapEvent()));
-    }
-
-    private static MotionEvent createTapEvent() {
-        return MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
-                MotionEvent.ACTION_DOWN, 0f, 0f, 0);
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTestRule.java
deleted file mode 100644
index f30ff98..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetTestRule.java
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.suggestions;
-
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-
-import android.support.v7.widget.RecyclerView;
-
-import org.chromium.chrome.browser.ntp.cards.ItemViewType;
-import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter;
-import org.chromium.chrome.test.BottomSheetTestRule;
-import org.chromium.chrome.test.util.browser.RecyclerViewTestUtils;
-import org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils;
-
-/**
- * Junit4 rule for testing suggestions in the Chrome Home "Home" sheet.
- */
-public class SuggestionsBottomSheetTestRule extends BottomSheetTestRule {
-    /**
-     * @return The {@link SuggestionsRecyclerView} for this sheet.
-     */
-    public SuggestionsRecyclerView getRecyclerView() {
-        SuggestionsRecyclerView recyclerView =
-                getBottomSheetContent().getContentView().findViewById(
-                        org.chromium.chrome.R.id.recycler_view);
-        assertNotNull(recyclerView);
-        return recyclerView;
-    }
-
-    /**
-     * @return The {@link NewTabPageAdapter} for this sheet.
-     */
-    public NewTabPageAdapter getAdapter() {
-        return getRecyclerView().getNewTabPageAdapter();
-    }
-
-    /**
-     * @param itemViewType The type of item to find.
-     * @return The position of the first item of the given type.
-     */
-    public int getFirstPositionForType(@ItemViewType int itemViewType) {
-        return getAdapter().getFirstPositionForType(itemViewType);
-    }
-
-    /**
-     * Finds and scrolls to the first item of the given type.
-     * @param type The type of item to find and scroll to.
-     * @return the ViewHolder for the given {@code position}.
-     */
-    public RecyclerView.ViewHolder scrollToFirstItemOfType(@ItemViewType int type) {
-        int position = getFirstPositionForType(type);
-        assertNotEquals("Scroll target of type " + type + " not found\n"
-                        + ContentSuggestionsTestUtils.stringify(getAdapter().getRootForTesting()),
-                RecyclerView.NO_POSITION, position);
-
-        return RecyclerViewTestUtils.scrollToView(getRecyclerView(), position);
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetUiCaptureTest.java
deleted file mode 100644
index 8b69b0f..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetUiCaptureTest.java
+++ /dev/null
@@ -1,68 +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.
-
-package org.chromium.chrome.browser.suggestions;
-
-import static org.chromium.chrome.test.BottomSheetTestRule.waitForWindowUpdates;
-
-import android.support.test.filters.MediumTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.chrome.browser.ntp.NtpUiCaptureTestData;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
-import org.chromium.chrome.browser.test.ScreenShooter;
-import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
-import org.chromium.ui.test.util.UiRestriction;
-
-/**
- * Tests for the appearance of the home sheet in different bottom sheet states.
- */
-@DisabledTest
-@RunWith(ChromeJUnit4ClassRunner.class)
-@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
-public class SuggestionsBottomSheetUiCaptureTest {
-    @Rule
-    public SuggestionsBottomSheetTestRule mActivityRule = new SuggestionsBottomSheetTestRule();
-
-    @Rule
-    public SuggestionsDependenciesRule createSuggestions() {
-        return new SuggestionsDependenciesRule(NtpUiCaptureTestData.createFactory());
-    }
-
-    @Rule
-    public ScreenShooter mScreenShooter = new ScreenShooter();
-
-    @Before
-    public void setup() throws InterruptedException {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.NTP_SIGNIN_PROMO_DISMISSED, true);
-        mActivityRule.startMainActivityOnBlankPage();
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"UiCatalogue"})
-    public void testBottomSheetPosition() {
-        mActivityRule.setSheetState(BottomSheet.SheetState.HALF, false);
-        waitForWindowUpdates();
-        mScreenShooter.shoot("Half");
-
-        mActivityRule.setSheetState(BottomSheet.SheetState.FULL, false);
-        waitForWindowUpdates();
-        mScreenShooter.shoot("Full");
-
-        mActivityRule.setSheetState(BottomSheet.SheetState.PEEK, false);
-        waitForWindowUpdates();
-        mScreenShooter.shoot("Peek");
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetObserverTest.java
index 33ff028..0484bbb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetObserverTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetObserverTest.java
@@ -91,6 +91,9 @@
      */
     private void runCloseEventTest(boolean animationEnabled, boolean peekStateEnabled)
             throws TimeoutException {
+        CallbackHelper hiddenHelper = mObserver.mHiddenCallbackHelper;
+        int initialHideEvents = hiddenHelper.getCallCount();
+
         mBottomSheetTestRule.setSheetState(SheetState.FULL, false);
 
         mSheetContent.setPeekHeight(peekStateEnabled ? HeightMode.DEFAULT : HeightMode.DISABLED);
@@ -100,11 +103,17 @@
         int initialOpenedCount = mObserver.mOpenedCallbackHelper.getCallCount();
 
         int closedCallbackCount = closedCallbackHelper.getCallCount();
-        mBottomSheetTestRule.setSheetState(
-                peekStateEnabled ? SheetState.PEEK : SheetState.HIDDEN, animationEnabled);
+
+        int targetState = peekStateEnabled ? SheetState.PEEK : SheetState.HIDDEN;
+        mBottomSheetTestRule.setSheetState(targetState, animationEnabled);
+
         closedCallbackHelper.waitForCallback(closedCallbackCount, 1);
 
+        if (targetState == SheetState.HIDDEN) hiddenHelper.waitForCallback(initialHideEvents, 1);
+
         assertEquals(initialOpenedCount, mObserver.mOpenedCallbackHelper.getCallCount());
+        assertEquals("Close event should have only been called once.",
+                closedCallbackCount + 1, closedCallbackHelper.getCallCount());
     }
 
     /** Test that the onSheetOpened event is triggered if the sheet is opened without animation. */
@@ -150,6 +159,8 @@
             throws TimeoutException {
         mSheetContent.setPeekHeight(peekStateEnabled ? HeightMode.DEFAULT : HeightMode.DISABLED);
 
+        CallbackHelper fullCallbackHelper = mObserver.mFullCallbackHelper;
+        int initialFullCount = fullCallbackHelper.getCallCount();
         CallbackHelper openedCallbackHelper = mObserver.mOpenedCallbackHelper;
         int openedCallbackCount = openedCallbackHelper.getCallCount();
         CallbackHelper closedCallbackHelper = mObserver.mClosedCallbackHelper;
@@ -166,7 +177,12 @@
         }
 
         mBottomSheetTestRule.setSheetState(SheetState.FULL, animationEnabled);
+
         openedCallbackHelper.waitForCallback(openedCallbackCount, 1);
+        fullCallbackHelper.waitForCallback(initialFullCount, 1);
+
+        assertEquals("Open event should have only been called once.",
+                openedCallbackCount + 1, openedCallbackHelper.getCallCount());
 
         assertEquals(initialClosedCount, closedCallbackHelper.getCallCount());
     }
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index 4ea42dc..f179c6a 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -7,7 +7,6 @@
 import("//components/gwp_asan/buildflags/buildflags.gni")
 import("//components/nacl/features.gni")
 import("//ppapi/buildflags/buildflags.gni")
-import("//printing/buildflags/buildflags.gni")
 import("//tools/grit/grit_rule.gni")
 import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
 
@@ -50,12 +49,6 @@
 
   if (is_win) {
     sources += [ "chrome_dll.rc" ]
-    if (enable_basic_printing) {
-      # The resource compiler can only handle macro functions up to 31 chars
-      # which the buildflag system produces for this. Make a define so we can
-      # toggle off of the enable-basic-printing flag in the .rc file.
-      defines = [ "ENABLE_PRINTING_FOR_RC" ]
-    }
     deps += [ "//printing/buildflags" ]
   }
 }
diff --git a/chrome/app/chrome_dll.rc b/chrome/app/chrome_dll.rc
index 5eed8f6..724208ce 100644
--- a/chrome/app/chrome_dll.rc
+++ b/chrome/app/chrome_dll.rc
@@ -2,6 +2,7 @@
 //
 #include "chrome_dll_resource.h"
 #include "chrome_command_ids.h"
+#include "printing/buildflags/buildflags.h"
 
 #define APSTUDIO_READONLY_SYMBOLS
 /////////////////////////////////////////////////////////////////////////////
@@ -35,10 +36,7 @@
 BEGIN
     VK_BACK,        IDC_BACK,                   VIRTKEY
     VK_LEFT,        IDC_BACK,                   VIRTKEY, ALT
-// This really should be using the buildflag but the resource compiler fails on
-// macro functions longer than 31 chars which this command produces. The BUILD
-// sets this regular define for this target only for this line to consume.
-#ifdef ENABLE_PRINTING_FOR_RC  // #if BUILDFLAG(ENABLE_PRINTING)
+#if BUILDFLAG(ENABLE_PRINTING)
     "P",            IDC_BASIC_PRINT,            VIRTKEY, CONTROL, SHIFT
 #endif  // ENABLE_PRINTING_FOR_RC
     "D",            IDC_BOOKMARK_ALL_TABS,      VIRTKEY, CONTROL, SHIFT
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 29a7cd7..22ba3fed 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -5320,6 +5320,10 @@
     }
   }
 
+  if (is_win || is_mac || is_desktop_linux) {
+    deps += [ "//chrome/browser/resources/signin:polymer3_elements" ]
+  }
+
   if (is_win || is_mac || is_desktop_linux || is_chromeos) {
     deps += [
       "//chrome/browser/resources/discards:discards_resources_gen",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 9b4aaccc..377660b 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -421,7 +421,6 @@
   "+third_party/blink/public/platform/web_sudden_termination_disabler_type.h",
   "+third_party/blink/public/public_buildflags.h",
   "+third_party/blink/public/web/web_context_menu_data.h",
-  "+third_party/blink/public/web/web_fullscreen_options.h",
   "+third_party/blink/public/web/web_media_player_action.h",
   "+third_party/blink/public/web/web_triggering_event_info.h",
 ]
diff --git a/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.cc b/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.cc
index c1e0837f..b726ec0 100644
--- a/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.cc
+++ b/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.cc
@@ -156,6 +156,15 @@
                                             second);
 }
 
+void AssistantCollectUserDataDelegate::OnKeyValueChanged(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jcaller,
+    const base::android::JavaParamRef<jstring>& jkey,
+    const base::android::JavaParamRef<jstring>& jvalue) {
+  ui_controller_->OnKeyValueChanged(SafeConvertJavaStringToNative(env, jkey),
+                                    SafeConvertJavaStringToNative(env, jvalue));
+}
+
 base::android::ScopedJavaGlobalRef<jobject>
 AssistantCollectUserDataDelegate::GetJavaObject() {
   return java_assistant_collect_user_data_delegate_;
diff --git a/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.h b/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.h
index c747620..8ff2bcf 100644
--- a/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.h
+++ b/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.h
@@ -66,6 +66,11 @@
       jint minute,
       jint second);
 
+  void OnKeyValueChanged(JNIEnv* env,
+                         const base::android::JavaParamRef<jobject>& jcaller,
+                         const base::android::JavaParamRef<jstring>& jkey,
+                         const base::android::JavaParamRef<jstring>& jvalue);
+
   base::android::ScopedJavaGlobalRef<jobject> GetJavaObject();
 
  private:
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
index 7630cbc2..edf8ef3 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -78,6 +78,64 @@
       proto.time().hour(), proto.time().minute(), proto.time().second());
 }
 
+// Creates the java equivalent to the text inputs specified in |section|.
+base::android::ScopedJavaLocalRef<jobject> CreateJavaTextInputsForSection(
+    JNIEnv* env,
+    const TextInputSectionProto& section) {
+  auto jinput_list =
+      Java_AssistantCollectUserDataModel_createTextInputList(env);
+  for (const auto& input : section.input_fields()) {
+    TextInputType type;
+    switch (input.input_type()) {
+      case TextInputProto::INPUT_TEXT:
+        type = TextInputType::INPUT_TEXT;
+        break;
+      case TextInputProto::INPUT_ALPHANUMERIC:
+        type = TextInputType::INPUT_ALPHANUMERIC;
+        break;
+      case TextInputProto::UNDEFINED:
+        NOTREACHED();
+        continue;
+    }
+    Java_AssistantCollectUserDataModel_appendTextInput(
+        env, jinput_list, type,
+        base::android::ConvertUTF8ToJavaString(env, input.hint()),
+        base::android::ConvertUTF8ToJavaString(env, input.value()),
+        base::android::ConvertUTF8ToJavaString(env, input.client_memory_key()));
+  }
+  return jinput_list;
+}
+
+// Creates the java equivalent to |sections|.
+base::android::ScopedJavaLocalRef<jobject> CreateJavaAdditionalSections(
+    JNIEnv* env,
+    const std::vector<UserFormSectionProto>& sections) {
+  auto jsection_list =
+      Java_AssistantCollectUserDataModel_createAdditionalSectionsList(env);
+  for (const auto& section : sections) {
+    switch (section.section_case()) {
+      case UserFormSectionProto::kStaticTextSection:
+        Java_AssistantCollectUserDataModel_appendStaticTextSection(
+            env, jsection_list,
+            base::android::ConvertUTF8ToJavaString(env, section.title()),
+            base::android::ConvertUTF8ToJavaString(
+                env, section.static_text_section().text()));
+        break;
+      case UserFormSectionProto::kTextInputSection: {
+        Java_AssistantCollectUserDataModel_appendTextInputSection(
+            env, jsection_list,
+            base::android::ConvertUTF8ToJavaString(env, section.title()),
+            CreateJavaTextInputsForSection(env, section.text_input_section()));
+        break;
+      }
+      case UserFormSectionProto::SECTION_NOT_SET:
+        NOTREACHED();
+        break;
+    }
+  }
+  return jsection_list;
+}
+
 }  // namespace
 
 // static
@@ -543,7 +601,14 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& jcaller,
     jint index) {
-  CloseOrCancel(index, TriggerContext::CreateEmpty());
+  // If the keyboard is currently shown, clicking the cancel button should
+  // hide the keyboard rather than close autofill assistant, because the cancel
+  // chip will be displayed right above the keyboard.
+  if (Java_AutofillAssistantUiController_isKeyboardShown(env, java_object_)) {
+    Java_AutofillAssistantUiController_hideKeyboard(env, java_object_);
+  } else {
+    CloseOrCancel(index, TriggerContext::CreateEmpty());
+  }
 }
 
 void UiControllerAndroid::OnCloseButtonClicked(
@@ -734,6 +799,11 @@
   ui_delegate_->SetDateTimeRangeEnd(year, month, day, hour, minute, second);
 }
 
+void UiControllerAndroid::OnKeyValueChanged(const std::string& key,
+                                            const std::string& value) {
+  ui_delegate_->SetAdditionalValue(key, value);
+}
+
 void UiControllerAndroid::OnCollectUserDataOptionsChanged(
     const CollectUserDataOptions* collect_user_data_options) {
   JNIEnv* env = AttachCurrentThread();
@@ -811,6 +881,15 @@
             env, collect_user_data_options->date_time_range.end_label()));
   }
 
+  Java_AssistantCollectUserDataModel_setPrependedSections(
+      env, jmodel,
+      CreateJavaAdditionalSections(
+          env, collect_user_data_options->additional_prepended_sections));
+  Java_AssistantCollectUserDataModel_setAppendedSections(
+      env, jmodel,
+      CreateJavaAdditionalSections(
+          env, collect_user_data_options->additional_appended_sections));
+
   Java_AssistantCollectUserDataModel_setVisible(env, jmodel, true);
 }
 
@@ -1015,4 +1094,4 @@
       base::android::ConvertJavaStringToUTF8(env, jmessage),
       static_cast<Metrics::DropOutReason>(jreason));
 }
-}  // namespace autofill_assistant.
+}  // namespace autofill_assistant
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h
index c730089..5dd0ad7 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.h
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -132,6 +132,7 @@
                                  int hour,
                                  int minute,
                                  int second);
+  void OnKeyValueChanged(const std::string& key, const std::string& value);
 
   // Called by AssistantFormDelegate:
   void OnCounterChanged(int input_index, int counter_index, int value);
diff --git a/chrome/browser/android/download/available_offline_content_provider.cc b/chrome/browser/android/download/available_offline_content_provider.cc
index 9418f93..9aeb3ea 100644
--- a/chrome/browser/android/download/available_offline_content_provider.cc
+++ b/chrome/browser/android/download/available_offline_content_provider.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/android/download/download_utils.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/common/chrome_features.h"
 #include "components/ntp_snippets/pref_names.h"
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
diff --git a/chrome/browser/android/download/available_offline_content_provider_unittest.cc b/chrome/browser/android/download/available_offline_content_provider_unittest.cc
index 27993387..6ebbbf1 100644
--- a/chrome/browser/android/download/available_offline_content_provider_unittest.cc
+++ b/chrome/browser/android/download/available_offline_content_provider_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/common/available_offline_content.mojom-test-utils.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/android/download/download_controller.cc b/chrome/browser/android/download/download_controller.cc
index cfcf278..81c8514b 100644
--- a/chrome/browser/android/download/download_controller.cc
+++ b/chrome/browser/android/download/download_controller.cc
@@ -31,6 +31,7 @@
 #include "chrome/browser/offline_pages/android/offline_page_bridge.h"
 #include "chrome/browser/permissions/permission_update_infobar_delegate_android.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/ui/android/view_android_helper.h"
 #include "chrome/browser/vr/vr_tab_helper.h"
 #include "chrome/grit/chromium_strings.h"
diff --git a/chrome/browser/android/download/download_manager_service.cc b/chrome/browser/android/download/download_manager_service.cc
index b2eaa19..8547b26 100644
--- a/chrome/browser/android/download/download_manager_service.cc
+++ b/chrome/browser/android/download/download_manager_service.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/download/offline_item_utils.h"
 #include "chrome/browser/download/simple_download_manager_coordinator_factory.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_constants.h"
 #include "components/download/network/android/network_status_listener_android.h"
diff --git a/chrome/browser/android/download/items/offline_content_aggregator_factory_android.cc b/chrome/browser/android/download/items/offline_content_aggregator_factory_android.cc
index 8561a6d..f6bd06c4 100644
--- a/chrome/browser/android/download/items/offline_content_aggregator_factory_android.cc
+++ b/chrome/browser/android/download/items/offline_content_aggregator_factory_android.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/offline_items_collection/core/android/offline_content_aggregator_bridge.h"
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
 
diff --git a/chrome/browser/android/feed/feed_host_service_factory.cc b/chrome/browser/android/feed/feed_host_service_factory.cc
index f9910db..2723dca 100644
--- a/chrome/browser/android/feed/feed_host_service_factory.cc
+++ b/chrome/browser/android/feed/feed_host_service_factory.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/offline_pages/offline_page_model_factory.h"
 #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/common/channel_info.h"
 #include "components/feed/content/feed_host_service.h"
diff --git a/chrome/browser/android/history/history_deletion_bridge.cc b/chrome/browser/android/history/history_deletion_bridge.cc
index e1d8036..5427200 100644
--- a/chrome/browser/android/history/history_deletion_bridge.cc
+++ b/chrome/browser/android/history/history_deletion_bridge.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "components/history/core/browser/history_service.h"
+#include "content/public/browser/browser_thread.h"
 
 using base::android::JavaParamRef;
 using base::android::JavaRef;
diff --git a/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc b/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
index 935e034..1ab29e1a 100644
--- a/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
+++ b/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/image_fetcher/jni_headers/ImageFetcherBridge_jni.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/image_fetcher/core/cache/image_cache.h"
 #include "components/image_fetcher/core/image_fetcher.h"
 #include "components/image_fetcher/core/image_fetcher_metrics_reporter.h"
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc
index 3af2e23..53acb749 100644
--- a/chrome/browser/android/preferences/website_preference_bridge.cc
+++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -42,9 +42,11 @@
 #include "content/public/browser/storage_partition.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "storage/browser/quota/quota_manager.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
 #include "url/origin.h"
 #include "url/url_constants.h"
+#include "url/url_util.h"
 
 using base::android::ConvertJavaStringToUTF8;
 using base::android::ConvertUTF8ToJavaString;
diff --git a/chrome/browser/android/signin/signin_manager_android_unittest.cc b/chrome/browser/android/signin/signin_manager_android_unittest.cc
index c42a8e2..b578c1e 100644
--- a/chrome/browser/android/signin/signin_manager_android_unittest.cc
+++ b/chrome/browser/android/signin/signin_manager_android_unittest.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/download/download_core_service_impl.h"
 #include "chrome/browser/offline_pages/offline_page_model_factory.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "components/bookmarks/browser/bookmark_model.h"
diff --git a/chrome/browser/android/vr/arcore_device/ar_image_transport.cc b/chrome/browser/android/vr/arcore_device/ar_image_transport.cc
index e9c0713..c0b1572c 100644
--- a/chrome/browser/android/vr/arcore_device/ar_image_transport.cc
+++ b/chrome/browser/android/vr/arcore_device/ar_image_transport.cc
@@ -14,6 +14,8 @@
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h"
 #include "ui/gfx/gpu_fence.h"
+#include "ui/gl/android/scoped_java_surface.h"
+#include "ui/gl/android/surface_texture.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_fence_egl.h"
@@ -36,7 +38,7 @@
   DVLOG(2) << __func__;
   DCHECK(IsOnGlThread());
 
-  if (!webxr)
+  if (!webxr || !UseSharedBuffer())
     return;
 
   std::vector<std::unique_ptr<vr::WebXrSharedBuffer>> buffers =
@@ -65,6 +67,21 @@
 
   glGenFramebuffersEXT(1, &camera_fbo_);
 
+  shared_buffer_draw_ = base::AndroidHardwareBufferCompat::IsSupportAvailable();
+
+  if (shared_buffer_draw_) {
+    DVLOG(2) << __func__ << ": UseSharedBuffer()=true";
+  } else {
+    DVLOG(2) << __func__ << ": UseSharedBuffer()=false, setting up surface";
+    glGenTextures(1, &transport_texture_id_);
+    transport_surface_texture_ =
+        gl::SurfaceTexture::Create(transport_texture_id_);
+    surface_size_ = {0, 0};
+    mailbox_bridge_->CreateSurface(transport_surface_texture_.get());
+    transport_surface_texture_->SetFrameAvailableCallback(base::BindRepeating(
+        &ArImageTransport::OnFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
+  }
+
   mailbox_bridge_->CreateAndBindContextProvider(
       base::BindOnce(&ArImageTransport::OnMailboxBridgeReady,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
@@ -79,6 +96,39 @@
   std::move(callback).Run();
 }
 
+void ArImageTransport::SetFrameAvailableCallback(
+    XrFrameCallback on_transport_frame_available) {
+  DVLOG(2) << __func__;
+  on_transport_frame_available_ = std::move(on_transport_frame_available);
+}
+
+void ArImageTransport::OnFrameAvailable() {
+  DVLOG(2) << __func__;
+  DCHECK(on_transport_frame_available_);
+
+  // This function assumes that there's only at most one frame in "processing"
+  // state at any given time, the webxr_ state handling ensures that. Drawing
+  // and swapping twice without an intervening UpdateTexImage call would lose
+  // an image, and that would lead to images and poses getting out of sync.
+  //
+  // It also assumes that the ArImageTransport and Surface only exist for the
+  // duration of a single session, and a new session will use fresh objects. For
+  // comparison, see GvrSchedulerDelegate::OnWebXrFrameAvailable which has more
+  // complex logic to support a lifetime across multiple sessions, including
+  // handling a possibly-unconsumed frame left over from a previous session.
+
+  transport_surface_texture_->UpdateTexImage();
+
+  // The SurfaceTexture needs to be drawn using the corresponding
+  // UV transform, that's usually a Y flip.
+  transport_surface_texture_->GetTransformMatrix(
+      &transport_surface_texture_uv_matrix_[0]);
+  transport_surface_texture_uv_transform_.matrix().setColMajorf(
+      transport_surface_texture_uv_matrix_);
+
+  on_transport_frame_available_.Run(transport_surface_texture_uv_transform_);
+}
+
 GLuint ArImageTransport::GetCameraTextureId() {
   return camera_texture_id_arcore_;
 }
@@ -190,8 +240,14 @@
     const gfx::Transform& uv_transform) {
   DVLOG(2) << __func__;
 
-  vr::WebXrSharedBuffer* shared_buffer =
-      webxr->GetRenderingFrame()->shared_buffer.get();
+  GLuint source_texture;
+  if (UseSharedBuffer()) {
+    vr::WebXrSharedBuffer* shared_buffer =
+        webxr->GetRenderingFrame()->shared_buffer.get();
+    source_texture = shared_buffer->local_texture;
+  } else {
+    source_texture = transport_texture_id_;
+  }
 
   // Set the blend mode for combining the drawn image (source) with the camera
   // image (destination). WebXR assumes that the canvas has premultiplied alpha,
@@ -201,8 +257,7 @@
   glEnable(GL_BLEND);
   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
-  CopyTextureToFramebuffer(shared_buffer->local_texture, frame_size,
-                           uv_transform);
+  CopyTextureToFramebuffer(source_texture, frame_size, uv_transform);
 }
 
 void ArImageTransport::CopyTextureToFramebuffer(
@@ -225,6 +280,26 @@
   ar_renderer_->Draw(texture, uv_transform_floats, 0, 0);
 }
 
+void ArImageTransport::CopyMailboxToSurfaceAndSwap(
+    const gfx::Size& frame_size,
+    const gpu::MailboxHolder& mailbox) {
+  DVLOG(2) << __func__;
+  if (frame_size != surface_size_) {
+    DVLOG(2) << __func__ << " resize from " << surface_size_.ToString()
+             << " to " << frame_size.ToString();
+    transport_surface_texture_->SetDefaultBufferSize(frame_size.width(),
+                                                     frame_size.height());
+    mailbox_bridge_->ResizeSurface(frame_size.width(), frame_size.height());
+    surface_size_ = frame_size;
+  }
+
+  // Draw the image to the surface in the GPU process's command buffer context.
+  // This will trigger an OnFrameAvailable event once the corresponding
+  // SurfaceTexture in the local GL context is ready for updating.
+  bool swapped = mailbox_bridge_->CopyMailboxToSurfaceAndSwap(mailbox);
+  DCHECK(swapped);
+}
+
 bool ArImageTransport::IsOnGlThread() const {
   return gl_thread_task_runner_->BelongsToCurrentThread();
 }
diff --git a/chrome/browser/android/vr/arcore_device/ar_image_transport.h b/chrome/browser/android/vr/arcore_device/ar_image_transport.h
index 6d4fc00..752cda6 100644
--- a/chrome/browser/android/vr/arcore_device/ar_image_transport.h
+++ b/chrome/browser/android/vr/arcore_device/ar_image_transport.h
@@ -13,6 +13,10 @@
 #include "device/vr/public/mojom/vr_service.mojom.h"
 #include "ui/gfx/geometry/size_f.h"
 
+namespace gl {
+class SurfaceTexture;
+}  // namespace gl
+
 namespace gfx {
 class GpuFence;
 }  // namespace gfx
@@ -30,6 +34,8 @@
 
 namespace device {
 
+using XrFrameCallback = base::RepeatingCallback<void(const gfx::Transform&)>;
+
 // This class handles transporting WebGL rendered output from the GPU process's
 // command buffer GL context to the local GL context, and compositing WebGL
 // output onto the camera image using the local GL context.
@@ -69,14 +75,21 @@
                                         const gfx::Size& frame_size,
                                         const gfx::Transform& uv_transform);
   virtual void WaitSyncToken(const gpu::SyncToken& sync_token);
+  virtual void CopyMailboxToSurfaceAndSwap(const gfx::Size& frame_size,
+                                           const gpu::MailboxHolder& mailbox);
+
+  bool UseSharedBuffer() { return shared_buffer_draw_; }
+  void SetFrameAvailableCallback(XrFrameCallback on_frame_available);
 
  private:
   std::unique_ptr<vr::WebXrSharedBuffer> CreateBuffer();
   void ResizeSharedBuffer(vr::WebXrPresentationState* webxr,
                           const gfx::Size& size,
                           vr::WebXrSharedBuffer* buffer);
+  void ResizeSurface(const gfx::Size& size);
   bool IsOnGlThread() const;
   void OnMailboxBridgeReady(base::OnceClosure callback);
+  void OnFrameAvailable();
   std::unique_ptr<ArRenderer> ar_renderer_;
   // samplerExternalOES texture for the camera image.
   GLuint camera_texture_id_arcore_ = 0;
@@ -86,6 +99,20 @@
 
   std::unique_ptr<vr::MailboxToSurfaceBridge> mailbox_bridge_;
 
+  // If true, use shared buffer transport aka DRAW_INTO_TEXTURE_MAILBOX.
+  // If false, use Surface transport aka SUBMIT_AS_MAILBOX_HOLDER.
+  bool shared_buffer_draw_ = false;
+
+  // Used for Surface transport (Android N)
+  //
+  // samplerExternalOES texture data for WebXR content image.
+  GLuint transport_texture_id_ = 0;
+  gfx::Size surface_size_;
+  scoped_refptr<gl::SurfaceTexture> transport_surface_texture_;
+  gfx::Transform transport_surface_texture_uv_transform_;
+  float transport_surface_texture_uv_matrix_[16];
+  XrFrameCallback on_transport_frame_available_;
+
   // Must be last.
   base::WeakPtrFactory<ArImageTransport> weak_ptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(ArImageTransport);
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.cc b/chrome/browser/android/vr/arcore_device/arcore_gl.cc
index 97c9eba..b1aba27 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_gl.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_gl.cc
@@ -187,12 +187,20 @@
       device::mojom::XRPresentationTransportOptions::New();
   transport_options->wait_for_gpu_fence = true;
 
-  // Currently, AR mode only supports Android O+ due to requiring
-  // AHardwareBuffer-backed GpuMemoryBuffer shared images. This could be
-  // extended back to Android N by using the SUBMIT_AS_MAILBOX_HOLDER method
-  // that uses Surface/SurfaceTexture.
-  transport_options->transport_method =
-      device::mojom::XRPresentationTransportMethod::DRAW_INTO_TEXTURE_MAILBOX;
+  if (ar_image_transport_->UseSharedBuffer()) {
+    DVLOG(2) << __func__
+             << ": UseSharedBuffer()=true, DRAW_INTO_TEXTURE_MAILBOX";
+    transport_options->transport_method =
+        device::mojom::XRPresentationTransportMethod::DRAW_INTO_TEXTURE_MAILBOX;
+  } else {
+    DVLOG(2) << __func__
+             << ": UseSharedBuffer()=false, SUBMIT_AS_MAILBOX_HOLDER";
+    transport_options->transport_method =
+        device::mojom::XRPresentationTransportMethod::SUBMIT_AS_MAILBOX_HOLDER;
+    transport_options->wait_for_transfer_notification = true;
+    ar_image_transport_->SetFrameAvailableCallback(base::BindRepeating(
+        &ArCoreGl::OnTransportFrameAvailable, weak_ptr_factory_.GetWeakPtr()));
+  }
 
   auto submit_frame_sink = device::mojom::XRPresentationConnection::New();
   submit_frame_sink->client_receiver =
@@ -389,14 +397,17 @@
     frame_data->left_eye = display_info_->left_eye.Clone();
     display_info_changed_ = false;
   }
-  // Set up a shared buffer for the renderer to draw into, it'll be sent
-  // alongside the frame pose.
-  gpu::MailboxHolder buffer_holder = ar_image_transport_->TransferFrame(
-      webxr_.get(), transfer_size_, uv_transform_);
+
+  if (ar_image_transport_->UseSharedBuffer()) {
+    // Set up a shared buffer for the renderer to draw into, it'll be sent
+    // alongside the frame pose.
+    gpu::MailboxHolder buffer_holder = ar_image_transport_->TransferFrame(
+        webxr_.get(), transfer_size_, uv_transform_);
+    frame_data->buffer_holder = buffer_holder;
+  }
 
   // Create the frame data to return to the renderer.
   frame_data->pose = std::move(pose);
-  frame_data->buffer_holder = buffer_holder;
   frame_data->time_delta = base::TimeTicks::Now() - base::TimeTicks();
 
   if (options && options->include_plane_data) {
@@ -481,7 +492,59 @@
 void ArCoreGl::SubmitFrame(int16_t frame_index,
                            const gpu::MailboxHolder& mailbox,
                            base::TimeDelta time_waited) {
-  NOTIMPLEMENTED();
+  DVLOG(2) << __func__ << ": frame=" << frame_index;
+  DCHECK(!ar_image_transport_->UseSharedBuffer());
+
+  if (!IsSubmitFrameExpected(frame_index))
+    return;
+
+  webxr_->ProcessOrDefer(base::BindOnce(&ArCoreGl::ProcessFrameFromMailbox,
+                                        weak_ptr_factory_.GetWeakPtr(),
+                                        frame_index, mailbox));
+}
+
+void ArCoreGl::ProcessFrameFromMailbox(int16_t frame_index,
+                                       const gpu::MailboxHolder& mailbox) {
+  DVLOG(2) << __func__ << ": frame=" << frame_index;
+  DCHECK(webxr_->HaveProcessingFrame());
+  DCHECK(!ar_image_transport_->UseSharedBuffer());
+
+  ar_image_transport_->CopyMailboxToSurfaceAndSwap(transfer_size_, mailbox);
+  // Notify the client that we're done with the mailbox so that the underlying
+  // image is eligible for destruction.
+  submit_client_->OnSubmitFrameTransferred(true);
+
+  CopyCameraImageToFramebuffer();
+
+  // Now wait for ar_image_transport_ to call OnTransportFrameAvailable
+  // indicating that the image drawn onto the Surface is ready for consumption
+  // from the SurfaceTexture.
+}
+
+void ArCoreGl::OnTransportFrameAvailable(const gfx::Transform& uv_transform) {
+  DVLOG(2) << __func__;
+  DCHECK(!ar_image_transport_->UseSharedBuffer());
+  DCHECK(webxr_->HaveProcessingFrame());
+  webxr_->TransitionFrameProcessingToRendering();
+
+  glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+  ar_image_transport_->CopyDrawnImageToFramebuffer(
+      webxr_.get(), camera_image_size_, uv_transform);
+
+  surface_->SwapBuffers(base::DoNothing());
+  DVLOG(3) << __func__ << ": SwapBuffers";
+
+  webxr_->EndFrameRendering();
+
+  if (submit_client_) {
+    // Create a local GpuFence and pass it to the Renderer via IPC.
+    std::unique_ptr<gl::GLFence> gl_fence = gl::GLFence::CreateForGpuFence();
+    std::unique_ptr<gfx::GpuFence> gpu_fence2 = gl_fence->GetGpuFence();
+    submit_client_->OnSubmitFrameGpuFence(
+        gfx::CloneHandleForIPC(gpu_fence2->GetGpuFenceHandle()));
+  }
+  // We finished processing a frame, unblock a potentially waiting next frame.
+  webxr_->TryDeferredProcessing();
 }
 
 void ArCoreGl::SubmitFrameWithTextureHandle(int16_t frame_index,
@@ -493,6 +556,7 @@
                                            const gpu::SyncToken& sync_token,
                                            base::TimeDelta time_waited) {
   DVLOG(2) << __func__ << ": frame=" << frame_index;
+  DCHECK(ar_image_transport_->UseSharedBuffer());
 
   if (!IsSubmitFrameExpected(frame_index))
     return;
@@ -509,6 +573,7 @@
   TRACE_EVENT0("gpu", "ArCore SubmitFrame");
 
   DCHECK(webxr_->HaveProcessingFrame());
+  DCHECK(ar_image_transport_->UseSharedBuffer());
   CopyCameraImageToFramebuffer();
 
   ar_image_transport_->CreateGpuFenceForSyncToken(
@@ -521,6 +586,7 @@
   DVLOG(3) << __func__ << ": frame=" << frame_index;
 
   DCHECK(webxr_->HaveProcessingFrame());
+  DCHECK(ar_image_transport_->UseSharedBuffer());
   webxr_->TransitionFrameProcessingToRendering();
 
   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.h b/chrome/browser/android/vr/arcore_device/arcore_gl.h
index 4e72a44e..fbf7797 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_gl.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_gl.h
@@ -130,6 +130,8 @@
   // mojom::XRSessionController
   void SetFrameDataRestricted(bool restricted) override;
 
+  void ProcessFrameFromMailbox(int16_t frame_index,
+                               const gpu::MailboxHolder& mailbox);
   void ProcessFrameDrawnIntoTexture(int16_t frame_index,
                                     const gpu::SyncToken& sync_token);
   void OnWebXrTokenSignaled(int16_t frame_index,
@@ -152,6 +154,7 @@
   void OnArImageTransportReady(base::OnceCallback<void(bool)> callback);
   bool IsOnGlThread() const;
   void CopyCameraImageToFramebuffer();
+  void OnTransportFrameAvailable(const gfx::Transform& uv_transform);
 
   base::OnceClosure session_shutdown_callback_;
 
diff --git a/chrome/browser/android/vr/arcore_device/arcore_shim.cc b/chrome/browser/android/vr/arcore_device/arcore_shim.cc
index 0ac05f4..8716cc5 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_shim.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_shim.cc
@@ -7,6 +7,7 @@
 #include <dlfcn.h>
 
 #include "base/android/android_hardware_buffer_compat.h"
+#include "base/android/build_info.h"
 #include "base/logging.h"
 
 namespace {
@@ -120,7 +121,8 @@
 }
 
 bool IsArCoreSupported() {
-  return base::AndroidHardwareBufferCompat::IsSupportAvailable();
+  return base::android::BuildInfo::GetInstance()->sdk_int() >=
+         base::android::SDK_VERSION_NOUGAT;
 }
 
 }  // namespace vr
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc
index 2e22f27..0148f7b2 100644
--- a/chrome/browser/apps/app_service/extension_apps.cc
+++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -597,6 +597,10 @@
   }
 }
 
+void ExtensionApps::OnArcAppListPrefsDestroyed() {
+  arc_prefs_ = nullptr;
+}
+
 // static
 bool ExtensionApps::IsBlacklisted(const std::string& app_id) {
   // We blacklist (meaning we don't publish the app, in the App Service sense)
diff --git a/chrome/browser/apps/app_service/extension_apps.h b/chrome/browser/apps/app_service/extension_apps.h
index 9a31c8e..25391656 100644
--- a/chrome/browser/apps/app_service/extension_apps.h
+++ b/chrome/browser/apps/app_service/extension_apps.h
@@ -119,6 +119,7 @@
   void OnPackageRemoved(const std::string& package_name,
                         bool uninstalled) override;
   void OnPackageListInitialRefreshed() override;
+  void OnArcAppListPrefsDestroyed() override;
 
   void Publish(apps::mojom::AppPtr app);
 
diff --git a/chrome/browser/background_fetch/background_fetch_browsertest.cc b/chrome/browser/background_fetch/background_fetch_browsertest.cc
index 07dde45..bacd6ab 100644
--- a/chrome/browser/background_fetch/background_fetch_browsertest.cc
+++ b/chrome/browser/background_fetch/background_fetch_browsertest.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
index ecd73fb..40bbb09 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/metrics/ukm_background_recorder_service.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/download/public/background_service/download_params.h"
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc
index ed0818a..25b2b69 100644
--- a/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc
+++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc
@@ -134,7 +134,7 @@
   }
 };
 
-// WARNING:  These tests work with --single_process, but not
+// WARNING:  These tests work with --single-process-tests, but not
 // --single-process.  The reason is that the sandbox does not get created
 // for us by the test process if --single-process is used.
 
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 33ea655..0e03a3c1 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -9,7 +9,8 @@
   <release seq="1">
     <structures>
       <if expr="is_win or is_macosx or desktop_linux">
-        <structure name="IDR_SIGNIN_SHARED_CSS_HTML" file="resources\signin\signin_shared_css.html" preprocess="true" allowexternalscript="true" type="chrome_html" />
+        <structure name="IDR_SIGNIN_SHARED_CSS_JS" file="${root_gen_dir}\chrome\browser\resources\signin\signin_shared_css.js" use_base_dir="false" preprocess="true" type="chrome_html" />
+        <structure name="IDR_SIGNIN_SHARED_OLD_CSS_HTML" file="resources\signin\signin_shared_old_css.html" preprocess="true" allowexternalscript="true" type="chrome_html" />
       </if>
       <if expr="not is_android">
         <structure name="IDR_INCOGNITO_TAB_HTML" file="resources\ntp4\incognito_tab.html" flattenhtml="true" type="chrome_html" />
@@ -329,10 +330,8 @@
         <include name="IDR_SYNC_DISABLED_CONFIRMATION_JS" file="resources\signin\sync_confirmation\sync_disabled_confirmation.js" type="BINDATA" />
         <include name="IDR_SYNC_CONFIRMATION_HTML" file="resources\signin\sync_confirmation\sync_confirmation.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
         <include name="IDR_SYNC_CONFIRMATION_JS" file="resources\signin\sync_confirmation\sync_confirmation.js" type="BINDATA" />
-        <include name="IDR_SYNC_CONFIRMATION_BROWSER_PROXY_HTML" file="resources\signin\sync_confirmation\sync_confirmation_browser_proxy.html" type="BINDATA" />
         <include name="IDR_SYNC_CONFIRMATION_BROWSER_PROXY_JS" file="resources\signin\sync_confirmation\sync_confirmation_browser_proxy.js" type="BINDATA" />
-        <include name="IDR_SYNC_CONFIRMATION_APP_HTML" file="resources\signin\sync_confirmation\sync_confirmation_app.html" type="BINDATA" flattenhtml="true" allowexternalscript="true" />
-        <include name="IDR_SYNC_CONFIRMATION_APP_JS" file="resources\signin\sync_confirmation\sync_confirmation_app.js" type="BINDATA" />
+        <include name="IDR_SYNC_CONFIRMATION_APP_JS" file="${root_gen_dir}\chrome\browser\resources\signin\sync_confirmation\sync_confirmation_app.js" use_base_dir="false" preprocess="true" type="BINDATA" />
         <include name="IDR_SIGNIN_EMAIL_CONFIRMATION_HTML" file="resources\signin\signin_email_confirmation\signin_email_confirmation.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
         <include name="IDR_SIGNIN_EMAIL_CONFIRMATION_JS" file="resources\signin\signin_email_confirmation\signin_email_confirmation.js" type="BINDATA" />
         <include name="IDR_SIGNIN_ERROR_HTML" file="resources\signin\signin_error\signin_error.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
index ac11face..4647cd4 100644
--- a/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
@@ -21,6 +21,7 @@
 #include "net/cookies/parsed_cookie.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/mojom/cookie_manager.mojom.h"
 #include "url/gurl.h"
 
 using content::BrowserThread;
diff --git a/chrome/browser/browsing_data/counters/autofill_counter_browsertest.cc b/chrome/browser/browsing_data/counters/autofill_counter_browsertest.cc
index dbce23de..59cd18f 100644
--- a/chrome/browser/browsing_data/counters/autofill_counter_browsertest.cc
+++ b/chrome/browser/browsing_data/counters/autofill_counter_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
 #include "base/threading/platform_thread.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/browsing_data/counters/site_data_counting_helper.cc b/chrome/browser/browsing_data/counters/site_data_counting_helper.cc
index f9b6c9b..ec30f25 100644
--- a/chrome/browser/browsing_data/counters/site_data_counting_helper.cc
+++ b/chrome/browser/browsing_data/counters/site_data_counting_helper.cc
@@ -18,6 +18,7 @@
 #include "content/public/browser/session_storage_usage_info.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/storage_usage_info.h"
+#include "media/media_buildflags.h"
 #include "net/cookies/cookie_util.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
diff --git a/chrome/browser/chrome_browser_main.h b/chrome/browser/chrome_browser_main.h
index 11e2736..23cbce2b 100644
--- a/chrome/browser/chrome_browser_main.h
+++ b/chrome/browser/chrome_browser_main.h
@@ -31,6 +31,10 @@
 class ShutdownWatcherHelper;
 class WebUsbDetector;
 
+namespace base {
+class RunLoop;
+}
+
 namespace tracing {
 class TraceEventSystemStatsMonitor;
 }
diff --git a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_installer.cc b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_installer.cc
index 5a5bbb2..9d6296b4 100644
--- a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_installer.cc
+++ b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_installer.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/logging.h"
+#include "base/strings/stringprintf.h"
 #include "chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_installer_utils.h"
 #include "chrome/browser/chromeos/policy/remote_commands/user_command_arc_job.h"
 #include "chrome/browser/net/nss_context.h"
diff --git a/chrome/browser/chromeos/device_sync/device_sync_client_factory.cc b/chrome/browser/chromeos/device_sync/device_sync_client_factory.cc
index 1037af9..f40f9774 100644
--- a/chrome/browser/chromeos/device_sync/device_sync_client_factory.cc
+++ b/chrome/browser/chromeos/device_sync/device_sync_client_factory.cc
@@ -25,6 +25,7 @@
 #include "content/public/browser/browser_context.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/preferences/public/mojom/preferences.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
diff --git a/chrome/browser/chromeos/drive/drivefs_test_support.cc b/chrome/browser/chromeos/drive/drivefs_test_support.cc
index 47cfcff1..e4d160e 100644
--- a/chrome/browser/chromeos/drive/drivefs_test_support.cc
+++ b/chrome/browser/chromeos/drive/drivefs_test_support.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/files/file_util.h"
+#include "base/hash/md5.h"
 #include "base/json/json_writer.h"
 #include "base/path_service.h"
 #include "base/test/bind_test_util.h"
diff --git a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
index 999eab2..8d0a48c 100644
--- a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
@@ -32,6 +32,7 @@
 #include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/entry_info.h"
+#include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_url.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index 804e0bc2f..fc0a304 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -676,20 +676,20 @@
         TestCase("saveFileDialogDefaultFilter").WithBrowser(),
         TestCase("openFileDialogFileListShowContextMenu").WithBrowser()));
 
+#if defined(NDEBUG)
+#define MAYBE_CopyBetweenWindows CopyBetweenWindows
+#else
 // Flaky on Chrome OS Debug. TODO(crbug.com/1008909).
+#define MAYBE_CopyBetweenWindows DISABLED_CopyBetweenWindows
+#endif
 WRAPPED_INSTANTIATE_TEST_SUITE_P(
-    DISABLED_CopyBetweenWindows, /* copy_between_windows.js */
-    FilesAppBrowserTest,
-    ::testing::Values(TestCase("copyBetweenWindowsDriveToUsb")));
-
-WRAPPED_INSTANTIATE_TEST_SUITE_P(
-    CopyBetweenWindows, /* copy_between_windows.js */
+    MAYBE_CopyBetweenWindows, /* copy_between_windows.js */
     FilesAppBrowserTest,
     ::testing::Values(TestCase("copyBetweenWindowsLocalToDrive"),
                       TestCase("copyBetweenWindowsLocalToUsb"),
                       TestCase("copyBetweenWindowsUsbToDrive"),
                       TestCase("copyBetweenWindowsDriveToLocal"),
-//                      TestCase("copyBetweenWindowsDriveToUsb"),
+                      TestCase("copyBetweenWindowsDriveToUsb"),
                       TestCase("copyBetweenWindowsUsbToLocal")));
 
 WRAPPED_INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_util.cc b/chrome/browser/chromeos/fileapi/external_file_url_util.cc
index d2b6042..75f84b845 100644
--- a/chrome/browser/chromeos/fileapi/external_file_url_util.cc
+++ b/chrome/browser/chromeos/fileapi/external_file_url_util.cc
@@ -18,6 +18,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/url_constants.h"
 #include "net/base/escape.h"
+#include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_url.h"
 
 using content::BrowserThread;
diff --git a/chrome/browser/chromeos/login/screens/marketing_opt_in_screen.cc b/chrome/browser/chromeos/login/screens/marketing_opt_in_screen.cc
index 0e0b741..38d1ab6 100644
--- a/chrome/browser/chromeos/login/screens/marketing_opt_in_screen.cc
+++ b/chrome/browser/chromeos/login/screens/marketing_opt_in_screen.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/login/screens/marketing_opt_in_screen.h"
 
+#include "base/command_line.h"
 #include "base/logging.h"
 #include "chrome/browser/chromeos/login/users/chrome_user_manager_util.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.cc
index 6b94100d..691211e 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.cc
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager_factory.h"
 #include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/download/public/background_service/download_metadata.h"
 #include "components/download/public/background_service/download_service.h"
 #include "services/network/public/cpp/resource_request_body.h"
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.cc
index 2cedeca..0525990 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.cc
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
 #include "components/download/public/background_service/download_metadata.h"
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index 4bb130b..9a830fd 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -1022,6 +1022,19 @@
       }
     }
 
+    if (container.has_login_screen_screen_magnifier_type()) {
+      PolicyLevel level;
+      if (GetPolicyLevel(
+              container.has_login_screen_screen_magnifier_type_options(),
+              container.login_screen_screen_magnifier_type_options(), &level)) {
+        policies->Set(
+            key::kDeviceLoginScreenScreenMagnifierType, level,
+            POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
+            DecodeIntegerValue(container.login_screen_screen_magnifier_type()),
+            nullptr);
+      }
+    }
+
     if (container.has_login_screen_keyboard_focus_highlight_enabled()) {
       PolicyLevel level;
       if (GetPolicyLevel(
diff --git a/chrome/browser/chromeos/policy/login_profile_policy_provider.cc b/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
index d1eb594..ce13a10f 100644
--- a/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
+++ b/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
@@ -54,6 +54,7 @@
     {key::kDeviceLoginScreenStickyKeysEnabled, key::kStickyKeysEnabled},
     {key::kDeviceLoginScreenKeyboardFocusHighlightEnabled,
      key::kKeyboardFocusHighlightEnabled},
+    {key::kDeviceLoginScreenScreenMagnifierType, key::kScreenMagnifierType},
 };
 
 const DevicePolicyToUserPolicyMapEntry kRecommendedDevicePoliciesMap[] = {
diff --git a/chrome/browser/chromeos/policy/login_screen_accessibility_policy_browsertest.cc b/chrome/browser/chromeos/policy/login_screen_accessibility_policy_browsertest.cc
index 48c9ef5..9fed9da7 100644
--- a/chrome/browser/chromeos/policy/login_screen_accessibility_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/login_screen_accessibility_policy_browsertest.cc
@@ -36,6 +36,10 @@
 
 namespace {
 
+const int kDisabledScreenMagnifier = 0;
+const int kFullScreenMagnifier = 1;
+const int kDockedScreenMagnifier = 2;
+
 // Spins the loop until a notification is received from |prefs| that the value
 // of |pref_name| has changed. If the notification is received before Wait()
 // has been called, Wait() returns immediately and no loop is spun.
@@ -115,6 +119,12 @@
   ASSERT_TRUE(accessibility_manager);
   accessibility_manager->SetProfileForTest(
       chromeos::ProfileHelper::GetSigninProfile());
+
+  chromeos::MagnificationManager* magnification_manager =
+      chromeos::MagnificationManager::Get();
+  ASSERT_TRUE(magnification_manager);
+  magnification_manager->SetProfileForTest(
+      chromeos::ProfileHelper::GetSigninProfile());
 }
 
 void LoginScreenAccessibilityPolicyBrowsertest::
@@ -908,4 +918,115 @@
   accessibility_manager->SetFocusHighlightEnabled(false);
   EXPECT_FALSE(accessibility_manager->IsFocusHighlightEnabled());
 }
+
+IN_PROC_BROWSER_TEST_F(LoginScreenAccessibilityPolicyBrowsertest,
+                       DeviceLoginScreenFullScreenMagnifier) {
+  // Verifies that the state of the full-screen magnifier accessibility
+  // feature on the login screen can be controlled through device policy.
+  chromeos::MagnificationManager* magnification_manager =
+      chromeos::MagnificationManager::Get();
+  PrefService* prefs = login_profile_->GetPrefs();
+  ASSERT_TRUE(prefs);
+  ASSERT_TRUE(magnification_manager);
+  EXPECT_FALSE(
+      prefs->GetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled));
+
+  // Manually enable the full-screen magnifier mode.
+  prefs->SetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled, true);
+  EXPECT_TRUE(
+      prefs->GetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled));
+
+  // Disable the screen magnifier through device policy and wait for the
+  // change to take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()
+      ->set_login_screen_screen_magnifier_type(kDisabledScreenMagnifier);
+  RefreshDevicePolicyAndWaitForPrefChange(
+      ash::prefs::kAccessibilityScreenMagnifierEnabled);
+
+  // Verify that the pref which controls the full-screen magnifier mode in the
+  // login profile is managed by the policy.
+  EXPECT_TRUE(IsPrefManaged(ash::prefs::kAccessibilityScreenMagnifierEnabled));
+  EXPECT_EQ(base::Value(false),
+            GetPrefValue(ash::prefs::kAccessibilityScreenMagnifierEnabled));
+
+  // Verify that the full-screen magnifier mode cannot be enabled manually
+  // anymore.
+  prefs->SetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled, true);
+  EXPECT_FALSE(
+      prefs->GetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled));
+
+  // Enable the full-screen magnifier mode through device policy as a
+  // recommended value and wait for the change to take effect.
+  proto.mutable_accessibility_settings()
+      ->set_login_screen_screen_magnifier_type(kFullScreenMagnifier);
+  proto.mutable_accessibility_settings()
+      ->mutable_login_screen_screen_magnifier_type_options()
+      ->set_mode(em::PolicyOptions::RECOMMENDED);
+  RefreshDevicePolicyAndWaitForPrefChange(
+      ash::prefs::kAccessibilityScreenMagnifierEnabled);
+
+  // Verify that the pref which controls the full-screen magnifier mode in the
+  // login profile is managed by the policy.
+  EXPECT_FALSE(IsPrefManaged(ash::prefs::kAccessibilityScreenMagnifierEnabled));
+  EXPECT_EQ(base::Value(true),
+            GetPrefValue(ash::prefs::kAccessibilityScreenMagnifierEnabled));
+
+  // Verify that the full-screen magnifier mode cannot be enabled manually
+  // anymore.
+  prefs->SetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled, false);
+  EXPECT_TRUE(
+      prefs->GetBoolean(ash::prefs::kAccessibilityScreenMagnifierEnabled));
+}
+
+IN_PROC_BROWSER_TEST_F(LoginScreenAccessibilityPolicyBrowsertest,
+                       DeviceLoginScreenDockedMagnifier) {
+  // Verifies that the state of the docked magnifier accessibility
+  // feature on the login screen can be controlled through device policy.
+  chromeos::MagnificationManager* magnification_manager =
+      chromeos::MagnificationManager::Get();
+  ASSERT_TRUE(magnification_manager);
+  EXPECT_FALSE(magnification_manager->IsDockedMagnifierEnabled());
+
+  // Manually enable the docked magnifier mode.
+  magnification_manager->SetDockedMagnifierEnabled(true);
+  EXPECT_TRUE(magnification_manager->IsDockedMagnifierEnabled());
+
+  // Disable the screen magnifier through device policy and wait for the
+  // change to take effect.
+  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+  proto.mutable_accessibility_settings()
+      ->set_login_screen_screen_magnifier_type(kDisabledScreenMagnifier);
+  RefreshDevicePolicyAndWaitForPrefChange(ash::prefs::kDockedMagnifierEnabled);
+
+  // Verify that the pref which controls the docked magnifier mode in the
+  // login profile is managed by the policy.
+  EXPECT_TRUE(IsPrefManaged(ash::prefs::kDockedMagnifierEnabled));
+  EXPECT_EQ(base::Value(false),
+            GetPrefValue(ash::prefs::kDockedMagnifierEnabled));
+
+  // Verify that the docked magnifier mode cannot be enabled manually
+  // anymore.
+  magnification_manager->SetDockedMagnifierEnabled(true);
+  EXPECT_FALSE(magnification_manager->IsDockedMagnifierEnabled());
+
+  // Enable the docked magnifier mode through device policy as a recommended
+  // value and wait for the change to take effect.
+  proto.mutable_accessibility_settings()
+      ->set_login_screen_screen_magnifier_type(kDockedScreenMagnifier);
+  proto.mutable_accessibility_settings()
+      ->mutable_login_screen_screen_magnifier_type_options()
+      ->set_mode(em::PolicyOptions::RECOMMENDED);
+  RefreshDevicePolicyAndWaitForPrefChange(ash::prefs::kDockedMagnifierEnabled);
+
+  // Verify that the pref which controls the docked magnifier mode in the
+  // login profile is being applied as recommended by the policy.
+  EXPECT_FALSE(IsPrefManaged(ash::prefs::kDockedMagnifierEnabled));
+  EXPECT_EQ(base::Value(true),
+            GetPrefValue(ash::prefs::kDockedMagnifierEnabled));
+
+  // Verify that the docked magnifier mode can be enabled manually again.
+  magnification_manager->SetDockedMagnifierEnabled(false);
+  EXPECT_FALSE(magnification_manager->IsDockedMagnifierEnabled());
+}
 }  // namespace policy
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc
index 9a18bdef..535c40a 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/files/important_file_writer.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
diff --git a/chrome/browser/chromeos/profiles/profile_util.cc b/chrome/browser/chromeos/profiles/profile_util.cc
index 21b6ded..9f71761ef 100644
--- a/chrome/browser/chromeos/profiles/profile_util.cc
+++ b/chrome/browser/chromeos/profiles/profile_util.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/profiles/profile_util.h"
 
+#include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/content_index/content_index_provider_impl.cc b/chrome/browser/content_index/content_index_provider_impl.cc
index e4e4d85..69d2439b 100644
--- a/chrome/browser/content_index/content_index_provider_impl.cc
+++ b/chrome/browser/content_index/content_index_provider_impl.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/metrics/ukm_background_recorder_service.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
 #include "components/offline_items_collection/core/offline_item.h"
 #include "components/offline_items_collection/core/update_delta.h"
diff --git a/chrome/browser/content_settings/host_content_settings_map_factory.cc b/chrome/browser/content_settings/host_content_settings_map_factory.cc
index a3797e6..ac6b348 100644
--- a/chrome/browser/content_settings/host_content_settings_map_factory.cc
+++ b/chrome/browser/content_settings/host_content_settings_map_factory.cc
@@ -26,6 +26,7 @@
 
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
 #include "chrome/browser/content_settings/content_settings_supervised_provider.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
 #endif
diff --git a/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc b/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
index dacbe821..b0a80d89 100644
--- a/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
+++ b/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
@@ -302,7 +302,8 @@
     // Config is not fetched if the holdback group is enabled and lite page
     // redirect previews are not enabled. So, return early.
     if (data_reduction_proxy::params::IsIncludedInHoldbackFieldTrial() &&
-        !previews::params::IsLitePageServerPreviewsEnabled()) {
+        !previews::params::IsLitePageServerPreviewsEnabled() &&
+        !params::ForceEnableClientConfigServiceForAllDataSaverUsers()) {
       return;
     }
 
@@ -313,7 +314,8 @@
     // Config is not fetched if the holdback group is enabled and lite page
     // redirect previews are not enabled. So, return early.
     if (data_reduction_proxy::params::IsIncludedInHoldbackFieldTrial() &&
-        !previews::params::IsLitePageServerPreviewsEnabled()) {
+        !previews::params::IsLitePageServerPreviewsEnabled() &&
+        !params::ForceEnableClientConfigServiceForAllDataSaverUsers()) {
       return;
     }
     // Destructor of |config_waiter_| waits for the config fetch request to
@@ -337,7 +339,8 @@
     // redirect previews are enabled.
     EXPECT_TRUE(
         !data_reduction_proxy::params::IsIncludedInHoldbackFieldTrial() ||
-        previews::params::IsLitePageServerPreviewsEnabled());
+        previews::params::IsLitePageServerPreviewsEnabled() ||
+        params::ForceEnableClientConfigServiceForAllDataSaverUsers());
 
     auto response = std::make_unique<net::test_server::BasicHttpResponse>();
     response->set_content(config_.SerializeAsString());
@@ -672,19 +675,27 @@
 
 // Test that enabling the holdback disables the proxy and that the client config
 // is fetched when lite page redirect preview is enabled.
-// First parameter is true if the data reduction proxy holdback should be
-// enabled. Second parameter is true if lite page redirect preview is enabled.
 class DataReductionProxyWithHoldbackBrowsertest
-    : public ::testing::WithParamInterface<std::tuple<bool, bool>>,
+    : public ::testing::WithParamInterface<std::tuple<bool, bool, bool>>,
       public DataReductionProxyBrowsertest {
  public:
   DataReductionProxyWithHoldbackBrowsertest()
       : DataReductionProxyBrowsertest(),
-        data_reduction_proxy_holdback_enabled_(std::get<0>(GetParam())),
-        lite_page_redirect_previews_enabled_(std::get<1>(GetParam())) {}
+        // Consider the holdback as enabled if holdback is enabled or the
+        // |force_enable_config_service_fetches_| is enabled.
+        data_reduction_proxy_holdback_enabled_(std::get<2>(GetParam()) ||
+                                               std::get<0>(GetParam())),
+        lite_page_redirect_previews_enabled_(std::get<1>(GetParam())),
+        force_enable_config_service_fetches_(std::get<2>(GetParam())) {}
 
   void SetUp() override {
-    if (data_reduction_proxy_holdback_enabled_) {
+    if (force_enable_config_service_fetches_) {
+      scoped_feature_list_.InitAndEnableFeatureWithParameters(
+          data_reduction_proxy::features::kDataReductionProxyHoldback,
+          {{"force_enable_config_service_fetches", "true"}});
+    }
+    if (!force_enable_config_service_fetches_ &&
+        data_reduction_proxy_holdback_enabled_) {
       scoped_feature_list_.InitAndEnableFeature(
           data_reduction_proxy::features::kDataReductionProxyHoldback);
     }
@@ -698,6 +709,7 @@
 
   const bool data_reduction_proxy_holdback_enabled_;
   const bool lite_page_redirect_previews_enabled_;
+  const bool force_enable_config_service_fetches_;
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -728,7 +740,8 @@
   // holdback is not enabled would trigger and cause the test to fail.
   ui_test_utils::NavigateToURL(browser(), GURL("http://does.not.resolve/foo"));
 
-  if (data_reduction_proxy_holdback_enabled_) {
+  if (data_reduction_proxy_holdback_enabled_ ||
+      force_enable_config_service_fetches_) {
     EXPECT_NE(GetBody(), kPrimaryResponse);
   } else {
     EXPECT_EQ(GetBody(), kPrimaryResponse);
@@ -737,9 +750,12 @@
 
 // First parameter is true if the data reduction proxy holdback should be
 // enabled. Second parameter is true if lite page redirect preview is enabled.
+// Third parameter is true if data reduction proxy config should always be
+// fetched.
 INSTANTIATE_TEST_SUITE_P(,
                          DataReductionProxyWithHoldbackBrowsertest,
                          ::testing::Combine(::testing::Bool(),
+                                            ::testing::Bool(),
                                             ::testing::Bool()));
 
 class DataReductionProxyExpBrowsertest : public DataReductionProxyBrowsertest {
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.h b/chrome/browser/devtools/chrome_devtools_manager_delegate.h
index 27a2dd2..0e7bdc0 100644
--- a/chrome/browser/devtools/chrome_devtools_manager_delegate.h
+++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/devtools/protocol/protocol.h"
 #include "content/public/browser/devtools_agent_host_observer.h"
 #include "content/public/browser/devtools_manager_delegate.h"
+#include "net/base/host_port_pair.h"
 
 class ChromeDevToolsSession;
 using RemoteLocations = std::set<net::HostPortPair>;
diff --git a/chrome/browser/devtools/device/android_device_manager.cc b/chrome/browser/devtools/device/android_device_manager.cc
index a592054..4c4cf0b8 100644
--- a/chrome/browser/devtools/device/android_device_manager.cc
+++ b/chrome/browser/devtools/device/android_device_manager.cc
@@ -18,6 +18,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/post_task.h"
+#include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/devtools/device/usb/usb_device_manager_helper.h"
 #include "chrome/browser/devtools/device/usb/usb_device_provider.h"
diff --git a/chrome/browser/devtools/device/devtools_device_discovery.h b/chrome/browser/devtools/device/devtools_device_discovery.h
index 7b97e2f..a83ad1f 100644
--- a/chrome/browser/devtools/device/devtools_device_discovery.h
+++ b/chrome/browser/devtools/device/devtools_device_discovery.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/values.h"
 #include "chrome/browser/devtools/device/android_device_manager.h"
 #include "content/public/browser/devtools_agent_host.h"
 
diff --git a/chrome/browser/devtools/device/tcp_device_provider.h b/chrome/browser/devtools/device/tcp_device_provider.h
index 5f1dae6..c3ce73ea 100644
--- a/chrome/browser/devtools/device/tcp_device_provider.h
+++ b/chrome/browser/devtools/device/tcp_device_provider.h
@@ -11,6 +11,7 @@
 
 #include "chrome/browser/devtools/device/android_device_manager.h"
 #include "net/base/host_port_pair.h"
+#include "services/network/public/mojom/host_resolver.mojom.h"
 
 // Instantiate this class only in a test and/or when the DEBUG_DEVTOOLS
 // BUILDFLAG is set.
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index f65bf79..c290c153 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -763,13 +763,9 @@
 
 // Tests that BeforeUnload event gets called on devtools that are opened
 // on another devtools.
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
 // TODO(https://crbug.com/1000654): Re-enable this test.
-#define MAYBE_TestDevToolsOnDevTools DISABLED_TestDevToolsOnDevTools
-#else
-#define MAYBE_TestDevToolsOnDevTools TestDevToolsOnDevTools
-#endif
-IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, MAYBE_TestDevToolsOnDevTools) {
+IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
+                       DISABLED_TestDevToolsOnDevTools) {
   ASSERT_TRUE(spawned_test_server()->Start());
   LoadTestPage(kDebuggerTestPage);
 
diff --git a/chrome/browser/download/download_core_service_impl.cc b/chrome/browser/download/download_core_service_impl.cc
index 799e6b5..ca6db72 100644
--- a/chrome/browser/download/download_core_service_impl.cc
+++ b/chrome/browser/download/download_core_service_impl.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/download/simple_download_manager_coordinator_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/download/public/common/simple_download_manager_coordinator.h"
 #include "components/history/core/browser/history_service.h"
 #include "content/public/browser/download_manager.h"
diff --git a/chrome/browser/download/download_manager_utils.cc b/chrome/browser/download/download_manager_utils.cc
index 20c845a..2c75976 100644
--- a/chrome/browser/download/download_manager_utils.cc
+++ b/chrome/browser/download/download_manager_utils.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/download/simple_download_manager_coordinator_factory.h"
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/transition_manager/full_browser_transition_manager.h"
 #include "components/download/public/common/download_features.h"
 #include "components/download/public/common/in_progress_download_manager.h"
diff --git a/chrome/browser/download/download_service_factory.cc b/chrome/browser/download/download_service_factory.cc
index 26b8687..c62bbdd 100644
--- a/chrome/browser/download/download_service_factory.cc
+++ b/chrome/browser/download/download_service_factory.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/transition_manager/full_browser_transition_manager.h"
 #include "chrome/common/chrome_constants.h"
 #include "components/download/content/factory/download_service_factory_helper.h"
diff --git a/chrome/browser/download/download_shelf.cc b/chrome/browser/download/download_shelf.cc
index 9a87e3f..a00f9f6 100644
--- a/chrome/browser/download/download_shelf.cc
+++ b/chrome/browser/download/download_shelf.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/download/download_shelf_controller.cc b/chrome/browser/download/download_shelf_controller.cc
index feb4de33..ad8ffa9d 100644
--- a/chrome/browser/download/download_shelf_controller.cc
+++ b/chrome/browser/download/download_shelf_controller.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/download/offline_item_utils.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
diff --git a/chrome/browser/download/offline_item_model.cc b/chrome/browser/download/offline_item_model.cc
index 8739c8d..80c837bb 100644
--- a/chrome/browser/download/offline_item_model.cc
+++ b/chrome/browser/download/offline_item_model.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/download/offline_item_model_manager.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/offline_items_collection/core/fail_state.h"
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
 
diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc
index 561240c2..c7a7a619 100644
--- a/chrome/browser/extensions/extension_management.cc
+++ b/chrome/browser/extensions/extension_management.cc
@@ -12,6 +12,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
+#include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/syslog_logging.h"
 #include "base/trace_event/trace_event.h"
diff --git a/chrome/browser/extensions/extension_management_unittest.cc b/chrome/browser/extensions/extension_management_unittest.cc
index a2d79344..c23a23e 100644
--- a/chrome/browser/extensions/extension_management_unittest.cc
+++ b/chrome/browser/extensions/extension_management_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/json/json_parser.h"
 #include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_management_internal.h"
 #include "chrome/browser/extensions/extension_management_test_util.h"
diff --git a/chrome/browser/extensions/extension_service_sync_unittest.cc b/chrome/browser/extensions/extension_service_sync_unittest.cc
index 49c7777..e0a1bce 100644
--- a/chrome/browser/extensions/extension_service_sync_unittest.cc
+++ b/chrome/browser/extensions/extension_service_sync_unittest.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/test_blacklist.h"
 #include "chrome/browser/extensions/updater/extension_updater.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
diff --git a/chrome/browser/extensions/plugin_manager.cc b/chrome/browser/extensions/plugin_manager.cc
index 950975c2..f0516b3 100644
--- a/chrome/browser/extensions/plugin_manager.cc
+++ b/chrome/browser/extensions/plugin_manager.cc
@@ -17,6 +17,7 @@
 #include "content/public/common/pepper_plugin_info.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_handlers/mime_types_handler.h"
+#include "net/base/mime_util.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/extensions/policy_test_utils.cc b/chrome/browser/extensions/policy_test_utils.cc
index 8771b4ae..5bf5668e4 100644
--- a/chrome/browser/extensions/policy_test_utils.cc
+++ b/chrome/browser/extensions/policy_test_utils.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/path_service.h"
+#include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 34e1d10..80bf058 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2198,7 +2198,7 @@
   {
     "name": "form-controls-refresh",
     "owners": [ "iopopesc@microsoft.com", "//third_party/blink/renderer/core/OWNERS" ],
-    "expiry_milestone": 78
+    "expiry_milestone": 81
   },
   {
     "name": "fractional-scroll-offsets",
@@ -2681,11 +2681,6 @@
     "expiry_milestone": 76
   },
   {
-    "name": "omnibox-reverse-tab-switch-logic",
-    "owners": [ "krb", "chrome-omnibox-team@google.com" ],
-    "expiry_milestone": 77
-  },
-  {
     "name": "omnibox-rich-entity-suggestions",
     "owners": [ "jdonnelly", "chrome-omnibox-team@google.com" ],
     "expiry_milestone": 80
@@ -2713,7 +2708,7 @@
   {
     "name": "omnibox-tab-switch-suggestions",
     "owners": [ "krb", "chrome-omnibox-team@google.com" ],
-    "expiry_milestone": 76
+    "expiry_milestone": 82
   },
   {
     "name": "omnibox-tab-switch-suggestions-dedicated-row",
diff --git a/chrome/browser/gcm/gcm_profile_service_factory.cc b/chrome/browser/gcm/gcm_profile_service_factory.cc
index 3fea583f..c3ec2fa 100644
--- a/chrome/browser/gcm/gcm_profile_service_factory.cc
+++ b/chrome/browser/gcm/gcm_profile_service_factory.cc
@@ -12,6 +12,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/gcm_driver/gcm_profile_service.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -20,6 +21,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/storage_partition.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 
 #if !defined(OS_ANDROID)
 #include "chrome/browser/gcm/gcm_product_util.h"
diff --git a/chrome/browser/media/offscreen_tab.cc b/chrome/browser/media/offscreen_tab.cc
index 518d3d2..bda2005 100644
--- a/chrome/browser/media/offscreen_tab.cc
+++ b/chrome/browser/media/offscreen_tab.cc
@@ -300,7 +300,7 @@
 void OffscreenTab::EnterFullscreenModeForTab(
     WebContents* contents,
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   DCHECK_EQ(offscreen_tab_web_contents_.get(), contents);
 
   if (in_fullscreen_mode())
diff --git a/chrome/browser/media/offscreen_tab.h b/chrome/browser/media/offscreen_tab.h
index e3d8a35..04e56e6 100644
--- a/chrome/browser/media/offscreen_tab.h
+++ b/chrome/browser/media/offscreen_tab.h
@@ -108,10 +108,9 @@
       const std::string& frame_name,
       const GURL& target_url) final;
   bool EmbedsFullscreenWidget() final;
-  void EnterFullscreenModeForTab(
-      content::WebContents* contents,
-      const GURL& origin,
-      const blink::WebFullscreenOptions& options) final;
+  void EnterFullscreenModeForTab(content::WebContents* contents,
+                                 const GURL& origin,
+                                 const blink::FullScreenOptions& options) final;
   void ExitFullscreenModeForTab(content::WebContents* contents) final;
   bool IsFullscreenForTabOrPending(const content::WebContents* contents) final;
   blink::mojom::DisplayMode GetDisplayMode(
diff --git a/chrome/browser/media/webrtc/webrtc_internals_perf_browsertest.cc b/chrome/browser/media/webrtc/webrtc_internals_perf_browsertest.cc
index efc4093..08e2679 100644
--- a/chrome/browser/media/webrtc/webrtc_internals_perf_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_internals_perf_browsertest.cc
@@ -184,9 +184,16 @@
     ASSERT_TRUE(test::HasReferenceFilesInCheckout());
     ASSERT_TRUE(embedded_test_server()->Start());
 
+    ASSERT_GE(TestTimeouts::test_launcher_timeout().InSeconds(), 100)
+        << "This is a long-running test; you must specify "
+           "--test-launcher-timeout to have a value of at least 100000.";
     ASSERT_GE(TestTimeouts::action_max_timeout().InSeconds(), 100)
         << "This is a long-running test; you must specify "
            "--ui-test-action-max-timeout to have a value of at least 100000.";
+    ASSERT_LT(TestTimeouts::action_max_timeout(),
+              TestTimeouts::test_launcher_timeout())
+        << "action_max_timeout needs to be strictly-less-than "
+           "test_launcher_timeout";
 
     content::WebContents* left_tab =
         OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
diff --git a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm
index bdbed588..db33470c 100644
--- a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm
+++ b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm
@@ -29,6 +29,10 @@
 
 }  // namespace
 
+@interface ICCameraDevice ()
+- (instancetype)initWithDictionary:(id)properties NS_DESIGNATED_INITIALIZER;
+@end
+
 @interface MockMTPICCameraDevice : ICCameraDevice {
  @private
   base::scoped_nsobject<NSMutableArray> allMediaFiles_;
@@ -40,6 +44,10 @@
 
 @implementation MockMTPICCameraDevice
 
+- (instancetype)init {
+  return [super initWithDictionary:@{}];
+}
+
 - (NSString*)mountPoint {
   return @"mountPoint";
 }
@@ -157,7 +165,7 @@
         storage_monitor::TestStorageMonitor::CreateAndInstall();
     manager_.SetNotifications(monitor->receiver());
 
-    camera_ = [MockMTPICCameraDevice alloc];
+    camera_ = [[MockMTPICCameraDevice alloc] init];
     id<ICDeviceBrowserDelegate> delegate = manager_.device_browser_delegate();
     [delegate deviceBrowser:manager_.device_browser_for_test()
                didAddDevice:camera_
diff --git a/chrome/browser/metrics/perf/windowed_incognito_observer.cc b/chrome/browser/metrics/perf/windowed_incognito_observer.cc
index 55cb2cfb..8f24af4 100644
--- a/chrome/browser/metrics/perf/windowed_incognito_observer.cc
+++ b/chrome/browser/metrics/perf/windowed_incognito_observer.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "content/public/browser/browser_thread.h"
 
 namespace metrics {
 
diff --git a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
index c8ff3864..0e89c92 100644
--- a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
+++ b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
@@ -85,6 +85,9 @@
     return;
   }
 
+  // Drop fullscreen mode so that the user sees the URL bar.
+  web_contents->ForSecurityDropFullscreen();
+
   request_manager->AddRequest(
       {origin, path, is_directory},
       base::BindOnce(
@@ -131,6 +134,9 @@
     std::move(callback).Run(PermissionAction::DISMISSED);
   }
 
+  // Drop fullscreen mode so that the user sees the URL bar.
+  web_contents->ForSecurityDropFullscreen();
+
   ShowNativeFileSystemDirectoryAccessConfirmationDialog(
       origin, path, std::move(callback), web_contents);
 }
diff --git a/chrome/browser/net/chrome_network_service_browsertest.cc b/chrome/browser/net/chrome_network_service_browsertest.cc
index 917948a..d982e5e 100644
--- a/chrome/browser/net/chrome_network_service_browsertest.cc
+++ b/chrome/browser/net/chrome_network_service_browsertest.cc
@@ -43,11 +43,12 @@
   base::Time t = base::Time::Now();
   net::CanonicalCookie cookie(kCookieName, kCookieValue, "www.test.com", "/", t,
                               t + base::TimeDelta::FromDays(1), base::Time(),
-                              false, false, net::CookieSameSite::NO_RESTRICTION,
+                              true /* secure */, false /* http-only*/,
+                              net::CookieSameSite::NO_RESTRICTION,
                               net::COOKIE_PRIORITY_DEFAULT);
   base::RunLoop run_loop;
   cookie_manager->SetCanonicalCookie(
-      cookie, "http", net::CookieOptions(),
+      cookie, "https", net::CookieOptions(),
       base::BindLambdaForTesting(
           [&](net::CanonicalCookie::CookieInclusionStatus status) {
             run_loop.Quit();
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index 1d90713..923c56c 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -57,6 +57,7 @@
 #if defined(OS_ANDROID)
 #include "chrome/browser/android/chrome_feature_list.h"
 #include "chrome/browser/android/ntp/ntp_snippets_launcher.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/feed/feed_feature_list.h"
 #endif
 
diff --git a/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc b/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc
index 1c92432b..ff143dd9 100644
--- a/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc
+++ b/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc
@@ -31,6 +31,7 @@
 #include "chrome/browser/offline_pages/visuals_decoder_impl.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/transition_manager/full_browser_transition_manager.h"
 #include "components/download/public/common/download_url_parameters.h"
diff --git a/chrome/browser/offline_pages/android/offline_page_bridge.cc b/chrome/browser/offline_pages/android/offline_page_bridge.cc
index 1bbf07d..c871699 100644
--- a/chrome/browser/offline_pages/android/offline_page_bridge.cc
+++ b/chrome/browser/offline_pages/android/offline_page_bridge.cc
@@ -33,6 +33,8 @@
 #include "chrome/browser/offline_pages/recent_tab_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
+#include "chrome/browser/profiles/profile_key.h"
+#include "chrome/browser/profiles/profile_key_android.h"
 #include "components/offline_pages/core/archive_validator.h"
 #include "components/offline_pages/core/background/request_queue_results.h"
 #include "components/offline_pages/core/background/save_page_request.h"
diff --git a/chrome/browser/offline_pages/android/prefetch_test_bridge.cc b/chrome/browser/offline_pages/android/prefetch_test_bridge.cc
index a9940e1..7f7fcccd 100644
--- a/chrome/browser/offline_pages/android/prefetch_test_bridge.cc
+++ b/chrome/browser/offline_pages/android/prefetch_test_bridge.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/android/profile_key_util.h"
 #include "chrome/browser/image_fetcher/image_fetcher_service_factory.h"
 #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "components/image_fetcher/core/cache/image_cache.h"
 #include "components/image_fetcher/core/image_fetcher_service.h"
diff --git a/chrome/browser/offline_pages/offline_page_request_handler.cc b/chrome/browser/offline_pages/offline_page_request_handler.cc
index 54df819..bd2d226 100644
--- a/chrome/browser/offline_pages/offline_page_request_handler.cc
+++ b/chrome/browser/offline_pages/offline_page_request_handler.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/offline_pages/offline_page_model_factory.h"
 #include "chrome/browser/offline_pages/offline_page_tab_helper.h"
 #include "chrome/browser/offline_pages/offline_page_utils.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "components/offline_pages/core/client_namespace_constants.h"
 #include "components/offline_pages/core/offline_clock.h"
diff --git a/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc b/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
index 15d03a8..69b55ac 100644
--- a/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
+++ b/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/offline_pages/offline_page_model_factory.h"
 #include "chrome/browser/offline_pages/offline_page_tab_helper.h"
 #include "chrome/browser/offline_pages/offline_page_url_loader.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper.cc b/chrome/browser/offline_pages/offline_page_tab_helper.cc
index a5d26ae..3eba203 100644
--- a/chrome/browser/offline_pages/offline_page_tab_helper.cc
+++ b/chrome/browser/offline_pages/offline_page_tab_helper.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h"
 #include "chrome/browser/offline_pages/request_coordinator_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/offline_pages/core/background/request_coordinator.h"
 #include "components/offline_pages/core/model/offline_page_model_utils.h"
 #include "components/offline_pages/core/offline_page_client_policy.h"
diff --git a/chrome/browser/offline_pages/offline_page_utils_unittest.cc b/chrome/browser/offline_pages/offline_page_utils_unittest.cc
index f3ac14c..9ae32b5 100644
--- a/chrome/browser/offline_pages/offline_page_utils_unittest.cc
+++ b/chrome/browser/offline_pages/offline_page_utils_unittest.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/offline_pages/request_coordinator_factory.h"
 #include "chrome/browser/offline_pages/test_offline_page_model_builder.h"
 #include "chrome/browser/offline_pages/test_request_coordinator_builder.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/offline_pages/core/background/request_coordinator.h"
diff --git a/chrome/browser/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/offline_pages/recent_tab_helper_unittest.cc
index 81837e83..2515200 100644
--- a/chrome/browser/offline_pages/recent_tab_helper_unittest.cc
+++ b/chrome/browser/offline_pages/recent_tab_helper_unittest.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/offline_pages/request_coordinator_factory.h"
 #include "chrome/browser/offline_pages/test_offline_page_model_builder.h"
 #include "chrome/browser/offline_pages/test_request_coordinator_builder.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/offline_pages/core/client_namespace_constants.h"
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index cf28f9e..06c48ded 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1540,6 +1540,9 @@
   handlers->AddHandler(std::make_unique<IntRangePolicyHandler>(
       key::kDeviceLoginScreenDefaultScreenMagnifierType, nullptr,
       chromeos::MAGNIFIER_DISABLED, chromeos::MAGNIFIER_DOCKED, false));
+  handlers->AddHandler(std::make_unique<IntRangePolicyHandler>(
+      key::kDeviceLoginScreenScreenMagnifierType, nullptr,
+      chromeos::MAGNIFIER_DISABLED, chromeos::MAGNIFIER_DOCKED, false));
   // TODO(binjin): Remove LegacyPoliciesDeprecatingPolicyHandler for these two
   // policies once deprecation of legacy power management policies is done.
   // http://crbug.com/346229
diff --git a/chrome/browser/predictors/loading_data_collector.cc b/chrome/browser/predictors/loading_data_collector.cc
index c9f40ac..3d2d516 100644
--- a/chrome/browser/predictors/loading_data_collector.cc
+++ b/chrome/browser/predictors/loading_data_collector.cc
@@ -17,6 +17,7 @@
 #include "components/history/core/browser/history_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/resource_type.h"
+#include "net/base/mime_util.h"
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_request.h"
 #include "third_party/blink/public/common/mime_util/mime_util.h"
diff --git a/chrome/browser/previews/previews_offline_helper_unittest.cc b/chrome/browser/previews/previews_offline_helper_unittest.cc
index 3e2b7ff1..7b36360d 100644
--- a/chrome/browser/previews/previews_offline_helper_unittest.cc
+++ b/chrome/browser/previews/previews_offline_helper_unittest.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/offline_pages/request_coordinator_factory.h"
 #include "chrome/browser/offline_pages/test_offline_page_model_builder.h"
 #include "chrome/browser/offline_pages/test_request_coordinator_builder.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/offline_pages/buildflags/buildflags.h"
diff --git a/chrome/browser/printing/print_test_utils.cc b/chrome/browser/printing/print_test_utils.cc
index 3dc5387d..ab3585c1 100644
--- a/chrome/browser/printing/print_test_utils.cc
+++ b/chrome/browser/printing/print_test_utils.cc
@@ -41,11 +41,11 @@
   ticket.SetIntKey(kSettingPrinterType, type);
   ticket.SetBoolKey(kSettingRasterizePdf, false);
   ticket.SetIntKey(kSettingScaleFactor, 100);
+  ticket.SetIntKey(kSettingScalingType, FIT_TO_PAGE);
   ticket.SetIntKey(kSettingPagesPerSheet, 1);
   ticket.SetIntKey(kSettingDpiHorizontal, kTestPrinterDpi);
   ticket.SetIntKey(kSettingDpiVertical, kTestPrinterDpi);
   ticket.SetStringKey(kSettingDeviceName, kDummyPrinterName);
-  ticket.SetBoolKey(kSettingFitToPageEnabled, true);
   ticket.SetIntKey(kSettingPageWidth, 215900);
   ticket.SetIntKey(kSettingPageHeight, 279400);
   ticket.SetBoolKey(kSettingShowSystemDialog, false);
diff --git a/chrome/browser/profile_resetter/profile_resetter_browsertest.cc b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
index 44d583f7..ce6d02c 100644
--- a/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
@@ -77,7 +77,7 @@
   waiting_callback_ = true;
   net::CookieOptions cookie_options;
   cookie_manager_->GetCookieList(
-      GURL("http://" + host + "/"), cookie_options,
+      GURL("https://" + host + "/"), cookie_options,
       base::BindOnce(&RemoveCookieTester::GetCookieListCallback,
                      base::Unretained(this)));
   BlockUntilNotified();
@@ -97,10 +97,10 @@
   options.set_include_httponly();
   cookie_manager_->SetCanonicalCookie(
       net::CanonicalCookie(name, value, host, "/", base::Time(), base::Time(),
-                           base::Time(), false, false,
+                           base::Time(), true /* secure*/, false /* http only*/,
                            net::CookieSameSite::NO_RESTRICTION,
                            net::COOKIE_PRIORITY_MEDIUM),
-      "http", options,
+      "https", options,
       base::BindOnce(&RemoveCookieTester::SetCanonicalCookieCallback,
                      base::Unretained(this)));
   BlockUntilNotified();
@@ -146,7 +146,6 @@
 
 IN_PROC_BROWSER_TEST_F(ProfileResetTest, ResetCookiesAndSiteData) {
   RemoveCookieTester tester(browser()->profile());
-  std::string host_prefix("http://");
   tester.AddCookie(kCookieHostname, kCookieName, kCookieValue);
   net::CanonicalCookie cookie;
   ASSERT_TRUE(tester.GetCookie(kCookieHostname, &cookie));
@@ -155,7 +154,7 @@
 
   ResetAndWait(ProfileResetter::COOKIES_AND_SITE_DATA);
 
-  EXPECT_FALSE(tester.GetCookie(host_prefix + kCookieHostname, &cookie));
+  EXPECT_FALSE(tester.GetCookie(kCookieHostname, &cookie));
 }
 
 }  // namespace
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index 1f96099..240ca4c 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -10,17 +10,15 @@
 #include <memory>
 #include <string>
 
-#include "base/logging.h"
+#include "base/files/file_path.h"
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
-#include "chrome/browser/profiles/profile_key.h"
-#include "components/domain_reliability/clear_mode.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/browser/content_browser_client.h"
 #include "mojo/public/cpp/bindings/remote.h"
-#include "services/network/public/mojom/network_service.mojom-forward.h"
+#include "services/network/public/mojom/network_context.mojom-forward.h"
+#include "url/gurl.h"
 
 #if !defined(OS_ANDROID)
 class ChromeZoomLevelPrefs;
@@ -29,6 +27,7 @@
 class ExtensionSpecialStoragePolicy;
 class PrefService;
 class PrefStore;
+class ProfileKey;
 class TestingProfile;
 
 namespace base {
diff --git a/chrome/browser/profiles/profile_android.cc b/chrome/browser/profiles/profile_android.cc
index 32a0843..ac94f1f7 100644
--- a/chrome/browser/profiles/profile_android.cc
+++ b/chrome/browser/profiles/profile_android.cc
@@ -9,6 +9,7 @@
 #include "chrome/android/public/profiles/jni_headers/Profile_jni.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_destroyer.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/profiles/profile_key_android.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index 17b758c..508f2ea 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
-#include "base/files/file_path_watcher.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/json/json_reader.h"
@@ -670,96 +669,3 @@
     profile_destroyed_observer.Wait();
   }
 }
-
-namespace {
-
-// Watches for the destruction of the specified path (Which, in the tests that
-// use it, is typically a directory), and expects the parent directory not to be
-// deleted.
-//
-// This is used the the media cache deletion tests, so handles all the possible
-// orderings of events that could happen:
-//
-// * In PRE_* tests, the media cache could deleted before the test completes, by
-// the task posted on Profile / isolated app URLRequestContext creation.
-//
-// * In the followup test, the media cache could be deleted by the off-thread
-// delete media cache task before the FileDestructionWatcher starts watching for
-// deletion, or even before it's created.
-//
-// * In the followup test, the media cache could be deleted after the
-// FileDestructionWatcher starts watching.
-//
-// It also may be possible to get a notification of the media cache being
-// created from the the previous test, so this allows multiple watch events to
-// happen, before the path is actually deleted.
-//
-// The public methods are called on the UI thread, the private ones called on a
-// separate SequencedTaskRunner.
-class FileDestructionWatcher {
- public:
-  explicit FileDestructionWatcher(const base::FilePath& watched_file_path)
-      : watched_file_path_(watched_file_path) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  }
-
-  void WaitForDestruction() {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    DCHECK(!watcher_);
-    base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock()})
-        ->PostTask(FROM_HERE,
-                   base::BindOnce(&FileDestructionWatcher::StartWatchingPath,
-                                  base::Unretained(this)));
-    run_loop_.Run();
-    // The watcher should be destroyed before quitting the run loop, once the
-    // file has been destroyed.
-    DCHECK(!watcher_);
-
-    // Double check that the file was destroyed, and that the parent directory
-    // was not.
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    EXPECT_FALSE(base::PathExists(watched_file_path_));
-    EXPECT_TRUE(base::PathExists(watched_file_path_.DirName()));
-  }
-
- private:
-  void StartWatchingPath() {
-    DCHECK(!watcher_);
-    watcher_ = std::make_unique<base::FilePathWatcher>();
-    // Start watching before checking if the file exists, as the file could be
-    // destroyed between the existence check and when we start watching, if the
-    // order were reversed.
-    EXPECT_TRUE(watcher_->Watch(
-        watched_file_path_, false /* recursive */,
-        base::BindRepeating(&FileDestructionWatcher::OnPathChanged,
-                            base::Unretained(this))));
-    CheckIfPathExists();
-  }
-
-  void OnPathChanged(const base::FilePath& path, bool error) {
-    EXPECT_EQ(watched_file_path_, path);
-    EXPECT_FALSE(error);
-    CheckIfPathExists();
-  }
-
-  // Checks if the path exists, and if so, destroys the watcher and quits
-  // |run_loop_|.
-  void CheckIfPathExists() {
-    if (!base::PathExists(watched_file_path_)) {
-      watcher_.reset();
-      run_loop_.Quit();
-      return;
-    }
-  }
-
-  base::RunLoop run_loop_;
-  const base::FilePath watched_file_path_;
-
-  // Created and destroyed off of the UI thread, on the sequence used to watch
-  // for changes.
-  std::unique_ptr<base::FilePathWatcher> watcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(FileDestructionWatcher);
-};
-
-}  // namespace
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc
index dd00b16..cf3e851c 100644
--- a/chrome/browser/profiles/profile_shortcut_manager_win.cc
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc
@@ -28,7 +28,6 @@
 #include "base/threading/scoped_blocking_call.h"
 #include "base/win/shortcut.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
@@ -45,7 +44,6 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
 #include "skia/ext/image_operations.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkRRect.h"
@@ -731,13 +729,12 @@
 
 ProfileShortcutManagerWin::ProfileShortcutManagerWin(ProfileManager* manager)
     : profile_manager_(manager) {
-  registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
-                 content::NotificationService::AllSources());
-
   profile_manager_->GetProfileAttributesStorage().AddObserver(this);
+  profile_manager_->AddObserver(this);
 }
 
 ProfileShortcutManagerWin::~ProfileShortcutManagerWin() {
+  profile_manager_->RemoveObserver(this);
   profile_manager_->GetProfileAttributesStorage().RemoveObserver(this);
 }
 
@@ -857,6 +854,14 @@
   CreateOrUpdateProfileIcon(profile_path);
 }
 
+void ProfileShortcutManagerWin::OnProfileAdded(Profile* profile) {
+  if (profile->GetPrefs()->GetInteger(prefs::kProfileIconVersion) <
+      kCurrentProfileIconVersion) {
+    // Ensure the profile's icon file has been created.
+    CreateOrUpdateProfileIcon(profile->GetPath());
+  }
+}
+
 base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath(
     const base::FilePath& profile_path) {
   const ProfileAttributesStorage& storage =
@@ -923,18 +928,3 @@
 
   entry->SetShortcutName(params.profile_name);
 }
-
-void ProfileShortcutManagerWin::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CREATED, type);
-
-  Profile* profile =
-      content::Source<Profile>(source).ptr()->GetOriginalProfile();
-  if (profile->GetPrefs()->GetInteger(prefs::kProfileIconVersion) <
-      kCurrentProfileIconVersion) {
-    // Ensure the profile's icon file has been created.
-    CreateOrUpdateProfileIcon(profile->GetPath());
-  }
-}
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.h b/chrome/browser/profiles/profile_shortcut_manager_win.h
index 784940e..6fcb03d 100644
--- a/chrome/browser/profiles/profile_shortcut_manager_win.h
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.h
@@ -10,9 +10,8 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
+#include "chrome/browser/profiles/profile_manager_observer.h"
 #include "chrome/browser/profiles/profile_shortcut_manager.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
 
 // Internal free-standing functions that are exported here for testing.
 namespace profiles {
@@ -58,7 +57,7 @@
 
 class ProfileShortcutManagerWin : public ProfileShortcutManager,
                                   public ProfileAttributesStorage::Observer,
-                                  public content::NotificationObserver {
+                                  public ProfileManagerObserver {
  public:
   // Specifies whether only the existing shortcut should be updated, a new
   // shortcut should be created if none exist, or only the icon for this profile
@@ -98,10 +97,8 @@
                             const base::string16& old_profile_name) override;
   void OnProfileAvatarChanged(const base::FilePath& profile_path) override;
 
-  // content::NotificationObserver implementation:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
+  // ProfileManagerObserver:
+  void OnProfileAdded(Profile* profile) override;
 
  private:
   // Gives the profile path of an alternate profile than |profile_path|.
@@ -118,8 +115,6 @@
 
   ProfileManager* profile_manager_;
 
-  content::NotificationRegistrar registrar_;
-
   DISALLOW_COPY_AND_ASSIGN(ProfileShortcutManagerWin);
 };
 
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index b9c391a..c0f3295 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -266,7 +266,14 @@
 let isDarkModeEnabled = false;
 
 /** Used to prevent inline autocompleting recently deleted output. */
-let isDeleting = false;
+let isDeletingInput = false;
+
+/**
+ * The rendered autocomplete match currently being deleted, or null if there
+ * isn't one.
+ * @type {?Element}
+ */
+let matchElBeingDeleted = null;
 
 /**
  * The last blacklisted tile rid if any, which by definition should not be
@@ -1075,6 +1082,7 @@
 /** @param {!DeleteAutocompleteMatchResult} result */
 function onDeleteAutocompleteMatch(result) {
   if (!result.success) {
+    matchElBeingDeleted = null;
     return;
   }
 
@@ -1086,6 +1094,7 @@
   const wasFocused = matchEls[selected].contains(document.activeElement);
 
   populateAutocompleteMatches(result.matches);
+  matchElBeingDeleted = null;
 
   if (result.matches.length === 0) {
     if (wasFocused) {
@@ -1172,7 +1181,7 @@
 
   // If the user is deleting content, don't quickly re-suggest the same
   // output.
-  if (!isDeleting) {
+  if (!isDeletingInput) {
     const first = result.matches[0];
     if (first.allowedToBeDefaultMatch && first.inlineAutocompletion) {
       updateRealboxOutput({inline: first.inlineAutocompletion});
@@ -1242,6 +1251,7 @@
 
   if (key === 'Delete' && e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey) {
     if (autocompleteMatches[selected].supportsDeletion) {
+      matchElBeingDeleted = matchEls[selected];
       window.chrome.embeddedSearch.searchBox.deleteAutocompleteMatch(selected);
       e.preventDefault();
     }
@@ -1326,6 +1336,13 @@
 
 /** @param {Event} e */
 function onRealboxWrapperFocusOut(e) {
+  const target = /** @type {Element} */ (e.target);
+  if (matchElBeingDeleted && matchElBeingDeleted.contains(target)) {
+    // When a match is being deleted, the focus gets dropped temporariliy as the
+    // element is deleted from the DOM. Don't stop autocomplete in those cases.
+    return;
+  }
+
   const relatedTarget = /** @type {Element} */ (e.relatedTarget);
   if (!$(IDS.REALBOX_INPUT_WRAPPER).contains(relatedTarget)) {
     hideRealboxMatches();  // Hide but don't clear input.
@@ -1452,6 +1469,7 @@
       icon.title = configData.translatedStrings.removeSuggestion;
       icon.classList.add(CLASSES.REMOVE_ICON);
       icon.onclick = e => {
+        matchElBeingDeleted = matchEl;
         window.chrome.embeddedSearch.searchBox.deleteAutocompleteMatch(i);
         e.preventDefault();
       };
@@ -1878,7 +1896,7 @@
         preserveSelection ? oldSelectionStart : newAll.length;
   }
 
-  isDeleting = userDeletedOutput(lastOutput, newOutput);
+  isDeletingInput = userDeletedOutput(lastOutput, newOutput);
   lastOutput = newOutput;
 }
 
diff --git a/chrome/browser/resources/print_preview/data/model.js b/chrome/browser/resources/print_preview/data/model.js
index e248222..bcdc1711 100644
--- a/chrome/browser/resources/print_preview/data/model.js
+++ b/chrome/browser/resources/print_preview/data/model.js
@@ -1259,14 +1259,12 @@
               print_preview.ScalingType.CUSTOM ?
           parseInt(this.getSettingValue('scaling'), 10) :
           100,
+      scalingType: this.getSettingValue(scalingSettingKey),
       pagesPerSheet: this.getSettingValue('pagesPerSheet'),
       dpiHorizontal: (dpi && 'horizontal_dpi' in dpi) ? dpi.horizontal_dpi : 0,
       dpiVertical: (dpi && 'vertical_dpi' in dpi) ? dpi.vertical_dpi : 0,
       dpiDefault: (dpi && 'is_default' in dpi) ? dpi.is_default : false,
       deviceName: destination.id,
-      // TODO(dhoss): Pass the enum in the ticket.
-      fitToPageEnabled: this.getSettingValue(scalingSettingKey) ===
-          print_preview.ScalingType.FIT_TO_PAGE,
       pageWidth: this.pageSize.width,
       pageHeight: this.pageSize.height,
       showSystemDialog: showSystemDialog,
diff --git a/chrome/browser/resources/print_preview/data/scaling.js b/chrome/browser/resources/print_preview/data/scaling.js
index be917a4..49c8d5b 100644
--- a/chrome/browser/resources/print_preview/data/scaling.js
+++ b/chrome/browser/resources/print_preview/data/scaling.js
@@ -5,11 +5,16 @@
 cr.define('print_preview', function() {
   'use strict';
 
-  /** @enum {number} */
+  /**
+   * Must be kept in sync with the C++ ScalingType enum in
+   * printing/print_job_constants.h.
+   * @enum {number}
+   */
   const ScalingType = {
     DEFAULT: 0,
     FIT_TO_PAGE: 1,
-    CUSTOM: 2,
+    FIT_TO_PAPER: 2,
+    CUSTOM: 3,
   };
 
   // Export
diff --git a/chrome/browser/resources/print_preview/ui/preview_area.js b/chrome/browser/resources/print_preview/ui/preview_area.js
index 882c0f37..bee4968 100644
--- a/chrome/browser/resources/print_preview/ui/preview_area.js
+++ b/chrome/browser/resources/print_preview/ui/preview_area.js
@@ -605,10 +605,7 @@
 
     // Simple settings: ranges, layout, header/footer, pages per sheet, fit to
     // page, css background, selection only, rasterize, scaling, dpi
-    const isScalingTypeFitToPage = this.getSettingValue('scalingTypePdf') ===
-        print_preview.ScalingType.FIT_TO_PAGE;
-    if (isScalingTypeFitToPage !== lastTicket.fitToPageEnabled ||
-        !areRangesEqual(
+    if (!areRangesEqual(
             /** @type {!Array<{from: number, to: number}>} */
             (this.getSettingValue('ranges')), lastTicket.pageRange) ||
         this.getSettingValue('layout') !== lastTicket.landscape ||
@@ -620,7 +617,7 @@
         this.getSettingValue('selectionOnly') !==
             lastTicket.shouldPrintSelectionOnly ||
         this.getSettingValue('rasterize') !== lastTicket.rasterizePDF ||
-        this.getScaleFactorForTicket_() !== lastTicket.scaleFactor) {
+        this.isScalingChanged_(lastTicket)) {
       return true;
     }
 
@@ -658,17 +655,48 @@
         /** @type {boolean} */ (this.getSettingValue('color')));
   },
 
-  /** @return {number} Scale factor. */
+  /** @return {number} Scale factor for print ticket. */
   getScaleFactorForTicket_: function() {
-    const scalingSettingKey = this.getSetting('scalingTypePdf').available ?
-        'scalingTypePdf' :
-        'scalingType';
-    return this.getSettingValue(scalingSettingKey) ===
+    return this.getSettingValue(this.getScalingSettingKey_()) ===
             print_preview.ScalingType.CUSTOM ?
         parseInt(this.getSettingValue('scaling'), 10) :
         100;
   },
 
+  /** @return {string} Appropriate key for the scaling type setting. */
+  getScalingSettingKey_: function() {
+    return this.getSetting('scalingTypePdf').available ? 'scalingTypePdf' :
+                                                         'scalingType';
+  },
+
+  /**
+   * @param {Object} lastTicket Last print ticket.
+   * @return {boolean} Whether new scaling settings update the previewed
+   *     document.
+   */
+  isScalingChanged_: function(lastTicket) {
+    // Preview always updates if the scale factor is changed.
+    if (this.getScaleFactorForTicket_() !== lastTicket.scaleFactor) {
+      return true;
+    }
+
+    // If both scale factors and type match, no scaling change happened.
+    const scalingType = this.getSettingValue(this.getScalingSettingKey_());
+    if (scalingType === lastTicket.scalingType) {
+      return false;
+    }
+
+    // Scaling doesn't always change because of a scalingType change. Changing
+    // between custom scaling with a scale factor of 100 and default scaling
+    // makes no difference.
+    const defaultToCustom = scalingType === print_preview.ScalingType.DEFAULT &&
+        lastTicket.scalingType === print_preview.ScalingType.CUSTOM;
+    const customToDefault = scalingType === print_preview.ScalingType.CUSTOM &&
+        lastTicket.scalingType === print_preview.ScalingType.DEFAULT;
+
+    return !defaultToCustom && !customToDefault;
+  },
+
   /**
    * @param {string} dpiField The field in dpi to retrieve.
    * @return {number} Field value.
@@ -703,9 +731,8 @@
       isFirstRequest: this.inFlightRequestId_ == 0,
       requestID: this.inFlightRequestId_,
       previewModifiable: this.documentModifiable,
-      fitToPageEnabled: this.getSettingValue('scalingTypePdf') ===
-          print_preview.ScalingType.FIT_TO_PAGE,
       scaleFactor: this.getScaleFactorForTicket_(),
+      scalingType: this.getSettingValue(this.getScalingSettingKey_()),
       shouldPrintBackgrounds: this.getSettingValue('cssBackground'),
       shouldPrintSelectionOnly: this.getSettingValue('selectionOnly'),
       // NOTE: Even though the remaining fields don't directly relate to the
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html
index 078fc8f..86bd158 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.html
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -22,10 +22,19 @@
     <settings-animated-pages id="pages" current-route="{{currentRoute}}"
         section="a11y" focus-config="[[focusConfig_]]">
       <div route-path="default">
-        <cr-link-row class="hr" id="captions" label="$i18n{captionsTitle}"
-            on-click="onCaptionsClick_" external$="[[captionSettingsOpensExternally_]]">
+<if expr="chromeos">
+        <cr-link-row class="hr" id="subpage-trigger"
+            label="$i18n{manageAccessibilityFeatures}"
+            on-click="onManageSystemAccessibilityFeaturesTap_"
+            sub-label="$i18n{moreFeaturesLinkDescription}"
+            hidden="[[showOsSettings_]]" external>
         </cr-link-row>
+</if>
 <if expr="not chromeos">
+        <cr-link-row class="hr" id="captions" label="$i18n{captionsTitle}"
+            on-click="onCaptionsClick_"
+            external$="[[captionSettingsOpensExternally_]]">
+        </cr-link-row>
         <settings-toggle-button
             id="a11yImageLabels"
             hidden$="[[!showAccessibilityLabelsSetting_]]"
@@ -36,7 +45,7 @@
         </settings-toggle-button>
 </if>
 <if expr="chromeos">
-        <template is="dom-if" if="[[pageVisibility.webstoreLink]]">
+        <template is="dom-if" if="[[showOsSettings_]]">
           <settings-toggle-button
               id="a11yImageLabels"
               hidden$="[[!showAccessibilityLabelsSetting_]]"
@@ -58,7 +67,7 @@
 </if>
         <cr-link-row class="hr" label="$i18n{moreFeaturesLink}"
             on-click="onMoreFeaturesLinkClick_" sub-label="$i18n{a11yWebStore}"
-            hidden="[[pageVisibility.webstoreLink]]" external>
+            hidden="[[showOsSettings_]]" external>
         </cr-link-row>
       </div>
 <if expr="not is_macosx">
@@ -73,7 +82,17 @@
       </template>
 </if>
 <if expr="chromeos">
-      <template is="dom-if" if="[[pageVisibility.webstoreLink]]">
+      <template is="dom-if" if="[[showCaptionSettings_]]">
+        <template is="dom-if" route-path="/manageAccessibility/captions">
+          <settings-subpage
+              associated-control="[[$$('#subpage-trigger')]]"
+              page-title="$i18n{captionsTitle}">
+            <settings-captions prefs="{{prefs}}">
+            </settings-captions>
+          </settings-subpage>
+        </template>
+      </template>
+      <template is="dom-if" if="[[showOsSettings_]]">
         <template is="dom-if" route-path="/manageAccessibility">
           <settings-subpage
               associated-control="[[$$('#subpage-trigger')]]"
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.js b/chrome/browser/resources/settings/a11y_page/a11y_page.js
index 3104568..e5c1a018 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.js
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.js
@@ -68,6 +68,17 @@
     },
 
     /**
+     * Whether to show OS settings.
+     * @private {boolean}
+     */
+    showOsSettings_: {
+      type: Boolean,
+      value: function() {
+        return loadTimeData.getBoolean('showOSSettings');
+      },
+    },
+
+    /**
      * Whether the caption settings link opens externally.
      * @private {boolean}
      */
@@ -136,6 +147,11 @@
   onManageAccessibilityFeaturesTap_: function() {
     settings.navigateTo(settings.routes.MANAGE_ACCESSIBILITY);
   },
+
+  /** @private */
+  onManageSystemAccessibilityFeaturesTap_: function() {
+    window.location.href = 'chrome://os-settings/manageAccessibility';
+  },
   // </if>
 
   /** private */
diff --git a/chrome/browser/resources/signin/BUILD.gn b/chrome/browser/resources/signin/BUILD.gn
new file mode 100644
index 0000000..0dbc17e
--- /dev/null
+++ b/chrome/browser/resources/signin/BUILD.gn
@@ -0,0 +1,18 @@
+# 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("//tools/polymer/polymer.gni")
+
+group("polymer3_elements") {
+  deps = [
+    ":signin_shared_css_module",
+    "sync_confirmation:polymer3_elements",
+  ]
+}
+
+polymer_modulizer("signin_shared_css") {
+  html_file = "signin_shared_css.html"
+  js_file = "signin_shared_css.js"
+  html_type = "v3-ready"
+}
diff --git a/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html b/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html
index b0ce42a..2cb6a34e 100644
--- a/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html
+++ b/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html
@@ -7,7 +7,7 @@
     <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html">
     <link rel="import" href="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.html">
     <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-    <link rel="import" href="signin_shared_css.html">
+    <link rel="import" href="signin_shared_old_css.html">
     <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
     <link rel="import" href="chrome://resources/html/cr.html">
     <link rel="import" href="chrome://resources/html/load_time_data.html">
diff --git a/chrome/browser/resources/signin/signin_error/signin_error.html b/chrome/browser/resources/signin/signin_error/signin_error.html
index fb8c5a7..251e1fa 100644
--- a/chrome/browser/resources/signin/signin_error/signin_error.html
+++ b/chrome/browser/resources/signin/signin_error/signin_error.html
@@ -5,7 +5,7 @@
     <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
     <link rel="import" href="chrome://resources/html/polymer.html">
     <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-    <link rel="import" href="signin_shared_css.html">
+    <link rel="import" href="signin_shared_old_css.html">
     <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
     <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
     <link rel="import" href="chrome://resources/html/cr.html">
diff --git a/chrome/browser/resources/signin/signin_shared_css.html b/chrome/browser/resources/signin/signin_shared_css.html
index 8267ae5..7922722 100644
--- a/chrome/browser/resources/signin/signin_shared_css.html
+++ b/chrome/browser/resources/signin/signin_shared_css.html
@@ -1,45 +1,41 @@
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-
 <!-- Common styles for signin-related tab modal dialogs. -->
-<dom-module id="signin-dialog-shared">
-  <template>
-    <style>
-      a {
-        color: var(--cr-link-color);
-        text-decoration: none;
-      }
+<template>
+  <style>
+    a {
+      color: var(--cr-link-color);
+      text-decoration: none;
+    }
 
-      body {
-        margin: 0;
-        padding: 0;
-      }
+    body {
+      margin: 0;
+      padding: 0;
+    }
 
-      .container {
-        color: var(--cr-primary-text-color);
-        width: 448px;
-      }
+    .container {
+      color: var(--cr-primary-text-color);
+      width: 448px;
+    }
 
-      .top-title-bar {
-        align-items: center;
-        border-bottom: var(--cr-separator-line);
-        display: flex;
-        font-size: 16px;
-        height: 52px;
-        padding: 0 24px;
-      }
+    .top-title-bar {
+      align-items: center;
+      border-bottom: var(--cr-separator-line);
+      display: flex;
+      font-size: 16px;
+      height: 52px;
+      padding: 0 24px;
+    }
 
-      .action-container {
-        display: flex;
-        justify-content: flex-end;
-        padding: 16px;
-      }
+    .action-container {
+      display: flex;
+      justify-content: flex-end;
+      padding: 16px;
+    }
 
 <if expr="is_macosx or is_linux">
-      .action-container {
-        flex-flow: row-reverse;
-        justify-content: flex-start;
-      }
+    .action-container {
+      flex-flow: row-reverse;
+      justify-content: flex-start;
+    }
 </if>
-    </style>
-  </template>
-</dom-module>
+  </style>
+</template>
diff --git a/chrome/browser/resources/signin/signin_shared_css.js b/chrome/browser/resources/signin/signin_shared_css.js
new file mode 100644
index 0000000..ce2743ca
--- /dev/null
+++ b/chrome/browser/resources/signin/signin_shared_css.js
@@ -0,0 +1,11 @@
+/* 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 'chrome://resources/cr_elements/shared_vars_css.m.js';
+
+import 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+const styleElement = document.createElement('dom-module');
+styleElement.setAttribute('assetpath', 'chrome://resources/');
+styleElement.innerHTML = `{__html_template__}`;
+styleElement.register('signin-dialog-shared');
diff --git a/chrome/browser/resources/signin/signin_shared_old_css.html b/chrome/browser/resources/signin/signin_shared_old_css.html
new file mode 100644
index 0000000..8267ae5
--- /dev/null
+++ b/chrome/browser/resources/signin/signin_shared_old_css.html
@@ -0,0 +1,45 @@
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+
+<!-- Common styles for signin-related tab modal dialogs. -->
+<dom-module id="signin-dialog-shared">
+  <template>
+    <style>
+      a {
+        color: var(--cr-link-color);
+        text-decoration: none;
+      }
+
+      body {
+        margin: 0;
+        padding: 0;
+      }
+
+      .container {
+        color: var(--cr-primary-text-color);
+        width: 448px;
+      }
+
+      .top-title-bar {
+        align-items: center;
+        border-bottom: var(--cr-separator-line);
+        display: flex;
+        font-size: 16px;
+        height: 52px;
+        padding: 0 24px;
+      }
+
+      .action-container {
+        display: flex;
+        justify-content: flex-end;
+        padding: 16px;
+      }
+
+<if expr="is_macosx or is_linux">
+      .action-container {
+        flex-flow: row-reverse;
+        justify-content: flex-start;
+      }
+</if>
+    </style>
+  </template>
+</dom-module>
diff --git a/chrome/browser/resources/signin/sync_confirmation/BUILD.gn b/chrome/browser/resources/signin/sync_confirmation/BUILD.gn
index 6f36b5e3..4492e543 100644
--- a/chrome/browser/resources/signin/sync_confirmation/BUILD.gn
+++ b/chrome/browser/resources/signin/sync_confirmation/BUILD.gn
@@ -3,8 +3,23 @@
 # found in the LICENSE file.
 
 import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
 
-js_type_check("closure_compile") {
+group("closure_compile") {
+  deps = [
+    ":closure_compile_polymer2",
+    ":closure_compile_polymer3",
+  ]
+}
+
+js_type_check("closure_compile_polymer2") {
+  deps = [
+    ":sync_disabled_confirmation",
+  ]
+}
+
+js_type_check("closure_compile_polymer3") {
+  is_polymer3 = true
   deps = [
     ":sync_confirmation",
     ":sync_confirmation_app",
@@ -15,25 +30,46 @@
 js_library("sync_confirmation") {
   deps = [
     ":sync_confirmation_browser_proxy",
-    "//ui/webui/resources/js:cr",
+    "//ui/webui/resources/js:cr.m",
   ]
 }
 
 js_library("sync_confirmation_app") {
   deps = [
     ":sync_confirmation_browser_proxy",
-    "//ui/webui/resources/js:cr",
-    "//ui/webui/resources/js:load_time_data",
-    "//ui/webui/resources/js:web_ui_listener_behavior",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js:load_time_data.m",
+    "//ui/webui/resources/js:web_ui_listener_behavior.m",
   ]
 }
 
 js_library("sync_confirmation_browser_proxy") {
   deps = [
-    "//ui/webui/resources/js:cr",
+    "//ui/webui/resources/js:cr.m",
   ]
   externs_list = [
     "$externs_path/chrome_send.js",
     "$externs_path/metrics_private.js",
   ]
 }
+
+js_library("sync_disabled_confirmation") {
+  deps = [
+    "//ui/webui/resources/js:assert",
+    "//ui/webui/resources/js:cr",
+    "//ui/webui/resources/js:util",
+  ]
+}
+
+group("polymer3_elements") {
+  deps = [
+    ":sync_confirmation_app_module",
+  ]
+}
+
+polymer_modulizer("sync_confirmation_app") {
+  html_file = "sync_confirmation_app.html"
+  js_file = "sync_confirmation_app.js"
+  html_type = "v3-ready"
+}
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
index 52d93830..328bfda 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
@@ -3,7 +3,7 @@
   <head>
     <meta charset="utf-8">
     <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
-    <link rel="import" href="sync_confirmation_app.html"></link>
+    <script type="module" src="sync_confirmation_app.js"></script>
     <style>
       body {
         margin: 0;
@@ -21,7 +21,5 @@
     <sync-confirmation-app></sync-confirmation-app>
   </body>
   <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
-  <link rel="import" href="chrome://resources/html/cr.html"></script>
-  <link rel="import" href="chrome://resources/html/util.html"></script>
-  <script src="sync_confirmation.js"></script>
+  <script type="module" src="sync_confirmation.js"></script>
 </html>
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
index ee5ac8ef..04c560f 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
@@ -2,31 +2,27 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
-cr.define('sync.confirmation', function() {
-  'use strict';
+import {addWebUIListener} from 'chrome://resources/js/cr.m.js';
 
-  function initialize() {
-    cr.addWebUIListener('clear-focus', clearFocus);
-    const syncConfirmationBrowserProxy =
-        sync.confirmation.SyncConfirmationBrowserProxyImpl.getInstance();
-    // Prefer using |document.body.offsetHeight| instead of
-    // |document.body.scrollHeight| as it returns the correct height of the
-    // even when the page zoom in Chrome is different than 100%.
-    syncConfirmationBrowserProxy.initializedWithSize(
-        [document.body.offsetHeight]);
-    // The web dialog size has been initialized, so reset the body width to
-    // auto. This makes sure that the body only takes up the viewable width,
-    // e.g. when there is a scrollbar.
-    document.body.style.width = 'auto';
-  }
+import {SyncConfirmationBrowserProxyImpl} from './sync_confirmation_browser_proxy.js';
 
-  function clearFocus() {
-    document.activeElement.blur();
-  }
+function initialize() {
+  addWebUIListener('clear-focus', clearFocus);
+  const syncConfirmationBrowserProxy =
+      SyncConfirmationBrowserProxyImpl.getInstance();
+  // Prefer using |document.body.offsetHeight| instead of
+  // |document.body.scrollHeight| as it returns the correct height of the
+  // even when the page zoom in Chrome is different than 100%.
+  syncConfirmationBrowserProxy.initializedWithSize(
+      [document.body.offsetHeight]);
+  // The web dialog size has been initialized, so reset the body width to
+  // auto. This makes sure that the body only takes up the viewable width,
+  // e.g. when there is a scrollbar.
+  document.body.style.width = 'auto';
+}
 
-  return {
-    initialize: initialize,
-  };
-});
+function clearFocus() {
+  document.activeElement.blur();
+}
 
-document.addEventListener('DOMContentLoaded', sync.confirmation.initialize);
+document.addEventListener('DOMContentLoaded', initialize);
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
index fffc18a7..818fad1 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
@@ -1,169 +1,152 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
+<style include="signin-dialog-shared">
+  :host {
+    color: var(--cr-primary-text-color);
+    display: block;
+  }
 
-<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
-<link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/load_time_data.html">
-<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="signin_shared_css.html">
-<link rel="import" href="sync_confirmation_browser_proxy.html">
+  cr-button {
+    padding-inline-end: 16px;
+    padding-inline-start: 16px;
+  }
 
-<script src="chrome://sync-confirmation/strings.js"></script>
+  .action-container {
+    bottom: 0;
+    box-sizing: border-box;
+    position: absolute;
+    width: 100%;
+  }
 
-<dom-module id="sync-confirmation-app">
-  <template>
-    <style include="signin-dialog-shared">
-      :host {
-        color: var(--cr-primary-text-color);
-        display: block;
-      }
-
-      cr-button {
-        padding-inline-end: 16px;
-        padding-inline-start: 16px;
-      }
-
-      .action-container {
-        bottom: 0;
-        box-sizing: border-box;
-        position: absolute;
-        width: 100%;
-      }
-
-      cr-button:not(.action-button) {
-        margin-inline-start: 8px;
-      }
+  cr-button:not(.action-button) {
+    margin-inline-start: 8px;
+  }
 
 <if expr="is_macosx or is_linux">
-      /* This works together with the button-flip in signin-dialog-shared. */
-      cr-button:not(.action-button) {
-        margin-inline-end: 8px;
-        margin-inline-start: 0;
-      }
+  /* This works together with the button-flip in signin-dialog-shared. */
+  cr-button:not(.action-button) {
+    margin-inline-end: 8px;
+    margin-inline-start: 0;
+  }
 </if>
 
-      #illustration-container {
-        height: 168px;
-        margin-bottom: 32px;
-        position: relative;
-        width: 100%;
-      }
+  #illustration-container {
+    height: 168px;
+    margin-bottom: 32px;
+    position: relative;
+    width: 100%;
+  }
 
-      #illustration {
-        background: url(./images/sync_confirmation_illustration.svg);
-        background-size: 100% 100%;
-        height: 100%;
-        position: absolute;
-        top: 0;
-        width: 100%;
-      }
+  #illustration {
+    background: url(./images/sync_confirmation_illustration.svg);
+    background-size: 100% 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    width: 100%;
+  }
 
-      @media (prefers-color-scheme: dark) {
-        #illustration {
-          background-image:
-              url(./images/sync_confirmation_illustration_dark.svg);
-        }
-      }
+  @media (prefers-color-scheme: dark) {
+    #illustration {
+      background-image:
+          url(./images/sync_confirmation_illustration_dark.svg);
+    }
+  }
 
-      #illustration-container > img {
-        border-radius: 50%;
-        height: 68px;
-        left: 0;
-        margin: auto;
-        position: absolute;
-        right: 0;
-        top: 96px;
-        width: 68px;
-      }
+  #illustration-container > img {
+    border-radius: 50%;
+    height: 68px;
+    left: 0;
+    margin: auto;
+    position: absolute;
+    right: 0;
+    top: 96px;
+    width: 68px;
+  }
 
-      .heading {
-        font-weight: normal;
-        margin-bottom: 32px;
-        padding: 0 24px;
-        text-align: center;
-      }
+  .heading {
+    font-weight: normal;
+    margin-bottom: 32px;
+    padding: 0 24px;
+    text-align: center;
+  }
 
-      #content-container {
-        /* Saves space for button row. */
-        padding-bottom: 96px;
-        position: relative;
-        width: 100%;
-      }
+  #content-container {
+    /* Saves space for button row. */
+    padding-bottom: 96px;
+    position: relative;
+    width: 100%;
+  }
 
-      .message-container {
-        line-height: 20px;
-        margin-bottom: 16px;
-        padding: 0 24px;
-      }
+  .message-container {
+    line-height: 20px;
+    margin-bottom: 16px;
+    padding: 0 24px;
+  }
 
-      .secondary {
-        color: var(--cr-secondary-text-color);
-      }
+  .secondary {
+    color: var(--cr-secondary-text-color);
+  }
 
-      @media (prefers-color-scheme: light) {
-        #grey-banner {
-          background: var(--paper-grey-50);
-          height: 128px;
-          top: 0;
-          width: 100%;
-        }
-      }
+  @media (prefers-color-scheme: light) {
+    #grey-banner {
+      background: var(--paper-grey-50);
+      height: 128px;
+      top: 0;
+      width: 100%;
+    }
+  }
 
-      #footer {
-        margin-bottom: 0;
-        padding-top: 12px;
-      }
+  #footer {
+    margin-bottom: 0;
+    padding-top: 12px;
+  }
 
-      #settingsButton {
-        left: 16px;
-        position: absolute;
-      }
+  #settingsButton {
+    left: 16px;
+    position: absolute;
+  }
 
-      :host-context([dir='rtl']) #settingsButton {
-        left: auto;
-        right: 16px;
-      }
-    </style>
+  :host-context([dir='rtl']) #settingsButton {
+    left: auto;
+    right: 16px;
+  }
+</style>
 
-    <!--
-      Use the 'consent-description' attribute to annotate all the UI elements
-      that are part of the text the user reads before consenting to the Sync
-      data collection . Similarly, use 'consent-confirmation' on UI elements on
-      which user clicks to indicate consent.
-    -->
+<!--
+  Use the 'consent-description' attribute to annotate all the UI elements
+  that are part of the text the user reads before consenting to the Sync
+  data collection . Similarly, use 'consent-confirmation' on UI elements on
+  which user clicks to indicate consent.
+-->
 
-    <div id="illustration-container">
-      <div id="grey-banner"></div>
-      <div id="illustration"></div>
-      <img src="[[accountImageSrc_]]">
+<div id="illustration-container">
+  <div id="grey-banner"></div>
+  <div id="illustration"></div>
+  <img src="[[accountImageSrc_]]">
+</div>
+<div id="content-container">
+  <h1 id="syncConfirmationHeading" class="heading" consent-description>
+    $i18n{syncConfirmationTitle}
+  </h1>
+  <div class="message-container">
+    <div consent-description>$i18n{syncConfirmationSyncInfoTitle}</div>
+    <div class="secondary" consent-description>
+      $i18n{syncConfirmationSyncInfoDesc}
     </div>
-    <div id="content-container">
-      <h1 id="syncConfirmationHeading" class="heading" consent-description>
-        $i18n{syncConfirmationTitle}
-      </h1>
-      <div class="message-container">
-        <div consent-description>$i18n{syncConfirmationSyncInfoTitle}</div>
-        <div class="secondary" consent-description>
-          $i18n{syncConfirmationSyncInfoDesc}
-        </div>
-      </div>
-      <div id="footer" class="message-container secondary">
-        $i18n{syncConfirmationSettingsInfo}
-      </div>
-      <div class="action-container">
-        <cr-button class="action-button" id="confirmButton"
-            on-click="onConfirm_" consent-confirmation>
-          $i18n{syncConfirmationConfirmLabel}
-        </cr-button>
-        <cr-button on-click="onUndo_">
-          $i18n{syncConfirmationUndoLabel}
-        </cr-button>
-        <cr-button id="settingsButton" on-click="onGoToSettings_"
-            consent-confirmation>
-          $i18n{syncConfirmationSettingsLabel}
-        </cr-button>
-      </div>
-    </div>
-  </template>
-  <script src="sync_confirmation_app.js"></script>
-</dom-module>
+  </div>
+  <div id="footer" class="message-container secondary">
+    $i18n{syncConfirmationSettingsInfo}
+  </div>
+  <div class="action-container">
+    <cr-button class="action-button" id="confirmButton"
+        on-click="onConfirm_" consent-confirmation>
+      $i18n{syncConfirmationConfirmLabel}
+    </cr-button>
+    <cr-button on-click="onUndo_">
+      $i18n{syncConfirmationUndoLabel}
+    </cr-button>
+    <cr-button id="settingsButton" on-click="onGoToSettings_"
+        consent-confirmation>
+      $i18n{syncConfirmationSettingsLabel}
+    </cr-button>
+  </div>
+</div>
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js
index 57f29b84..2e9c4aa 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js
@@ -2,9 +2,23 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/polymer/v3_0/paper-styles/color.js';
+import './strings.m.js';
+import './signin_shared_css.js';
+
+import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
+import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {SyncConfirmationBrowserProxy, SyncConfirmationBrowserProxyImpl} from './sync_confirmation_browser_proxy.js';
+
 Polymer({
   is: 'sync-confirmation-app',
 
+  _template: html`{__html_template__}`,
+
   behaviors: [
     WebUIListenerBehavior,
   ],
@@ -19,7 +33,7 @@
     },
   },
 
-  /** @private {?sync.confirmation.SyncConfirmationBrowserProxy} */
+  /** @private {?SyncConfirmationBrowserProxy} */
   syncConfirmationBrowserProxy_: null,
 
   /** @private {?function(Event)} */
@@ -28,7 +42,7 @@
   /** @override */
   attached: function() {
     this.syncConfirmationBrowserProxy_ =
-        sync.confirmation.SyncConfirmationBrowserProxyImpl.getInstance();
+        SyncConfirmationBrowserProxyImpl.getInstance();
     this.boundKeyDownHandler_ = this.onKeyDown_.bind(this);
     // This needs to be bound to document instead of "this" because the dialog
     // window opens initially, the focus level is only on document, so the key
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_browser_proxy.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_browser_proxy.html
deleted file mode 100644
index 636a6b9..0000000
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_browser_proxy.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<link rel="import" href="chrome://resources/html/cr.html">
-<script src="sync_confirmation_browser_proxy.js"></script>
\ No newline at end of file
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_browser_proxy.js b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_browser_proxy.js
index c5cb104a..b98c5ee 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_browser_proxy.js
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_browser_proxy.js
@@ -6,75 +6,69 @@
  * @fileoverview A helper object used by the sync confirmation dialog to
  * interact with the browser.
  */
+import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
 
-cr.define('sync.confirmation', function() {
-  /** @interface */
-  class SyncConfirmationBrowserProxy {
-    /**
-     * Called when the user confirms the Sync Confirmation dialog.
-     * @param {!Array<string>} description Strings that the user was presented
-     *     with in the UI.
-     * @param {string} confirmation Text of the element that the user
-     *     clicked on.
-     */
-    confirm(description, confirmation) {}
+/** @interface */
+export class SyncConfirmationBrowserProxy {
+  /**
+   * Called when the user confirms the Sync Confirmation dialog.
+   * @param {!Array<string>} description Strings that the user was presented
+   *     with in the UI.
+   * @param {string} confirmation Text of the element that the user
+   *     clicked on.
+   */
+  confirm(description, confirmation) {}
 
-    /**
-     * Called when the user undoes the Sync confirmation.
-     */
-    undo() {}
+  /**
+   * Called when the user undoes the Sync confirmation.
+   */
+  undo() {}
 
-    /**
-     * Called when the user clicks on the Settings link in
-     *     the Sync Confirmation dialog.
-     * @param {!Array<string>} description Strings that the user was presented
-     *     with in the UI.
-     * @param {string} confirmation Text of the element that the user
-     *     clicked on.
-     */
-    goToSettings(description, confirmation) {}
+  /**
+   * Called when the user clicks on the Settings link in
+   *     the Sync Confirmation dialog.
+   * @param {!Array<string>} description Strings that the user was presented
+   *     with in the UI.
+   * @param {string} confirmation Text of the element that the user
+   *     clicked on.
+   */
+  goToSettings(description, confirmation) {}
 
-    /** @param {!Array<number>} height */
-    initializedWithSize(height) {}
+  /** @param {!Array<number>} height */
+  initializedWithSize(height) {}
 
-    /**
-     * Called when the WebUIListener for "account-image-changed" was added.
-     */
-    requestAccountImage() {}
+  /**
+   * Called when the WebUIListener for "account-image-changed" was added.
+   */
+  requestAccountImage() {}
+}
+
+/** @implements {SyncConfirmationBrowserProxy} */
+export class SyncConfirmationBrowserProxyImpl {
+  /** @override */
+  confirm(description, confirmation) {
+    chrome.send('confirm', [description, confirmation]);
   }
 
-  /** @implements {sync.confirmation.SyncConfirmationBrowserProxy} */
-  class SyncConfirmationBrowserProxyImpl {
-    /** @override */
-    confirm(description, confirmation) {
-      chrome.send('confirm', [description, confirmation]);
-    }
-
-    /** @override */
-    undo() {
-      chrome.send('undo');
-    }
-
-    /** @override */
-    goToSettings(description, confirmation) {
-      chrome.send('goToSettings', [description, confirmation]);
-    }
-
-    /** @override */
-    initializedWithSize(height) {
-      chrome.send('initializedWithSize', height);
-    }
-
-    /** @override */
-    requestAccountImage() {
-      chrome.send('accountImageRequest');
-    }
+  /** @override */
+  undo() {
+    chrome.send('undo');
   }
 
-  cr.addSingletonGetter(SyncConfirmationBrowserProxyImpl);
+  /** @override */
+  goToSettings(description, confirmation) {
+    chrome.send('goToSettings', [description, confirmation]);
+  }
 
-  return {
-    SyncConfirmationBrowserProxy: SyncConfirmationBrowserProxy,
-    SyncConfirmationBrowserProxyImpl: SyncConfirmationBrowserProxyImpl,
-  };
-});
+  /** @override */
+  initializedWithSize(height) {
+    chrome.send('initializedWithSize', height);
+  }
+
+  /** @override */
+  requestAccountImage() {
+    chrome.send('accountImageRequest');
+  }
+}
+
+addSingletonGetter(SyncConfirmationBrowserProxyImpl);
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.html b/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.html
index 524cb04..059bc92 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.html
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.html
@@ -11,7 +11,7 @@
     <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
     <link rel="import" href="chrome://resources/html/polymer.html">
     <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-    <link rel="import" href="signin_shared_css.html">
+    <link rel="import" href="signin_shared_old_css.html">
     <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
     <custom-style>
       <style include="signin-dialog-shared">
diff --git a/chrome/browser/resources/tab_strip/tab.html b/chrome/browser/resources/tab_strip/tab.html
index 3386afbc..85517760 100644
--- a/chrome/browser/resources/tab_strip/tab.html
+++ b/chrome/browser/resources/tab_strip/tab.html
@@ -44,7 +44,6 @@
     margin-inline-end: 8px;
     margin-inline-start: 12px;
     max-width: var(--favicon-size);
-    overflow: hidden;
     position: relative;
     /* When transitioning to the default visible state, the margin and max-width
      * transitions should finish first, then the opacity should be set to 1.
@@ -164,6 +163,10 @@
     display: block;
   }
 
+  :host([active][blocked_]) #blocked {
+    display: none;
+  }
+
   #titleText {
     font-size: 100%;
     font-weight: normal;
diff --git a/chrome/browser/resources/tab_strip/tab.js b/chrome/browser/resources/tab_strip/tab.js
index 1c8f22f..43180aa 100644
--- a/chrome/browser/resources/tab_strip/tab.js
+++ b/chrome/browser/resources/tab_strip/tab.js
@@ -73,8 +73,8 @@
         'loading_',
         !tab.shouldHideThrobber &&
             tab.networkState === TabNetworkState.LOADING);
-
     this.toggleAttribute('pinned_', tab.pinned);
+    this.toggleAttribute('blocked_', tab.blocked);
     this.setAttribute('draggable', tab.pinned);
     this.toggleAttribute('crashed', tab.crashed);
 
diff --git a/chrome/browser/resources/tab_strip/tabs_api_proxy.js b/chrome/browser/resources/tab_strip/tabs_api_proxy.js
index fbad2ca..6217b60 100644
--- a/chrome/browser/resources/tab_strip/tabs_api_proxy.js
+++ b/chrome/browser/resources/tab_strip/tabs_api_proxy.js
@@ -19,6 +19,7 @@
 /**
  * @typedef {{
  *    active: boolean,
+ *    blocked: boolean,
  *    crashed: boolean,
  *    favIconUrl: (string|undefined),
  *    id: number,
diff --git a/chrome/browser/safe_browsing/download_protection/download_reporter.cc b/chrome/browser/safe_browsing/download_protection/download_reporter.cc
index 8bfb96d7..ff9e1c6b 100644
--- a/chrome/browser/safe_browsing/download_protection/download_reporter.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_reporter.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h"
 #include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "components/download/public/common/download_danger_type.h"
 #include "components/download/public/common/download_item.h"
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
index f8e469c..2e72546 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
@@ -91,11 +91,6 @@
   return base::string16();
 }
 
-base::string16 SettingsResetPromptController::GetButtonLabel() const {
-  return l10n_util::GetStringUTF16(
-      IDS_SETTINGS_RESET_PROMPT_ACCEPT_BUTTON_LABEL);
-}
-
 base::string16 SettingsResetPromptController::GetMainText() const {
   DCHECK(!main_text_.empty());
   return main_text_;
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h
index 5d134ab..81156dd 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h
@@ -31,7 +31,6 @@
       std::unique_ptr<BrandcodedDefaultSettings> default_settings);
 
   base::string16 GetWindowTitle() const;
-  base::string16 GetButtonLabel() const;
   base::string16 GetMainText() const;
   // Returns the offset into the main text string where a URL was inserted. To
   // be used by the dialog to apply an appropriate style to the URL text.
diff --git a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc
index 988d22e..88bde8ec 100644
--- a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc
+++ b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/download/simple_download_manager_coordinator_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "components/keyed_service/core/service_access_type.h"
diff --git a/chrome/browser/search_engines/template_url_service_factory_android.cc b/chrome/browser/search_engines/template_url_service_factory_android.cc
index 59dbdfa..58aef45 100644
--- a/chrome/browser/search_engines/template_url_service_factory_android.cc
+++ b/chrome/browser/search_engines/template_url_service_factory_android.cc
@@ -2,6 +2,7 @@
 // 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 "chrome/android/chrome_jni_headers/TemplateUrlServiceFactory_jni.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
diff --git a/chrome/browser/sessions/session_data_deleter.cc b/chrome/browser/sessions/session_data_deleter.cc
index 3eb7dee..102df72 100644
--- a/chrome/browser/sessions/session_data_deleter.cc
+++ b/chrome/browser/sessions/session_data_deleter.cc
@@ -22,6 +22,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/cookies/cookie_util.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 #include "storage/browser/quota/special_storage_policy.h"
 
 namespace {
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
index b4a2f4c..e016dd1 100644
--- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
+++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
@@ -21,6 +21,7 @@
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "net/base/net_errors.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 
 namespace signin {
 
diff --git a/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc b/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc
index 5b27f91..1017c8a 100644
--- a/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc
+++ b/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
diff --git a/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc b/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc
index 9ac50ce6..984e70c 100644
--- a/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc
+++ b/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc
@@ -42,6 +42,7 @@
 #include "net/base/url_util.h"
 #include "net/cert/x509_certificate.h"
 #include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 #include "url/gurl.h"
 
 namespace {
diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h
index eb3ca5e..849275fa 100644
--- a/chrome/browser/ssl/ssl_error_handler.h
+++ b/chrome/browser/ssl/ssl_error_handler.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/ssl/ssl_error_assistant.pb.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
 #include "components/ssl_errors/error_classification.h"
+#include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/restore_type.h"
diff --git a/chrome/browser/startup_data.cc b/chrome/browser/startup_data.cc
index 1be683c..197b9e5 100644
--- a/chrome/browser/startup_data.cc
+++ b/chrome/browser/startup_data.cc
@@ -30,6 +30,7 @@
 #include "chrome/browser/prefs/in_process_service_factory_factory.h"
 #include "chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.h"
 #include "chrome/browser/profiles/pref_service_builder_utils.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/supervised_user/supervised_user_pref_store.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
index 1f7143f..95a4c11 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -12,6 +12,7 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
diff --git a/chrome/browser/supervised_user/permission_request_creator_mock.cc b/chrome/browser/supervised_user/permission_request_creator_mock.cc
index 5e25e05..ec04d5c 100644
--- a/chrome/browser/supervised_user/permission_request_creator_mock.cc
+++ b/chrome/browser/supervised_user/permission_request_creator_mock.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
index 0e41d61..d661581 100644
--- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/supervised_user/logged_in_user_mixin.h"
 #include "chrome/browser/supervised_user/permission_request_creator_mock.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index 8ba00e3..76a94c5 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/supervised_user/experimental/supervised_user_filtering_switches.h"
 #include "chrome/browser/supervised_user/permission_request_creator.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
diff --git a/chrome/browser/supervised_user/supervised_user_service_browsertest.cc b/chrome/browser/supervised_user/supervised_user_service_browsertest.cc
index 2a21102..dff9433 100644
--- a/chrome/browser/supervised_user/supervised_user_service_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_service_browsertest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/supervised_user/logged_in_user_mixin.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter_browsertest.cc b/chrome/browser/supervised_user/supervised_user_url_filter_browsertest.cc
index c66ea08..709a38d9 100644
--- a/chrome/browser/supervised_user/supervised_user_url_filter_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_url_filter_browsertest.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/supervised_user/logged_in_user_mixin.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/browser/supervised_user/supervised_user_interstitial.h"
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index f2956e5..14f261b3 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -102,6 +102,7 @@
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/supervised_user/supervised_user_service.h"
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h
index 2e91c19..16b5bf3 100644
--- a/chrome/browser/sync/test/integration/sync_test.h
+++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "base/callback_list.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "build/buildflag.h"
diff --git a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
index c3f74e6a..d2676d4e 100644
--- a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
@@ -222,8 +222,10 @@
   DISALLOW_COPY_AND_ASSIGN(TwoClientPreferencesSyncTestWithSelfNotifications);
 };
 
+// Flaky. https://crbug.com/1012688
+// This was E2E_ENABLED(ShouldKeepLocalDataOnTypeMismatch).
 IN_PROC_BROWSER_TEST_F(TwoClientPreferencesSyncTestWithSelfNotifications,
-                       E2E_ENABLED(ShouldKeepLocalDataOnTypeMismatch)) {
+                       DISABLED_ShouldKeepLocalDataOnTypeMismatch) {
   ResetSyncForPrimaryAccount();
   // Client 1 has type-conflicting data in it's pref file. Verify that incoming
   // values from sync of other type do not modify the local state.
diff --git a/chrome/browser/transition_manager/full_browser_transition_manager.cc b/chrome/browser/transition_manager/full_browser_transition_manager.cc
index 4beed95..bb3f3c9 100644
--- a/chrome/browser/transition_manager/full_browser_transition_manager.cc
+++ b/chrome/browser/transition_manager/full_browser_transition_manager.cc
@@ -7,6 +7,7 @@
 #include "base/no_destructor.h"
 #include "base/stl_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 
 FullBrowserTransitionManager::FullBrowserTransitionManager() = default;
 FullBrowserTransitionManager::~FullBrowserTransitionManager() = default;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 09230df4..6c4ca84b 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -939,6 +939,8 @@
       "global_error/global_error_service_factory.h",
       "global_media_controls/media_dialog_delegate.cc",
       "global_media_controls/media_dialog_delegate.h",
+      "global_media_controls/media_notification_container_impl.h",
+      "global_media_controls/media_notification_container_observer.h",
       "global_media_controls/media_toolbar_button_controller.cc",
       "global_media_controls/media_toolbar_button_controller.h",
       "global_media_controls/media_toolbar_button_controller_delegate.cc",
@@ -2825,8 +2827,8 @@
       "views/global_media_controls/media_dialog_view.cc",
       "views/global_media_controls/media_dialog_view.h",
       "views/global_media_controls/media_dialog_view_observer.h",
-      "views/global_media_controls/media_notification_container_impl.cc",
-      "views/global_media_controls/media_notification_container_impl.h",
+      "views/global_media_controls/media_notification_container_impl_view.cc",
+      "views/global_media_controls/media_notification_container_impl_view.h",
       "views/global_media_controls/media_notification_list_view.cc",
       "views/global_media_controls/media_notification_list_view.h",
       "views/global_media_controls/media_toolbar_button_view.cc",
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index 590853986..0829ea07 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -410,6 +410,9 @@
 }
 
 ArcAppListPrefs::~ArcAppListPrefs() {
+  for (auto& observer : observer_list_)
+    observer.OnArcAppListPrefsDestroyed();
+
   arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get();
   if (!arc_session_manager)
     return;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
index 71f9e0b..bb90420 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -217,6 +217,9 @@
     virtual void OnInstallationFinished(const std::string& package_name,
                                         bool success) {}
 
+    // Notifies that ArcAppListPrefs is destroyed.
+    virtual void OnArcAppListPrefsDestroyed() {}
+
    protected:
     virtual ~Observer() {}
   };
diff --git a/chrome/browser/ui/app_list/search/internal_app_result.cc b/chrome/browser/ui/app_list/search/internal_app_result.cc
index 2302238..1c67aed 100644
--- a/chrome/browser/ui/app_list/search/internal_app_result.cc
+++ b/chrome/browser/ui/app_list/search/internal_app_result.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
 #include "components/favicon/core/large_icon_service.h"
 #include "components/favicon_base/fallback_icon_style.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/image/image_skia_operations.h"
 
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/search_ranking_event_logger.cc b/chrome/browser/ui/app_list/search/search_result_ranker/search_ranking_event_logger.cc
index 2ca9b12..683519a0 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/search_ranking_event_logger.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/search_ranking_event_logger.cc
@@ -7,6 +7,7 @@
 #include <cmath>
 
 #include "ash/public/cpp/app_list/app_list_types.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/omnibox_result.h"
diff --git a/chrome/browser/ui/ash/assistant/assistant_service_connection.cc b/chrome/browser/ui/ash/assistant/assistant_service_connection.cc
index bb71985..9480ace 100644
--- a/chrome/browser/ui/ash/assistant/assistant_service_connection.cc
+++ b/chrome/browser/ui/ash/assistant/assistant_service_connection.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/ash/assistant/assistant_service_connection.h"
 
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
 namespace {
 
 constexpr const char kConnectionKey[] = "assistant_service_connection";
diff --git a/chrome/browser/ui/ash/assistant/device_actions.cc b/chrome/browser/ui/ash/assistant/device_actions.cc
index 42afc3f..0f78be4d 100644
--- a/chrome/browser/ui/ash/assistant/device_actions.cc
+++ b/chrome/browser/ui/ash/assistant/device_actions.cc
@@ -8,6 +8,8 @@
 
 #include "ash/public/cpp/ash_pref_names.h"
 #include "base/bind.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
diff --git a/chrome/browser/ui/ash/assistant/proactive_suggestions_loader.cc b/chrome/browser/ui/ash/assistant/proactive_suggestions_loader.cc
index 98f94bc..9affedf 100644
--- a/chrome/browser/ui/ash/assistant/proactive_suggestions_loader.cc
+++ b/chrome/browser/ui/ash/assistant/proactive_suggestions_loader.cc
@@ -7,6 +7,7 @@
 #include "ash/public/cpp/assistant/proactive_suggestions.h"
 #include "ash/public/cpp/assistant/util/histogram_util.h"
 #include "base/i18n/rtl.h"
+#include "base/strings/string_number_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/services/assistant/public/features.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc
index f01d350..2f6bd64 100644
--- a/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 #include "components/arc/metrics/arc_metrics_constants.h"
 #include "ui/events/event_constants.h"
+#include "ui/gfx/image/image_skia.h"
 
 ArcPlaystoreShortcutLauncherItemController::
     ArcPlaystoreShortcutLauncherItemController()
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 44c534d2..d0dd501 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1715,7 +1715,7 @@
 void Browser::EnterFullscreenModeForTab(
     WebContents* web_contents,
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab(
       web_contents, origin);
 }
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index d0ac5fc..1d8277f 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -755,7 +755,7 @@
   void EnterFullscreenModeForTab(
       content::WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override;
+      const blink::FullScreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
   bool IsFullscreenForTabOrPending(
       const content::WebContents* web_contents) override;
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 8707e58c..665ab0a 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -2817,8 +2817,8 @@
       static_cast<web_modal::WebContentsModalDialogManagerDelegate*>(browser());
 
   // Simulate the tab requesting fullscreen.
-  browser_as_wc_delegate->EnterFullscreenModeForTab(
-      tab, GURL(), blink::WebFullscreenOptions());
+  browser_as_wc_delegate->EnterFullscreenModeForTab(tab, GURL(),
+                                                    blink::FullScreenOptions());
   EXPECT_TRUE(browser_as_wc_delegate->IsFullscreenForTabOrPending(tab));
 
   // The tab gets a modal dialog.
@@ -2844,8 +2844,8 @@
 
   // Simulate a screen-captured tab requesting fullscreen.
   tab->IncrementCapturerCount(gfx::Size(1280, 720));
-  browser_as_wc_delegate->EnterFullscreenModeForTab(
-      tab, GURL(), blink::WebFullscreenOptions());
+  browser_as_wc_delegate->EnterFullscreenModeForTab(tab, GURL(),
+                                                    blink::FullScreenOptions());
   EXPECT_TRUE(browser_as_wc_delegate->IsFullscreenForTabOrPending(tab));
 
   // The tab gets a modal dialog.
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
index fea598b..47e2ed5 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
@@ -117,7 +117,7 @@
     FullscreenNotificationObserver fullscreen_observer(browser());
     if (enter_fullscreen)
       browser()->EnterFullscreenModeForTab(tab, GURL(),
-                                           blink::WebFullscreenOptions());
+                                           blink::FullScreenOptions());
     else
       browser()->ExitFullscreenModeForTab(tab);
     fullscreen_observer.Wait();
@@ -278,7 +278,7 @@
     FullscreenNotificationObserver fullscreen_observer(browser());
     EXPECT_FALSE(browser()->window()->IsFullscreen());
     browser()->EnterFullscreenModeForTab(tab, GURL(),
-                                         blink::WebFullscreenOptions());
+                                         blink::FullScreenOptions());
     fullscreen_observer.Wait();
     EXPECT_TRUE(browser()->window()->IsFullscreen());
   }
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc
index a54c97e..fd63d8c2 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc
@@ -194,8 +194,7 @@
 void FullscreenControllerTest::EnterActiveTabFullscreen() {
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
   FullscreenNotificationObserver fullscreen_observer(browser());
-  browser()->EnterFullscreenModeForTab(tab, GURL(),
-                                       blink::WebFullscreenOptions());
+  browser()->EnterFullscreenModeForTab(tab, GURL(), blink::FullScreenOptions());
   fullscreen_observer.Wait();
 }
 
diff --git a/chrome/browser/ui/global_media_controls/media_dialog_delegate.h b/chrome/browser/ui/global_media_controls/media_dialog_delegate.h
index 6188d7b..4b9fa6d97 100644
--- a/chrome/browser/ui/global_media_controls/media_dialog_delegate.h
+++ b/chrome/browser/ui/global_media_controls/media_dialog_delegate.h
@@ -13,13 +13,20 @@
 class MediaNotificationItem;
 }  // namespace media_message_center
 
+class MediaNotificationContainerImpl;
+
 // Delegate for MediaToolbarButtonController that is told when to display or
 // hide a media session.
 class MediaDialogDelegate {
  public:
-  virtual void ShowMediaSession(
+  // Displays a media session and returns a pointer to the
+  // MediaNotificationContainerImpl that was added to the dialog. The returned
+  // MediaNotificationContainerImpl is owned by the MediaDialogDelegate.
+  virtual MediaNotificationContainerImpl* ShowMediaSession(
       const std::string& id,
       base::WeakPtr<media_message_center::MediaNotificationItem> item) = 0;
+
+  // Hides a media session.
   virtual void HideMediaSession(const std::string& id) = 0;
 
  protected:
diff --git a/chrome/browser/ui/global_media_controls/media_notification_container_impl.h b/chrome/browser/ui/global_media_controls/media_notification_container_impl.h
new file mode 100644
index 0000000..af1e737
--- /dev/null
+++ b/chrome/browser/ui/global_media_controls/media_notification_container_impl.h
@@ -0,0 +1,19 @@
+// 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 CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_H_
+#define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_H_
+
+class MediaNotificationContainerObserver;
+
+class MediaNotificationContainerImpl {
+ public:
+  virtual void AddObserver(MediaNotificationContainerObserver* observer) = 0;
+  virtual void RemoveObserver(MediaNotificationContainerObserver* observer) = 0;
+
+ protected:
+  virtual ~MediaNotificationContainerImpl() = default;
+};
+
+#endif  // CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_H_
diff --git a/chrome/browser/ui/global_media_controls/media_notification_container_observer.h b/chrome/browser/ui/global_media_controls/media_notification_container_observer.h
new file mode 100644
index 0000000..fa016041
--- /dev/null
+++ b/chrome/browser/ui/global_media_controls/media_notification_container_observer.h
@@ -0,0 +1,28 @@
+// 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 CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_OBSERVER_H_
+#define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_OBSERVER_H_
+
+#include "base/observer_list_types.h"
+
+class MediaNotificationContainerObserver : public base::CheckedObserver {
+ public:
+  // Called when the container's expanded state changes.
+  virtual void OnContainerExpanded(bool expanded) = 0;
+
+  // Called when the metadata displayed in the container changes.
+  virtual void OnContainerMetadataChanged() = 0;
+
+  // Called when the container is dismissed from the dialog.
+  virtual void OnContainerDismissed(const std::string& id) = 0;
+
+  // Called when the container is about to be deleted.
+  virtual void OnContainerDestroyed(const std::string& id) = 0;
+
+ protected:
+  ~MediaNotificationContainerObserver() override = default;
+};
+
+#endif  // CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_OBSERVER_H_
diff --git a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.cc b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.cc
index b4b6c1e..7b2f07c 100644
--- a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.cc
+++ b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/global_media_controls/media_dialog_delegate.h"
+#include "chrome/browser/ui/global_media_controls/media_notification_container_impl.h"
 #include "chrome/browser/ui/global_media_controls/media_toolbar_button_controller_delegate.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "components/media_message_center/media_notification_item.h"
@@ -92,7 +93,10 @@
           weak_ptr_factory_.GetWeakPtr()));
 }
 
-MediaToolbarButtonController::~MediaToolbarButtonController() = default;
+MediaToolbarButtonController::~MediaToolbarButtonController() {
+  for (auto container_pair : observed_containers_)
+    container_pair.second->RemoveObserver(this);
+}
 
 void MediaToolbarButtonController::OnFocusGained(
     media_session::mojom::AudioFocusRequestStatePtr session) {
@@ -161,7 +165,14 @@
   if (it != sessions_.end())
     item = it->second.item()->GetWeakPtr();
 
-  dialog_delegate_->ShowMediaSession(id, item);
+  MediaNotificationContainerImpl* container =
+      dialog_delegate_->ShowMediaSession(id, item);
+
+  // Observe the container for dismissal.
+  if (container) {
+    container->AddObserver(this);
+    observed_containers_[id] = container;
+  }
 }
 
 void MediaToolbarButtonController::HideNotification(const std::string& id) {
@@ -202,6 +213,20 @@
                             IsWebContentsFocused(web_contents));
 }
 
+void MediaToolbarButtonController::OnContainerDismissed(const std::string& id) {
+  auto it = sessions_.find(id);
+  if (it != sessions_.end())
+    it->second.item()->Dismiss();
+}
+
+void MediaToolbarButtonController::OnContainerDestroyed(const std::string& id) {
+  auto iter = observed_containers_.find(id);
+  DCHECK(iter != observed_containers_.end());
+
+  iter->second->RemoveObserver(this);
+  observed_containers_.erase(iter);
+}
+
 void MediaToolbarButtonController::SetDialogDelegate(
     MediaDialogDelegate* delegate) {
   DCHECK(!delegate || !dialog_delegate_);
@@ -219,20 +244,20 @@
     if (it != sessions_.end())
       item = it->second.item()->GetWeakPtr();
 
-    dialog_delegate_->ShowMediaSession(id, item);
+    MediaNotificationContainerImpl* container =
+        dialog_delegate_->ShowMediaSession(id, item);
+
+    // Observe the container for dismissal.
+    if (container) {
+      container->AddObserver(this);
+      observed_containers_[id] = container;
+    }
   }
 
   media_message_center::RecordConcurrentNotificationCount(
       active_controllable_session_ids_.size());
 }
 
-void MediaToolbarButtonController::OnDismissButtonClicked(
-    const std::string& id) {
-  auto it = sessions_.find(id);
-  if (it != sessions_.end())
-    it->second.item()->Dismiss();
-}
-
 void MediaToolbarButtonController::OnReceivedAudioFocusRequests(
     std::vector<media_session::mojom::AudioFocusRequestStatePtr> sessions) {
   for (auto& session : sessions)
diff --git a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h
index 98f5d0e..7d15e25 100644
--- a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h
+++ b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/global_media_controls/media_notification_container_observer.h"
 #include "components/media_message_center/media_notification_controller.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -31,6 +32,7 @@
 }  // namespace service_manager
 
 class MediaDialogDelegate;
+class MediaNotificationContainerImpl;
 class MediaToolbarButtonControllerDelegate;
 
 // Controller for the MediaToolbarButtonView that decides when to show or hide
@@ -38,7 +40,8 @@
 // MediaDialogView to display.
 class MediaToolbarButtonController
     : public media_session::mojom::AudioFocusObserver,
-      public media_message_center::MediaNotificationController {
+      public media_message_center::MediaNotificationController,
+      public MediaNotificationContainerObserver {
  public:
   MediaToolbarButtonController(const base::UnguessableToken& source_id,
                                service_manager::Connector* connector,
@@ -58,10 +61,13 @@
   scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() const override;
   void LogMediaSessionActionButtonPressed(const std::string& id) override;
 
-  void SetDialogDelegate(MediaDialogDelegate* delegate);
+  // MediaNotificationContainerObserver implementation.
+  void OnContainerExpanded(bool expanded) override {}
+  void OnContainerMetadataChanged() override {}
+  void OnContainerDismissed(const std::string& id) override;
+  void OnContainerDestroyed(const std::string& id) override;
 
-  // Called when the dismiss button was clicked on a session.
-  void OnDismissButtonClicked(const std::string& id);
+  void SetDialogDelegate(MediaDialogDelegate* delegate);
 
  private:
   friend class MediaToolbarButtonControllerTest;
@@ -117,7 +123,10 @@
 
   // Stores a Session for each media session keyed by its |request_id| in string
   // format.
-  std::map<const std::string, Session> sessions_;
+  std::map<std::string, Session> sessions_;
+
+  // A map of all containers we're currently observing.
+  std::map<std::string, MediaNotificationContainerImpl*> observed_containers_;
 
   // Connections with the media session service to listen for audio focus
   // updates and control media sessions.
diff --git a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller_unittest.cc b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller_unittest.cc
index 95dbf0b..aa19a0f 100644
--- a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller_unittest.cc
+++ b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller_unittest.cc
@@ -62,8 +62,9 @@
   // MediaDialogDelegate implementation.
   MOCK_METHOD2(
       ShowMediaSession,
-      void(const std::string& id,
-           base::WeakPtr<media_message_center::MediaNotificationItem> item));
+      MediaNotificationContainerImpl*(
+          const std::string& id,
+          base::WeakPtr<media_message_center::MediaNotificationItem> item));
   MOCK_METHOD1(HideMediaSession, void(const std::string& id));
 
  private:
@@ -165,7 +166,7 @@
   }
 
   void SimulateDismissButtonClicked(const base::UnguessableToken& id) {
-    controller_->OnDismissButtonClicked(id.ToString());
+    controller_->OnContainerDismissed(id.ToString());
   }
 
   void ExpectHistogramCountRecorded(int count, int size) {
diff --git a/chrome/browser/ui/send_mouse_move_uitest_win.cc b/chrome/browser/ui/send_mouse_move_uitest_win.cc
index 20e3a21..0d04093 100644
--- a/chrome/browser/ui/send_mouse_move_uitest_win.cc
+++ b/chrome/browser/ui/send_mouse_move_uitest_win.cc
@@ -25,8 +25,9 @@
 // This test positions the mouse at every point on the screen. It is not meant
 // to be run on the bots, as it takes too long. Run it manually as needed to
 // verify ui_controls::SendMouseMoveNotifyWhenDone with:
-//   interactive_ui_tests.exe --single_process --gtest_also_run_disabled_tests \
-//       --gtest_filter=SendMouseMoveUITest.DISABLED_Fullscreen
+//   interactive_ui_tests.exe --single-process-tests \
+// --gtest_also_run_disabled_tests \
+// --gtest_filter=SendMouseMoveUITest.DISABLED_Fullscreen
 IN_PROC_BROWSER_TEST_F(SendMouseMoveUITest, DISABLED_Fullscreen) {
   // Make the browser fullscreen so that we can position the mouse anywhere on
   // the display, as ui_controls::SendMouseMoveNotifyWhenDone can only provide
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 48fb601..12af7290 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -47,6 +47,7 @@
 #include "chrome/browser/previews/previews_ui_tab_helper.h"
 #include "chrome/browser/previews/resource_loading_hints/resource_loading_hints_web_contents_observer.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/resource_coordinator/tab_helper.h"
 #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer.h"
 #include "chrome/browser/safe_browsing/trigger_creator.h"
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
index da0d1e7..acfd3ac 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
@@ -80,32 +80,13 @@
   BaseDialogContainer(std::unique_ptr<views::View> dialog_body,
                       const base::Closure& close_callback)
       : dialog_body_(AddChildView(std::move(dialog_body))),
-        close_callback_(close_callback) {
-    // Since we are using a ClientView instead of a DialogClientView, we need to
-    // manually bind the escape key to close the dialog.
-    ui::Accelerator escape(ui::VKEY_ESCAPE, ui::EF_NONE);
-    AddAccelerator(escape);
-  }
+        close_callback_(close_callback) {}
   ~BaseDialogContainer() override {}
 
  protected:
   views::View* dialog_body() { return dialog_body_; }
 
  private:
-  // Overridden from views::View:
-  void ViewHierarchyChanged(
-      const views::ViewHierarchyChangedDetails& details) override {
-    views::DialogDelegateView::ViewHierarchyChanged(details);
-    if (details.is_add && details.child == this)
-      GetFocusManager()->AdvanceFocus(false);
-  }
-
-  bool AcceleratorPressed(const ui::Accelerator& accelerator) override {
-    DCHECK_EQ(accelerator.key_code(), ui::VKEY_ESCAPE);
-    GetWidget()->CloseWithReason(views::Widget::ClosedReason::kEscKeyPressed);
-    return true;
-  }
-
   // Overridden from views::DialogDelegate:
   int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; }
 
@@ -115,9 +96,6 @@
     if (!close_callback_.is_null())
       close_callback_.Run();
   }
-  views::ClientView* CreateClientView(views::Widget* widget) override {
-    return new views::ClientView(widget, GetContentsView());
-  }
 
   views::View* dialog_body_;
   const base::Closure close_callback_;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
index afef006c..4b21555 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -151,12 +151,6 @@
   return edit_button;
 }
 
-bool BookmarkBubbleView::GetExtraViewPadding(int* padding) {
-  *padding = ChromeLayoutProvider::Get()->GetDistanceMetric(
-      DISTANCE_UNRELATED_CONTROL_HORIZONTAL_LARGE);
-  return true;
-}
-
 std::unique_ptr<views::View> BookmarkBubbleView::CreateFootnoteView() {
 #if defined(OS_CHROMEOS)
   // ChromeOS does not show the signin promo.
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h
index 809f4c1..32ae8f7 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h
@@ -66,7 +66,6 @@
   void WindowClosing() override;
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   std::unique_ptr<views::View> CreateExtraView() override;
-  bool GetExtraViewPadding(int* padding) override;
   std::unique_ptr<views::View> CreateFootnoteView() override;
   bool Cancel() override;
   bool Accept() override;
diff --git a/chrome/browser/ui/views/device_chooser_content_view.cc b/chrome/browser/ui/views/device_chooser_content_view.cc
index 7d27c72..0402d225 100644
--- a/chrome/browser/ui/views/device_chooser_content_view.cc
+++ b/chrome/browser/ui/views/device_chooser_content_view.cc
@@ -326,13 +326,6 @@
   return container;
 }
 
-base::string16 DeviceChooserContentView::GetDialogButtonLabel(
-    ui::DialogButton button) const {
-  return button == ui::DIALOG_BUTTON_OK
-             ? chooser_controller_->GetOkButtonLabel()
-             : chooser_controller_->GetCancelButtonLabel();
-}
-
 bool DeviceChooserContentView::IsDialogButtonEnabled(
     ui::DialogButton button) const {
   return chooser_controller_->BothButtonsAlwaysEnabled() ||
diff --git a/chrome/browser/ui/views/device_chooser_content_view.h b/chrome/browser/ui/views/device_chooser_content_view.h
index a824486..7852a14 100644
--- a/chrome/browser/ui/views/device_chooser_content_view.h
+++ b/chrome/browser/ui/views/device_chooser_content_view.h
@@ -65,7 +65,6 @@
 
   base::string16 GetWindowTitle() const;
   std::unique_ptr<views::View> CreateExtraView();
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const;
   bool IsDialogButtonEnabled(ui::DialogButton button) const;
   void Accept();
   void Cancel();
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
index db5747c..54224e5 100644
--- a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
@@ -43,6 +43,12 @@
   // ------------------------------------
 
   DCHECK(chooser_controller);
+
+  DialogDelegate::set_button_label(ui::DIALOG_BUTTON_OK,
+                                   chooser_controller->GetOkButtonLabel());
+  DialogDelegate::set_button_label(ui::DIALOG_BUTTON_CANCEL,
+                                   chooser_controller->GetCancelButtonLabel());
+
   device_chooser_content_view_ =
       new DeviceChooserContentView(this, std::move(chooser_controller));
   device_chooser_content_view_->SetBorder(views::CreateEmptyBorder(
@@ -65,11 +71,6 @@
   return ui::MODAL_TYPE_CHILD;
 }
 
-base::string16 ChooserDialogView::GetDialogButtonLabel(
-    ui::DialogButton button) const {
-  return device_chooser_content_view_->GetDialogButtonLabel(button);
-}
-
 bool ChooserDialogView::IsDialogButtonEnabled(ui::DialogButton button) const {
   return device_chooser_content_view_->IsDialogButtonEnabled(button);
 }
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.h b/chrome/browser/ui/views/extensions/chooser_dialog_view.h
index c5a4596..f12c01d5 100644
--- a/chrome/browser/ui/views/extensions/chooser_dialog_view.h
+++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.h
@@ -29,7 +29,6 @@
   ui::ModalType GetModalType() const override;
 
   // views::DialogDelegate:
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;
   views::View* GetInitiallyFocusedView() override;
   std::unique_ptr<views::View> CreateExtraView() override;
diff --git a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc
index fc9ce93..ced151a5 100644
--- a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc
@@ -25,7 +25,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/web/web_fullscreen_options.h"
+#include "third_party/blink/public/common/fullscreen/fullscreen_options.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/event.h"
@@ -111,7 +111,7 @@
         static_cast<content::WebContentsDelegate*>(browser());
     delegate->EnterFullscreenModeForTab(GetActiveWebContents(),
                                         GURL("about:blank"),
-                                        blink::WebFullscreenOptions());
+                                        blink::FullScreenOptions());
     fullscreen_observer.Wait();
     ASSERT_TRUE(delegate->IsFullscreenForTabOrPending(GetActiveWebContents()));
   }
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
index 300c442..4a4bbfb0 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/global_media_controls/media_dialog_view_observer.h"
-#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h"
+#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h"
 #include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
 #include "ui/views/background.h"
@@ -60,16 +60,22 @@
   return instance_ != nullptr;
 }
 
-void MediaDialogView::ShowMediaSession(
+MediaNotificationContainerImpl* MediaDialogView::ShowMediaSession(
     const std::string& id,
     base::WeakPtr<media_message_center::MediaNotificationItem> item) {
-  active_sessions_view_->ShowNotification(
-      id, std::make_unique<MediaNotificationContainerImpl>(this, controller_,
-                                                           id, item));
+  auto container =
+      std::make_unique<MediaNotificationContainerImplView>(id, item);
+  MediaNotificationContainerImplView* container_ptr = container.get();
+  container_ptr->AddObserver(this);
+  observed_containers_[id] = container_ptr;
+
+  active_sessions_view_->ShowNotification(id, std::move(container));
   OnAnchorBoundsChanged();
 
   for (auto& observer : observers_)
     observer.OnMediaSessionShown();
+
+  return container_ptr;
 }
 
 void MediaDialogView::HideMediaSession(const std::string& id) {
@@ -118,6 +124,23 @@
   return gfx::Size(width, 1);
 }
 
+void MediaDialogView::OnContainerExpanded(bool expanded) {
+  OnAnchorBoundsChanged();
+}
+
+void MediaDialogView::OnContainerMetadataChanged() {
+  for (auto& observer : observers_)
+    observer.OnMediaSessionMetadataUpdated();
+}
+
+void MediaDialogView::OnContainerDestroyed(const std::string& id) {
+  auto iter = observed_containers_.find(id);
+  DCHECK(iter != observed_containers_.end());
+
+  iter->second->RemoveObserver(this);
+  observed_containers_.erase(iter);
+}
+
 void MediaDialogView::AddObserver(MediaDialogViewObserver* observer) {
   observers_.AddObserver(observer);
 }
@@ -126,12 +149,7 @@
   observers_.RemoveObserver(observer);
 }
 
-void MediaDialogView::OnMediaSessionMetadataChanged() {
-  for (auto& observer : observers_)
-    observer.OnMediaSessionMetadataUpdated();
-}
-
-const std::map<const std::string, MediaNotificationContainerImpl*>&
+const std::map<const std::string, MediaNotificationContainerImplView*>&
 MediaDialogView::GetNotificationsForTesting() const {
   return active_sessions_view_->notifications_for_testing();
 }
@@ -146,7 +164,10 @@
   DCHECK(controller_);
 }
 
-MediaDialogView::~MediaDialogView() = default;
+MediaDialogView::~MediaDialogView() {
+  for (auto container_pair : observed_containers_)
+    container_pair.second->RemoveObserver(this);
+}
 
 void MediaDialogView::Init() {
   // Remove margins.
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
index 689abe0..cd72469 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
@@ -8,6 +8,7 @@
 #include "base/observer_list.h"
 #include "base/optional.h"
 #include "chrome/browser/ui/global_media_controls/media_dialog_delegate.h"
+#include "chrome/browser/ui/global_media_controls/media_notification_container_observer.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 
 namespace service_manager {
@@ -15,13 +16,14 @@
 }  // namespace service_manager
 
 class MediaDialogViewObserver;
-class MediaNotificationContainerImpl;
+class MediaNotificationContainerImplView;
 class MediaNotificationListView;
 class MediaToolbarButtonController;
 
 // Dialog that shows media controls that control the active media session.
 class MediaDialogView : public views::BubbleDialogDelegateView,
-                        public MediaDialogDelegate {
+                        public MediaDialogDelegate,
+                        public MediaNotificationContainerObserver {
  public:
   static void ShowDialog(views::View* anchor_view,
                          MediaToolbarButtonController* controller,
@@ -32,7 +34,7 @@
   static MediaDialogView* GetDialogViewForTesting() { return instance_; }
 
   // MediaDialogDelegate implementation.
-  void ShowMediaSession(
+  MediaNotificationContainerImpl* ShowMediaSession(
       const std::string& id,
       base::WeakPtr<media_message_center::MediaNotificationItem> item) override;
   void HideMediaSession(const std::string& id) override;
@@ -45,12 +47,16 @@
   void AddedToWidget() override;
   gfx::Size CalculatePreferredSize() const override;
 
+  // MediaNotificationContainerObserver implementation.
+  void OnContainerExpanded(bool expanded) override;
+  void OnContainerMetadataChanged() override;
+  void OnContainerDismissed(const std::string& id) override {}
+  void OnContainerDestroyed(const std::string& id) override;
+
   void AddObserver(MediaDialogViewObserver* observer);
   void RemoveObserver(MediaDialogViewObserver* observer);
 
-  void OnMediaSessionMetadataChanged();
-
-  const std::map<const std::string, MediaNotificationContainerImpl*>&
+  const std::map<const std::string, MediaNotificationContainerImplView*>&
   GetNotificationsForTesting() const;
 
  private:
@@ -74,6 +80,10 @@
 
   base::ObserverList<MediaDialogViewObserver> observers_;
 
+  // A map of all containers we're currently observing.
+  std::map<const std::string, MediaNotificationContainerImplView*>
+      observed_containers_;
+
   DISALLOW_COPY_AND_ASSIGN(MediaDialogView);
 };
 
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
index 878b9b0..add4e1c 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/ui/global_media_controls/media_toolbar_button_observer.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/global_media_controls/media_dialog_view_observer.h"
-#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h"
+#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h"
 #include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/test/base/in_process_browser_test.h"
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h
deleted file mode 100644
index 7565301..0000000
--- a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h
+++ /dev/null
@@ -1,90 +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 CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_H_
-#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_H_
-
-#include <string>
-
-#include "base/memory/weak_ptr.h"
-#include "components/media_message_center/media_notification_container.h"
-#include "components/media_message_center/media_notification_view.h"
-#include "ui/views/controls/button/button.h"
-#include "ui/views/view.h"
-
-namespace media_message_center {
-class MediaNotificationItem;
-}  // namespace media_message_center
-
-class MediaDialogView;
-class MediaToolbarButtonController;
-
-// MediaNotificationContainerImpl holds a media notification for display within
-// the MediaDialogView. The media notification shows metadata for a media
-// session and can control playback.
-class MediaNotificationContainerImpl
-    : public views::View,
-      public media_message_center::MediaNotificationContainer,
-      public views::ButtonListener {
- public:
-  MediaNotificationContainerImpl(
-      MediaDialogView* parent,
-      MediaToolbarButtonController* controller,
-      const std::string& id,
-      base::WeakPtr<media_message_center::MediaNotificationItem> item);
-  ~MediaNotificationContainerImpl() override;
-
-  // media_message_center::MediaNotificationContainer:
-  void OnExpanded(bool expanded) override;
-  void OnMediaSessionInfoChanged(
-      const media_session::mojom::MediaSessionInfoPtr& session_info) override;
-  void OnMediaSessionMetadataChanged() override;
-  void OnVisibleActionsChanged(
-      const std::set<media_session::mojom::MediaSessionAction>& actions)
-      override;
-  void OnMediaArtworkChanged(const gfx::ImageSkia& image) override;
-  void OnColorsChanged(SkColor foreground, SkColor background) override;
-
-  // views::ButtonListener:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
-
-  media_message_center::MediaNotificationView* view_for_testing() {
-    return view_.get();
-  }
-
- private:
-  class DismissButton;
-
-  void UpdateDismissButtonIcon();
-
-  void UpdateDismissButtonBackground();
-
-  // Updates the forced expanded state of |view_|.
-  void ForceExpandedState();
-
-  // The MediaNotificationContainerImpl is owned by the
-  // MediaNotificationListView which is owned by the MediaDialogView, so the raw
-  // pointer is safe here.
-  MediaDialogView* const parent_;
-
-  // The MediaToolbarButtonController is owned by the MediaToolbarButton which
-  // outlives the MediaDialogView (and therefore the
-  // MediaNotificationContainerImpl).
-  MediaToolbarButtonController* const controller_;
-
-  const std::string id_;
-  std::unique_ptr<views::View> dismiss_button_container_;
-  DismissButton* dismiss_button_;
-  std::unique_ptr<media_message_center::MediaNotificationView> view_;
-
-  SkColor foreground_color_;
-  SkColor background_color_;
-
-  bool has_artwork_ = false;
-  bool has_many_actions_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaNotificationContainerImpl);
-};
-
-#endif  // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl.cc b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc
similarity index 62%
rename from chrome/browser/ui/views/global_media_controls/media_notification_container_impl.cc
rename to chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc
index c96c167..b2f20a9e 100644
--- a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc
@@ -2,14 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h"
+#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h"
 
+#include "chrome/browser/ui/global_media_controls/media_notification_container_observer.h"
 #include "chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h"
 #include "chrome/browser/ui/views/global_media_controls/media_dialog_view.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/animation/ink_drop_mask.h"
+#include "ui/views/animation/slide_out_controller.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/image_button_factory.h"
@@ -33,7 +35,7 @@
 
 }  // anonymous namespace
 
-class MediaNotificationContainerImpl::DismissButton
+class MediaNotificationContainerImplView::DismissButton
     : public views::ImageButton {
  public:
   explicit DismissButton(views::ButtonListener* listener)
@@ -52,23 +54,23 @@
   DISALLOW_COPY_AND_ASSIGN(DismissButton);
 };
 
-MediaNotificationContainerImpl::MediaNotificationContainerImpl(
-    MediaDialogView* parent,
-    MediaToolbarButtonController* controller,
+MediaNotificationContainerImplView::MediaNotificationContainerImplView(
     const std::string& id,
     base::WeakPtr<media_message_center::MediaNotificationItem> item)
-    : parent_(parent),
-      controller_(controller),
-      id_(id),
+    : id_(id),
       foreground_color_(kDefaultForegroundColor),
       background_color_(kDefaultBackgroundColor) {
-  DCHECK(parent_);
-  DCHECK(controller_);
-
   SetLayoutManager(std::make_unique<views::FillLayout>());
 
   SetPreferredSize(kNormalSize);
 
+  swipeable_container_ = std::make_unique<views::View>();
+  swipeable_container_->set_owned_by_client();
+  swipeable_container_->SetLayoutManager(std::make_unique<views::FillLayout>());
+  swipeable_container_->SetPaintToLayer();
+  swipeable_container_->layer()->SetFillsBoundsOpaquely(false);
+  AddChildView(swipeable_container_.get());
+
   dismiss_button_container_ = std::make_unique<views::View>();
   dismiss_button_container_->set_owned_by_client();
   dismiss_button_container_->SetPreferredSize(kDismissButtonSize);
@@ -90,35 +92,44 @@
   view_->set_owned_by_client();
   ForceExpandedState();
 
-  AddChildView(view_.get());
+  swipeable_container_->AddChildView(view_.get());
+
+  slide_out_controller_ =
+      std::make_unique<views::SlideOutController>(this, this);
 }
 
-MediaNotificationContainerImpl::~MediaNotificationContainerImpl() = default;
+MediaNotificationContainerImplView::~MediaNotificationContainerImplView() {
+  for (auto& observer : observers_)
+    observer.OnContainerDestroyed(id_);
+}
 
-void MediaNotificationContainerImpl::OnExpanded(bool expanded) {
+void MediaNotificationContainerImplView::OnExpanded(bool expanded) {
   SetPreferredSize(expanded ? kExpandedSize : kNormalSize);
   PreferredSizeChanged();
-  parent_->OnAnchorBoundsChanged();
+
+  for (auto& observer : observers_)
+    observer.OnContainerExpanded(expanded);
 }
 
-void MediaNotificationContainerImpl::OnMediaSessionInfoChanged(
+void MediaNotificationContainerImplView::OnMediaSessionInfoChanged(
     const media_session::mojom::MediaSessionInfoPtr& session_info) {
   dismiss_button_container_->SetVisible(
       !session_info || session_info->playback_state !=
                            media_session::mojom::MediaPlaybackState::kPlaying);
 }
 
-void MediaNotificationContainerImpl::OnMediaSessionMetadataChanged() {
-  parent_->OnMediaSessionMetadataChanged();
+void MediaNotificationContainerImplView::OnMediaSessionMetadataChanged() {
+  for (auto& observer : observers_)
+    observer.OnContainerMetadataChanged();
 }
 
-void MediaNotificationContainerImpl::OnVisibleActionsChanged(
+void MediaNotificationContainerImplView::OnVisibleActionsChanged(
     const std::set<media_session::mojom::MediaSessionAction>& actions) {
   has_many_actions_ = actions.size() >= kMinVisibleActionsForExpanding;
   ForceExpandedState();
 }
 
-void MediaNotificationContainerImpl::OnMediaArtworkChanged(
+void MediaNotificationContainerImplView::OnMediaArtworkChanged(
     const gfx::ImageSkia& image) {
   has_artwork_ = !image.isNull();
 
@@ -126,8 +137,8 @@
   ForceExpandedState();
 }
 
-void MediaNotificationContainerImpl::OnColorsChanged(SkColor foreground,
-                                                     SkColor background) {
+void MediaNotificationContainerImplView::OnColorsChanged(SkColor foreground,
+                                                         SkColor background) {
   if (foreground_color_ != foreground) {
     foreground_color_ = foreground;
     UpdateDismissButtonIcon();
@@ -138,19 +149,42 @@
   }
 }
 
-void MediaNotificationContainerImpl::ButtonPressed(views::Button* sender,
-                                                   const ui::Event& event) {
-  DCHECK_EQ(dismiss_button_, sender);
-  controller_->OnDismissButtonClicked(id_);
+ui::Layer* MediaNotificationContainerImplView::GetSlideOutLayer() {
+  return swipeable_container_->layer();
 }
 
-void MediaNotificationContainerImpl::UpdateDismissButtonIcon() {
+void MediaNotificationContainerImplView::OnSlideOut() {
+  DismissNotification();
+}
+
+void MediaNotificationContainerImplView::ButtonPressed(views::Button* sender,
+                                                       const ui::Event& event) {
+  DCHECK_EQ(dismiss_button_, sender);
+  DismissNotification();
+}
+
+void MediaNotificationContainerImplView::AddObserver(
+    MediaNotificationContainerObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void MediaNotificationContainerImplView::RemoveObserver(
+    MediaNotificationContainerObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+views::ImageButton*
+MediaNotificationContainerImplView::GetDismissButtonForTesting() {
+  return dismiss_button_;
+}
+
+void MediaNotificationContainerImplView::UpdateDismissButtonIcon() {
   views::SetImageFromVectorIconWithColor(
       dismiss_button_, vector_icons::kCloseRoundedIcon, kDismissButtonIconSize,
       foreground_color_);
 }
 
-void MediaNotificationContainerImpl::UpdateDismissButtonBackground() {
+void MediaNotificationContainerImplView::UpdateDismissButtonBackground() {
   if (!has_artwork_) {
     dismiss_button_container_->SetBackground(nullptr);
     return;
@@ -160,7 +194,12 @@
       background_color_, kDismissButtonBackgroundRadius));
 }
 
-void MediaNotificationContainerImpl::ForceExpandedState() {
+void MediaNotificationContainerImplView::DismissNotification() {
+  for (auto& observer : observers_)
+    observer.OnContainerDismissed(id_);
+}
+
+void MediaNotificationContainerImplView::ForceExpandedState() {
   if (view_) {
     bool should_expand = has_many_actions_ || has_artwork_;
     view_->SetForcedExpandedState(&should_expand);
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h
new file mode 100644
index 0000000..840c7fca
--- /dev/null
+++ b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h
@@ -0,0 +1,106 @@
+// 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 CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_VIEW_H_
+
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "chrome/browser/ui/global_media_controls/media_notification_container_impl.h"
+#include "components/media_message_center/media_notification_container.h"
+#include "components/media_message_center/media_notification_view.h"
+#include "ui/views/animation/slide_out_controller_delegate.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/view.h"
+
+namespace media_message_center {
+class MediaNotificationItem;
+}  // namespace media_message_center
+
+namespace views {
+class SlideOutController;
+}  // namespace views
+
+class MediaNotificationContainerObserver;
+
+// MediaNotificationContainerImplView holds a media notification for display
+// within the MediaDialogView. The media notification shows metadata for a media
+// session and can control playback.
+class MediaNotificationContainerImplView
+    : public views::View,
+      public media_message_center::MediaNotificationContainer,
+      public MediaNotificationContainerImpl,
+      public views::SlideOutControllerDelegate,
+      public views::ButtonListener {
+ public:
+  MediaNotificationContainerImplView(
+      const std::string& id,
+      base::WeakPtr<media_message_center::MediaNotificationItem> item);
+  ~MediaNotificationContainerImplView() override;
+
+  // media_message_center::MediaNotificationContainer:
+  void OnExpanded(bool expanded) override;
+  void OnMediaSessionInfoChanged(
+      const media_session::mojom::MediaSessionInfoPtr& session_info) override;
+  void OnMediaSessionMetadataChanged() override;
+  void OnVisibleActionsChanged(
+      const std::set<media_session::mojom::MediaSessionAction>& actions)
+      override;
+  void OnMediaArtworkChanged(const gfx::ImageSkia& image) override;
+  void OnColorsChanged(SkColor foreground, SkColor background) override;
+
+  // views::SlideOutControllerDelegate:
+  ui::Layer* GetSlideOutLayer() override;
+  void OnSlideStarted() override {}
+  void OnSlideChanged(bool in_progress) override {}
+  void OnSlideOut() override;
+
+  // views::ButtonListener:
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+
+  // MediaNotificationContainerImpl:
+  void AddObserver(MediaNotificationContainerObserver* observer) override;
+  void RemoveObserver(MediaNotificationContainerObserver* observer) override;
+
+  views::ImageButton* GetDismissButtonForTesting();
+
+  media_message_center::MediaNotificationView* view_for_testing() {
+    return view_.get();
+  }
+
+ private:
+  class DismissButton;
+
+  void UpdateDismissButtonIcon();
+
+  void UpdateDismissButtonBackground();
+
+  void DismissNotification();
+
+  // Updates the forced expanded state of |view_|.
+  void ForceExpandedState();
+
+  const std::string id_;
+  std::unique_ptr<views::View> swipeable_container_;
+  std::unique_ptr<views::View> dismiss_button_container_;
+  DismissButton* dismiss_button_;
+  std::unique_ptr<media_message_center::MediaNotificationView> view_;
+
+  SkColor foreground_color_;
+  SkColor background_color_;
+
+  bool has_artwork_ = false;
+  bool has_many_actions_ = false;
+
+  base::ObserverList<MediaNotificationContainerObserver> observers_;
+
+  // Handles gesture events for swiping to dismiss notifications.
+  std::unique_ptr<views::SlideOutController> slide_out_controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaNotificationContainerImplView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_VIEW_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view_unittest.cc b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view_unittest.cc
new file mode 100644
index 0000000..2a3a04b
--- /dev/null
+++ b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view_unittest.cc
@@ -0,0 +1,246 @@
+// 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 "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/global_media_controls/media_notification_container_observer.h"
+#include "services/media_session/public/mojom/media_session.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/views/test/button_test_api.h"
+#include "ui/views/test/views_test_base.h"
+
+using media_session::mojom::MediaPlaybackState;
+using media_session::mojom::MediaSessionAction;
+using ::testing::_;
+
+namespace {
+
+const char kTestNotificationId[] = "testid";
+const char kOtherTestNotificationId[] = "othertestid";
+
+class MockMediaNotificationContainerObserver
+    : public MediaNotificationContainerObserver {
+ public:
+  MockMediaNotificationContainerObserver() = default;
+  ~MockMediaNotificationContainerObserver() = default;
+
+  // MediaNotificationContainerObserver implementation.
+  MOCK_METHOD1(OnContainerExpanded, void(bool expanded));
+  MOCK_METHOD0(OnContainerMetadataChanged, void());
+  MOCK_METHOD1(OnContainerDismissed, void(const std::string& id));
+  MOCK_METHOD1(OnContainerDestroyed, void(const std::string& id));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockMediaNotificationContainerObserver);
+};
+
+}  // anonymous namespace
+
+class MediaNotificationContainerImplViewTest : public views::ViewsTestBase {
+ public:
+  MediaNotificationContainerImplViewTest() = default;
+  ~MediaNotificationContainerImplViewTest() override = default;
+
+  // ViewsTestBase:
+  void SetUp() override {
+    ViewsTestBase::SetUp();
+
+    views::Widget::InitParams params =
+        CreateParams(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+    params.bounds = gfx::Rect(400, 300);
+    params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+    widget_.Init(std::move(params));
+    views::View* container_view = new views::View();
+    widget_.SetContentsView(container_view);
+
+    auto notification_container =
+        std::make_unique<MediaNotificationContainerImplView>(
+            kTestNotificationId, nullptr);
+    notification_container_ =
+        container_view->AddChildView(std::move(notification_container));
+
+    observer_ = std::make_unique<MockMediaNotificationContainerObserver>();
+    notification_container_->AddObserver(observer_.get());
+
+    SimulateMediaSessionData();
+
+    widget_.Show();
+  }
+
+  void TearDown() override {
+    notification_container_->RemoveObserver(observer_.get());
+    widget_.Close();
+    ViewsTestBase::TearDown();
+  }
+
+  void SimulateNotificationSwipedToDismiss() {
+    // When the notification is swiped, the SlideOutController sends this to the
+    // MediaNotificationContainerImplView.
+    notification_container()->OnSlideOut();
+  }
+
+  bool IsDismissButtonVisible() { return GetDismissButton()->IsDrawn(); }
+
+  void SimulateDismissButtonClicked() {
+    ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                         ui::EventTimeForNow(), 0, 0);
+    views::test::ButtonTestApi(GetDismissButton()).NotifyClick(event);
+  }
+
+  void SimulateSessionPlaying() { SimulateSessionInfo(true); }
+
+  void SimulateSessionPaused() { SimulateSessionInfo(false); }
+
+  void SimulateMetadataChanged() {
+    media_session::MediaMetadata metadata;
+    metadata.source_title = base::ASCIIToUTF16("source_title2");
+    metadata.title = base::ASCIIToUTF16("title2");
+    metadata.artist = base::ASCIIToUTF16("artist2");
+    GetView()->UpdateWithMediaMetadata(metadata);
+  }
+
+  void SimulateAllActionsEnabled() {
+    actions_.insert(MediaSessionAction::kPlay);
+    actions_.insert(MediaSessionAction::kPause);
+    actions_.insert(MediaSessionAction::kPreviousTrack);
+    actions_.insert(MediaSessionAction::kNextTrack);
+    actions_.insert(MediaSessionAction::kSeekBackward);
+    actions_.insert(MediaSessionAction::kSeekForward);
+    actions_.insert(MediaSessionAction::kStop);
+
+    NotifyUpdatedActions();
+  }
+
+  void SimulateOnlyPlayPauseEnabled() {
+    actions_.clear();
+    actions_.insert(MediaSessionAction::kPlay);
+    actions_.insert(MediaSessionAction::kPause);
+    NotifyUpdatedActions();
+  }
+
+  void SimulateHasArtwork() {
+    SkBitmap image;
+    image.allocN32Pixels(10, 10);
+    image.eraseColor(SK_ColorMAGENTA);
+    GetView()->UpdateWithMediaArtwork(
+        gfx::ImageSkia::CreateFrom1xBitmap(image));
+  }
+
+  void SimulateHasNoArtwork() {
+    GetView()->UpdateWithMediaArtwork(gfx::ImageSkia());
+  }
+
+  MockMediaNotificationContainerObserver& observer() { return *observer_; }
+
+  MediaNotificationContainerImplView* notification_container() {
+    return notification_container_;
+  }
+
+ private:
+  void SimulateSessionInfo(bool playing) {
+    media_session::mojom::MediaSessionInfoPtr session_info(
+        media_session::mojom::MediaSessionInfo::New());
+    session_info->playback_state =
+        playing ? MediaPlaybackState::kPlaying : MediaPlaybackState::kPaused;
+    session_info->is_controllable = true;
+
+    GetView()->UpdateWithMediaSessionInfo(std::move(session_info));
+  }
+
+  void SimulateMediaSessionData() {
+    SimulateSessionInfo(true);
+
+    media_session::MediaMetadata metadata;
+    metadata.source_title = base::ASCIIToUTF16("source_title");
+    metadata.title = base::ASCIIToUTF16("title");
+    metadata.artist = base::ASCIIToUTF16("artist");
+    GetView()->UpdateWithMediaMetadata(metadata);
+
+    SimulateOnlyPlayPauseEnabled();
+  }
+
+  void NotifyUpdatedActions() { GetView()->UpdateWithMediaActions(actions_); }
+
+  media_message_center::MediaNotificationView* GetView() {
+    return notification_container()->view_for_testing();
+  }
+
+  views::ImageButton* GetDismissButton() {
+    return notification_container()->GetDismissButtonForTesting();
+  }
+
+  views::Widget widget_;
+  MediaNotificationContainerImplView* notification_container_ = nullptr;
+  std::unique_ptr<MockMediaNotificationContainerObserver> observer_;
+
+  // Set of actions currently enabled.
+  std::set<MediaSessionAction> actions_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaNotificationContainerImplViewTest);
+};
+
+TEST_F(MediaNotificationContainerImplViewTest, SwipeToDismiss) {
+  EXPECT_CALL(observer(), OnContainerDismissed(kTestNotificationId));
+  SimulateNotificationSwipedToDismiss();
+}
+
+TEST_F(MediaNotificationContainerImplViewTest, ClickToDismiss) {
+  // We don't show the dismiss button when playing.
+  SimulateSessionPlaying();
+  EXPECT_FALSE(IsDismissButtonVisible());
+
+  // We only show it when paused.
+  SimulateSessionPaused();
+  EXPECT_TRUE(IsDismissButtonVisible());
+
+  // Clicking it should inform observers that we've been dismissed.
+  EXPECT_CALL(observer(), OnContainerDismissed(kTestNotificationId));
+  SimulateDismissButtonClicked();
+}
+
+TEST_F(MediaNotificationContainerImplViewTest, ForceExpandedState) {
+  bool notification_expanded = false;
+  EXPECT_CALL(observer(), OnContainerExpanded(_))
+      .WillRepeatedly([&notification_expanded](bool expanded) {
+        notification_expanded = expanded;
+      });
+
+  // When we have many actions enabled, we should be forced into the expanded
+  // state.
+  SimulateAllActionsEnabled();
+  EXPECT_TRUE(notification_expanded);
+
+  // When we don't have many actions enabled, we should be forced out of the
+  // expanded state.
+  SimulateOnlyPlayPauseEnabled();
+  EXPECT_FALSE(notification_expanded);
+
+  // We will also be forced into the expanded state when artwork is present.
+  SimulateHasArtwork();
+  EXPECT_TRUE(notification_expanded);
+
+  // Once the artwork is gone, we should be forced back out of the expanded
+  // state.
+  SimulateHasNoArtwork();
+  EXPECT_FALSE(notification_expanded);
+}
+
+TEST_F(MediaNotificationContainerImplViewTest, SendsMetadataUpdates) {
+  EXPECT_CALL(observer(), OnContainerMetadataChanged());
+  SimulateMetadataChanged();
+}
+
+TEST_F(MediaNotificationContainerImplViewTest, SendsDestroyedUpdates) {
+  auto container = std::make_unique<MediaNotificationContainerImplView>(
+      kOtherTestNotificationId, nullptr);
+  MockMediaNotificationContainerObserver observer;
+  container->AddObserver(&observer);
+
+  // When the container is destroyed, it should notify the observer.
+  EXPECT_CALL(observer, OnContainerDestroyed(kOtherTestNotificationId));
+  container.reset();
+  testing::Mock::VerifyAndClearExpectations(&observer);
+}
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc b/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc
index 8139413e..3957aba 100644
--- a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h"
 
-#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h"
+#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h"
 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
 #include "ui/views/layout/box_layout.h"
 
@@ -31,7 +31,7 @@
 
 void MediaNotificationListView::ShowNotification(
     const std::string& id,
-    std::unique_ptr<MediaNotificationContainerImpl> notification) {
+    std::unique_ptr<MediaNotificationContainerImplView> notification) {
   DCHECK(!base::Contains(notifications_, id));
   DCHECK_NE(nullptr, notification.get());
 
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.h b/chrome/browser/ui/views/global_media_controls/media_notification_list_view.h
index dc7c6fd6..8bac1f6 100644
--- a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.h
+++ b/chrome/browser/ui/views/global_media_controls/media_notification_list_view.h
@@ -10,7 +10,7 @@
 
 #include "ui/views/controls/scroll_view.h"
 
-class MediaNotificationContainerImpl;
+class MediaNotificationContainerImplView;
 
 // MediaNotificationListView is a container that holds a list of active media
 // sessions.
@@ -21,17 +21,18 @@
 
   void ShowNotification(
       const std::string& id,
-      std::unique_ptr<MediaNotificationContainerImpl> notification);
+      std::unique_ptr<MediaNotificationContainerImplView> notification);
   void HideNotification(const std::string& id);
   bool empty() { return notifications_.empty(); }
 
-  const std::map<const std::string, MediaNotificationContainerImpl*>&
+  const std::map<const std::string, MediaNotificationContainerImplView*>&
   notifications_for_testing() const {
     return notifications_;
   }
 
  private:
-  std::map<const std::string, MediaNotificationContainerImpl*> notifications_;
+  std::map<const std::string, MediaNotificationContainerImplView*>
+      notifications_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaNotificationListView);
 };
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
index 5424961..c5d1c26 100644
--- a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
+++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
@@ -28,13 +28,44 @@
 #include "ui/views/border.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/fill_layout.h"
+#include "ui/views/layout/flex_layout.h"
+#include "ui/views/layout/flex_layout_types.h"
+#include "ui/views/view_class_properties.h"
+
+namespace {
+
+class ChipLabel : public views::Label {
+ public:
+  using views::Label::Label;
+
+  // views::Label
+  gfx::Insets GetInsets() const override {
+    const int chip_corner_radius =
+        views::LayoutProvider::Get()->GetCornerRadiusMetric(
+            views::EMPHASIS_MAXIMUM, size());
+    return gfx::Insets(0, chip_corner_radius, 0, chip_corner_radius);
+  }
+  gfx::Size CalculatePreferredSize() const override {
+    return gfx::Size(views::Label::CalculatePreferredSize().width(),
+                     GetLayoutConstant(LOCATION_BAR_ICON_SIZE));
+  }
+};
+
+}  // namespace
 
 KeywordHintView::KeywordHintView(LocationBarView* parent, Profile* profile)
-    : Button(parent),
-      profile_(profile),
-      chip_container_(new views::View()),
-      chip_label_(
-          new views::Label(base::string16(), CONTEXT_OMNIBOX_DECORATION)) {
+    : Button(parent), profile_(profile) {
+  auto chip_container = std::make_unique<views::View>();
+  auto chip_label =
+      std::make_unique<ChipLabel>(base::string16(), CONTEXT_OMNIBOX_DECORATION);
+
+  auto* layout = SetLayoutManager(std::make_unique<views::FlexLayout>());
+  layout->SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
+      .SetDefault(views::kFlexBehaviorKey,
+                  views::FlexSpecification::ForSizeRule(
+                      views::MinimumFlexSizeRule::kPreferredSnapToZero,
+                      views::MaximumFlexSizeRule::kPreferred, true));
+
   const ui::ThemeProvider* theme_provider =
       &ThemeService::GetThemeProviderForProfile(profile_);
   const SkColor leading_label_text_color =
@@ -43,9 +74,6 @@
       GetOmniboxColor(theme_provider, OmniboxPart::LOCATION_BAR_BACKGROUND);
   leading_label_ = CreateLabel(leading_label_text_color, background_color);
 
-  chip_label_->SetBorder(
-      views::CreateEmptyBorder(gfx::Insets(0, GetCornerRadius())));
-
   const SkColor tab_border_color =
       GetOmniboxColor(theme_provider, OmniboxPart::LOCATION_BAR_BUBBLE_OUTLINE);
   SkColor text_color = leading_label_text_color;
@@ -55,17 +83,23 @@
     text_color = SK_ColorWHITE;
     tab_bg_color = tab_border_color;
   }
-  chip_label_->SetEnabledColor(text_color);
-  chip_label_->SetBackgroundColor(tab_bg_color);
+  chip_label->SetEnabledColor(text_color);
+  chip_label->SetBackgroundColor(tab_bg_color);
 
-  chip_container_->SetBackground(CreateBackgroundFromPainter(
+  chip_container->SetBackground(CreateBackgroundFromPainter(
       views::Painter::CreateRoundRectWith1PxBorderPainter(
           tab_bg_color, tab_border_color,
           views::LayoutProvider::Get()->GetCornerRadiusMetric(
               views::EMPHASIS_HIGH))));
-  chip_container_->AddChildView(chip_label_);
-  chip_container_->SetLayoutManager(std::make_unique<views::FillLayout>());
-  AddChildView(chip_container_);
+  chip_label_ = chip_container->AddChildView(std::move(chip_label));
+  chip_container->SetLayoutManager(std::make_unique<views::FillLayout>());
+  chip_container->SetProperty(
+      views::kFlexBehaviorKey,
+      views::FlexSpecification::ForSizeRule(
+          views::MinimumFlexSizeRule::kPreferred,
+          views::MaximumFlexSizeRule::kPreferred, true));
+  chip_container->SizeToPreferredSize();
+  chip_container_ = AddChildView(std::move(chip_container));
 
   trailing_label_ = CreateLabel(text_color, background_color);
 
@@ -171,43 +205,6 @@
   return "KeywordHintView";
 }
 
-void KeywordHintView::Layout() {
-  const int chip_width = chip_container_->GetPreferredSize().width();
-  const int chip_height = GetLayoutConstant(LOCATION_BAR_ICON_SIZE) +
-                          chip_container_->GetInsets().height();
-  // |chip_container_|'s size must be updated before calling GetInsets(), since
-  // that function reads its height.
-  chip_container_->SetSize(gfx::Size(chip_width, chip_height));
-  bool show_labels = width() - GetInsets().width() > chip_width;
-  gfx::Size leading_size(leading_label_->GetPreferredSize());
-  leading_label_->SetBounds(GetInsets().left(), 0,
-                            show_labels ? leading_size.width() : 0, height());
-
-  const int chip_vertical_padding = std::max(0, height() - chip_height) / 2;
-  chip_container_->SetPosition(
-      gfx::Point(leading_label_->bounds().right(), chip_vertical_padding));
-  gfx::Size trailing_size(trailing_label_->GetPreferredSize());
-  trailing_label_->SetBounds(chip_container_->bounds().right(), 0,
-                             show_labels ? trailing_size.width() : 0, height());
-}
-
-gfx::Size KeywordHintView::CalculatePreferredSize() const {
-  // Height will be ignored by the LocationBarView.
-  return gfx::Size(leading_label_->GetPreferredSize().width() +
-                       chip_container_->GetPreferredSize().width() +
-                       trailing_label_->GetPreferredSize().width() +
-                       GetInsets().width(),
-                   0);
-}
-
-void KeywordHintView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
-  const int chip_corner_radius = GetCornerRadius();
-  chip_label_->SetBorder(views::CreateEmptyBorder(
-      gfx::Insets(GetInsets().top(), chip_corner_radius, GetInsets().bottom(),
-                  chip_corner_radius)));
-  views::Button::OnBoundsChanged(previous_bounds);
-}
-
 void KeywordHintView::OnThemeChanged() {
   const SkColor leading_label_text_color = GetOmniboxColor(
       GetThemeProvider(), OmniboxPart::LOCATION_BAR_TEXT_DEFAULT);
@@ -240,14 +237,9 @@
 
 views::Label* KeywordHintView::CreateLabel(SkColor text_color,
                                            SkColor background_color) {
-  views::Label* label =
-      new views::Label(base::string16(), CONTEXT_OMNIBOX_DECORATION);
+  auto label = std::make_unique<views::Label>(base::string16(),
+                                              CONTEXT_OMNIBOX_DECORATION);
   label->SetEnabledColor(text_color);
   label->SetBackgroundColor(background_color);
-  AddChildView(label);
-  return label;
-}
-
-int KeywordHintView::GetCornerRadius() const {
-  return chip_container_->height() / 2;
+  return AddChildView(std::move(label));
 }
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.h b/chrome/browser/ui/views/location_bar/keyword_hint_view.h
index 548ddc7b..5b20fbd 100644
--- a/chrome/browser/ui/views/location_bar/keyword_hint_view.h
+++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.h
@@ -40,9 +40,6 @@
   // The minimum size is just big enough to show the tab.
   gfx::Size GetMinimumSize() const override;
   const char* GetClassName() const override;
-  void Layout() override;
-  gfx::Size CalculatePreferredSize() const override;
-  void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
 
   void OnThemeChanged() override;
 
@@ -50,8 +47,6 @@
   // Creates a label for non-chip text.
   views::Label* CreateLabel(SkColor text_color, SkColor background_color);
 
-  int GetCornerRadius() const;
-
   Profile* profile_ = nullptr;
 
   views::Label* leading_label_ = nullptr;
diff --git a/chrome/browser/ui/views/media_router/cloud_services_dialog_view.cc b/chrome/browser/ui/views/media_router/cloud_services_dialog_view.cc
index f430b108..3963061 100644
--- a/chrome/browser/ui/views/media_router/cloud_services_dialog_view.cc
+++ b/chrome/browser/ui/views/media_router/cloud_services_dialog_view.cc
@@ -74,14 +74,6 @@
       IDS_MEDIA_ROUTER_CLOUD_SERVICES_DIALOG_TITLE);
 }
 
-base::string16 CloudServicesDialogView::GetDialogButtonLabel(
-    ui::DialogButton button) const {
-  return l10n_util::GetStringUTF16(
-      button == ui::DIALOG_BUTTON_OK
-          ? IDS_MEDIA_ROUTER_CLOUD_SERVICES_DIALOG_ENABLE
-          : IDS_MEDIA_ROUTER_CLOUD_SERVICES_DIALOG_CANCEL);
-}
-
 int CloudServicesDialogView::GetDialogButtons() const {
   return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
 }
@@ -110,6 +102,12 @@
                                                  Browser* browser)
     : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
       browser_(browser) {
+  DialogDelegate::set_button_label(
+      ui::DIALOG_BUTTON_OK,
+      l10n_util::GetStringUTF16(IDS_MEDIA_ROUTER_CLOUD_SERVICES_DIALOG_ENABLE));
+  DialogDelegate::set_button_label(
+      ui::DIALOG_BUTTON_CANCEL,
+      l10n_util::GetStringUTF16(IDS_MEDIA_ROUTER_CLOUD_SERVICES_DIALOG_CANCEL));
   set_close_on_deactivate(false);
   SetLayoutManager(std::make_unique<views::FillLayout>());
 }
diff --git a/chrome/browser/ui/views/media_router/cloud_services_dialog_view.h b/chrome/browser/ui/views/media_router/cloud_services_dialog_view.h
index 6d4c6e6..cd6bf0d 100644
--- a/chrome/browser/ui/views/media_router/cloud_services_dialog_view.h
+++ b/chrome/browser/ui/views/media_router/cloud_services_dialog_view.h
@@ -36,7 +36,6 @@
   base::string16 GetWindowTitle() const override;
 
   // views::DialogDelegate:
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   int GetDialogButtons() const override;
   bool Accept() override;
   bool Cancel() override;
diff --git a/chrome/browser/ui/views/media_router/media_remoting_dialog_view.cc b/chrome/browser/ui/views/media_router/media_remoting_dialog_view.cc
index 2254df7..41456f09 100644
--- a/chrome/browser/ui/views/media_router/media_remoting_dialog_view.cc
+++ b/chrome/browser/ui/views/media_router/media_remoting_dialog_view.cc
@@ -82,14 +82,6 @@
   return dialog_title_;
 }
 
-base::string16 MediaRemotingDialogView::GetDialogButtonLabel(
-    ui::DialogButton button) const {
-  return l10n_util::GetStringUTF16(
-      button == ui::DIALOG_BUTTON_OK
-          ? IDS_MEDIA_ROUTER_REMOTING_DIALOG_OPTIMIZE_BUTTON
-          : IDS_MEDIA_ROUTER_REMOTING_DIALOG_CANCEL_BUTTON);
-}
-
 int MediaRemotingDialogView::GetDialogButtons() const {
   return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
 }
@@ -127,6 +119,14 @@
       dialog_title_(
           l10n_util::GetStringUTF16(IDS_MEDIA_ROUTER_REMOTING_DIALOG_TITLE)) {
   DCHECK(pref_service_);
+  DialogDelegate::set_button_label(
+      ui::DIALOG_BUTTON_OK,
+      l10n_util::GetStringUTF16(
+          IDS_MEDIA_ROUTER_REMOTING_DIALOG_OPTIMIZE_BUTTON));
+  DialogDelegate::set_button_label(
+      ui::DIALOG_BUTTON_CANCEL,
+      l10n_util::GetStringUTF16(
+          IDS_MEDIA_ROUTER_REMOTING_DIALOG_CANCEL_BUTTON));
   SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kVertical));
   // Depress the Cast toolbar icon.
diff --git a/chrome/browser/ui/views/media_router/media_remoting_dialog_view.h b/chrome/browser/ui/views/media_router/media_remoting_dialog_view.h
index 24133f9..0e2386d 100644
--- a/chrome/browser/ui/views/media_router/media_remoting_dialog_view.h
+++ b/chrome/browser/ui/views/media_router/media_remoting_dialog_view.h
@@ -46,7 +46,6 @@
   base::string16 GetWindowTitle() const override;
 
   // views::DialogDelegate:
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   int GetDialogButtons() const override;
   bool Accept() override;
   bool Cancel() override;
diff --git a/chrome/browser/ui/views/native_file_system/native_file_system_browsertest.cc b/chrome/browser/ui/views/native_file_system/native_file_system_browsertest.cc
index 07034a6..8f80078 100644
--- a/chrome/browser/ui/views/native_file_system/native_file_system_browsertest.cc
+++ b/chrome/browser/ui/views/native_file_system/native_file_system_browsertest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/browser_test_utils.h"
 #include "third_party/blink/public/common/features.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 #include "ui/shell_dialogs/select_file_dialog_factory.h"
@@ -99,6 +100,12 @@
     ui::SelectFileDialog::SetFactory(nullptr);
   }
 
+  bool IsFullscreen() {
+    content::WebContents* web_contents =
+        browser()->tab_strip_model()->GetActiveWebContents();
+    return web_contents->IsFullscreenForCurrentTab();
+  }
+
   base::FilePath CreateTestFile(const std::string& contents) {
     base::ScopedAllowBlockingForTesting allow_blocking;
     base::FilePath result;
@@ -215,6 +222,54 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_F(NativeFileSystemBrowserTest, FullscreenOpenFile) {
+  const base::FilePath test_file = CreateTestFile("");
+  const std::string file_contents = "file contents to write";
+  GURL frame_url = embedded_test_server()->GetURL("/title1.html");
+
+  ui::SelectFileDialog::SetFactory(
+      new FakeSelectFileDialogFactory({test_file}));
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL("/title1.html"));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  NativeFileSystemPermissionRequestManager::FromWebContents(web_contents)
+      ->set_auto_response_for_test(PermissionAction::GRANTED);
+
+  EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(),
+            content::EvalJs(web_contents,
+                            "(async () => {"
+                            "  let e = await self.chooseFileSystemEntries("
+                            "      {type: 'openFile'});"
+                            "  self.entry = e;"
+                            "  return e.name; })()"));
+
+  EXPECT_TRUE(
+      content::ExecuteScript(web_contents,
+                             "(async () => {"
+                             "  await document.body.requestFullscreen();"
+                             "})()"));
+
+  // Wait until the fullscreen operation completes.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(IsFullscreen());
+
+  EXPECT_TRUE(content::ExecuteScript(
+      web_contents,
+      "(async () => {"
+      "  let fsChangePromise = new Promise((resolve) => {"
+      "    document.onfullscreenchange = resolve;"
+      "  });"
+      "  const w = await self.entry.createWriter();"
+      "  await fsChangePromise;"
+      "  return; })()"));
+
+  // Wait until the fullscreen exit operation completes.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(IsFullscreen());
+}
+
 IN_PROC_BROWSER_TEST_F(NativeFileSystemBrowserTest, SafeBrowsing) {
   const base::FilePath test_file = temp_dir_.GetPath().AppendASCII("test.exe");
 
diff --git a/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.cc b/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.cc
index fc6b76d8..faa208d 100644
--- a/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.cc
+++ b/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.cc
@@ -51,7 +51,6 @@
   base::string16 GetWindowTitle() const override;
 
   // views::DialogDelegate:
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;
   views::View* GetInitiallyFocusedView() override;
   std::unique_ptr<views::View> CreateExtraView() override;
@@ -95,6 +94,11 @@
   // | Get help                         |
   // ------------------------------------
 
+  DialogDelegate::set_button_label(ui::DIALOG_BUTTON_OK,
+                                   chooser_controller->GetOkButtonLabel());
+  DialogDelegate::set_button_label(ui::DIALOG_BUTTON_CANCEL,
+                                   chooser_controller->GetCancelButtonLabel());
+
   SetLayoutManager(std::make_unique<views::FillLayout>());
   device_chooser_content_view_ =
       new DeviceChooserContentView(this, std::move(chooser_controller));
@@ -120,11 +124,6 @@
   return dcv ? dcv->cancel_button() : nullptr;
 }
 
-base::string16 ChooserBubbleUiViewDelegate::GetDialogButtonLabel(
-    ui::DialogButton button) const {
-  return device_chooser_content_view_->GetDialogButtonLabel(button);
-}
-
 bool ChooserBubbleUiViewDelegate::IsDialogButtonEnabled(
     ui::DialogButton button) const {
   return device_chooser_content_view_->IsDialogButtonEnabled(button);
diff --git a/chrome/browser/ui/views/profiles/incognito_menu_view.cc b/chrome/browser/ui/views/profiles/incognito_menu_view.cc
index 5b08c92a..65e36fe7 100644
--- a/chrome/browser/ui/views/profiles/incognito_menu_view.cc
+++ b/chrome/browser/ui/views/profiles/incognito_menu_view.cc
@@ -49,23 +49,40 @@
   const SkColor icon_color = provider->GetTypographyProvider().GetColor(
       *this, views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY);
 
-  auto incognito_icon = std::make_unique<views::ImageView>();
-  incognito_icon->SetImage(
-      gfx::CreateVectorIcon(kIncognitoProfileIcon, icon_color));
+  if (!base::FeatureList::IsEnabled(features::kProfileMenuRevamp)) {
+    auto incognito_icon = std::make_unique<views::ImageView>();
+    incognito_icon->SetImage(
+        gfx::CreateVectorIcon(kIncognitoProfileIcon, icon_color));
 
-  AddMenuGroup(false /* add_separator */);
-  CreateAndAddTitleCard(
-      std::move(incognito_icon),
+    AddMenuGroup(false /* add_separator */);
+    CreateAndAddTitleCard(
+        std::move(incognito_icon),
+        l10n_util::GetStringUTF16(IDS_INCOGNITO_PROFILE_MENU_TITLE),
+        incognito_window_count > 1
+            ? l10n_util::GetPluralStringFUTF16(
+                  IDS_INCOGNITO_WINDOW_COUNT_MESSAGE, incognito_window_count)
+            : base::string16(),
+        base::RepeatingClosure());
+
+    AddMenuGroup();
+    exit_button_ = CreateAndAddButton(
+        gfx::CreateVectorIcon(kCloseAllIcon, 16, gfx::kChromeIconGrey),
+        l10n_util::GetStringUTF16(IDS_INCOGNITO_PROFILE_MENU_CLOSE_BUTTON),
+        base::BindRepeating(&IncognitoMenuView::OnExitButtonClicked,
+                            base::Unretained(this)));
+    return;
+  }
+
+  SetIdentityInfo(
+      ColoredImageForMenu(kIncognitoProfileIcon, icon_color),
+      /*badge=*/gfx::ImageSkia(),
       l10n_util::GetStringUTF16(IDS_INCOGNITO_PROFILE_MENU_TITLE),
       incognito_window_count > 1
           ? l10n_util::GetPluralStringFUTF16(IDS_INCOGNITO_WINDOW_COUNT_MESSAGE,
                                              incognito_window_count)
-          : base::string16(),
-      base::RepeatingClosure());
-
-  AddMenuGroup();
-  exit_button_ = CreateAndAddButton(
-      gfx::CreateVectorIcon(kCloseAllIcon, 16, gfx::kChromeIconGrey),
+          : base::string16());
+  AddFeatureButton(
+      ImageForMenu(kCloseAllIcon),
       l10n_util::GetStringUTF16(IDS_INCOGNITO_PROFILE_MENU_CLOSE_BUTTON),
       base::BindRepeating(&IncognitoMenuView::OnExitButtonClicked,
                           base::Unretained(this)));
@@ -78,6 +95,7 @@
 }
 
 void IncognitoMenuView::OnExitButtonClicked() {
+  RecordClick(ActionableItem::kExitProfileButton);
   // Skipping before-unload trigger to give incognito mode users a chance to
   // quickly close all incognito windows without needing to confirm closing the
   // open forms.
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc
index 16d59d8e..c5af4529 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -10,7 +10,6 @@
 
 #include "base/feature_list.h"
 #include "base/macros.h"
-#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "build/build_config.h"
@@ -176,16 +175,14 @@
   if (profile->IsRegularProfile()) {
     BuildIdentity();
     BuildSyncInfo();
-    BuildFeatureButtons();
     BuildAutofillButtons();
-  } else if (profile->IsIncognitoProfile()) {
-    BuildIncognitoIdentity();
   } else if (profile->IsGuestSession()) {
     BuildGuestIdentity();
   } else {
     NOTREACHED();
   }
 
+  BuildFeatureButtons();
   BuildProfileManagementHeading();
   BuildSelectableProfiles();
   BuildProfileManagementFeatureButtons();
@@ -403,10 +400,6 @@
                     profiles::USER_MANAGER_OPEN_CREATE_USER_PAGE);
 }
 
-void ProfileMenuView::RecordClick(ActionableItem item) {
-  base::UmaHistogramEnumeration("Profile.Menu.ClickedActionableItem", item);
-}
-
 void ProfileMenuView::BuildIdentity() {
   Profile* profile = browser()->profile();
   signin::IdentityManager* identity_manager =
@@ -438,19 +431,6 @@
                   l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME));
 }
 
-void ProfileMenuView::BuildIncognitoIdentity() {
-  int incognito_window_count =
-      BrowserList::GetIncognitoSessionsActiveForProfile(browser()->profile());
-
-  SetIdentityInfo(
-      ImageForMenu(kIncognitoProfileIcon), GetSyncIcon(),
-      l10n_util::GetStringUTF16(IDS_INCOGNITO_PROFILE_MENU_TITLE),
-      incognito_window_count > 1
-          ? l10n_util::GetPluralStringFUTF16(IDS_INCOGNITO_WINDOW_COUNT_MESSAGE,
-                                             incognito_window_count)
-          : base::string16());
-}
-
 gfx::ImageSkia ProfileMenuView::GetSyncIcon() {
   Profile* profile = browser()->profile();
   signin::IdentityManager* identity_manager =
@@ -567,23 +547,35 @@
 void ProfileMenuView::BuildFeatureButtons() {
   signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(browser()->profile());
-  if (!identity_manager->HasUnconsentedPrimaryAccount())
-    return;
+  const bool is_guest = browser()->profile()->IsGuestSession();
+  const bool has_unconsented_account =
+      !is_guest && identity_manager->HasUnconsentedPrimaryAccount();
+  const bool has_primary_account =
+      !is_guest && identity_manager->HasPrimaryAccount();
+
+  if (has_unconsented_account) {
+    AddFeatureButton(
+#if defined(GOOGLE_CHROME_BUILD)
+        // The Google G icon needs to be shrunk, so it won't look too big
+        // compared to the other icons.
+        ImageForMenu(kGoogleGLogoIcon, /*icon_to_image_ratio=*/0.75),
+#else
+        gfx::ImageSkia(),
+#endif
+        l10n_util::GetStringUTF16(IDS_SETTINGS_MANAGE_GOOGLE_ACCOUNT),
+        base::BindRepeating(
+            &ProfileMenuView::OnManageGoogleAccountButtonClicked,
+            base::Unretained(this)));
+  }
 
   AddFeatureButton(
-#if defined(GOOGLE_CHROME_BUILD)
-      // The Google G icon needs to be shrunk, so it won't look too big
-      // compared to the other icons.
-      ImageForMenu(kGoogleGLogoIcon, /*icon_to_image_ratio=*/0.75),
-#else
-      gfx::ImageSkia(),
-#endif
-      l10n_util::GetStringUTF16(IDS_SETTINGS_MANAGE_GOOGLE_ACCOUNT),
-      base::BindRepeating(&ProfileMenuView::OnManageGoogleAccountButtonClicked,
+      ImageForMenu(kCloseAllIcon),
+      l10n_util::GetStringUTF16(IDS_PROFILES_CLOSE_ALL_WINDOWS_BUTTON),
+      base::BindRepeating(&ProfileMenuView::OnExitProfileButtonClicked,
                           base::Unretained(this)));
 
-  if (!identity_manager->HasPrimaryAccount()) {
-    // The sign-out button is only shown when sync is off.
+  // The sign-out button is always at the bottom.
+  if (has_unconsented_account && !has_primary_account) {
     AddFeatureButton(
         ImageForMenu(kSignOutIcon),
         l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT),
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.h b/chrome/browser/ui/views/profiles/profile_menu_view.h
index e28e8af..39233239 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.h
@@ -30,29 +30,6 @@
 // It displays a list of profiles and allows users to switch between profiles.
 class ProfileMenuView : public ProfileMenuViewBase, public AvatarMenuObserver {
  public:
-  // These values are persisted to logs. Entries should not be renumbered and
-  // numeric values should never be reused.
-  enum class ActionableItem {
-    kManageGoogleAccountButton = 0,
-    kPasswordsButton = 1,
-    kCreditCardsButton = 2,
-    kAddressesButton = 3,
-    kGuestProfileButton = 4,
-    kManageProfilesButton = 5,
-    kLockButton = 6,
-    kExitProfileButton = 7,
-    kSyncErrorButton = 8,
-    kCurrentProfileCard = 9,
-    kSigninButton = 10,
-    kSigninAccountButton = 11,
-    kSignoutButton = 12,
-    kOtherProfileButton = 13,
-    kCookiesClearedOnExitLink = 14,
-    kAddNewProfileButton = 15,
-    kSyncSettingsButton = 16,
-    kMaxValue = kSyncSettingsButton,
-  };
-
   ProfileMenuView(views::Button* anchor_button,
                      Browser* browser,
                      signin_metrics::AccessPoint access_point);
@@ -90,9 +67,6 @@
   void OnCookiesClearedOnExitLinkClicked();
   void OnAddNewProfileButtonClicked();
 
-  // Should be called inside each button/link action.
-  void RecordClick(ActionableItem item);
-
   // AvatarMenuObserver:
   void OnAvatarMenuChanged(AvatarMenu* avatar_menu) override;
 
@@ -104,7 +78,6 @@
   // Helper methods for building the menu.
   void BuildIdentity();
   void BuildGuestIdentity();
-  void BuildIncognitoIdentity();
   gfx::ImageSkia GetSyncIcon();
   void BuildAutofillButtons();
   void BuildSyncInfo();
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
index 1de09225..e212e83 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -10,6 +10,7 @@
 
 #include "base/feature_list.h"
 #include "base/macros.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/user_metrics.h"
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
@@ -202,29 +203,17 @@
 
   ProfileMenuViewBase* bubble;
 
-  if (base::FeatureList::IsEnabled(features::kProfileMenuRevamp)) {
-#if !defined(OS_CHROMEOS)
-    // On Desktop, all modes(regular, guest, incognito) are handled within
-    // ProfileMenuView.
-    bubble = new ProfileMenuView(anchor_button, browser, access_point);
-#else
-    // On ChromeOS, only the incognito menu is implemented.
+  if (view_mode == profiles::BUBBLE_VIEW_MODE_INCOGNITO) {
     DCHECK(browser->profile()->IsIncognitoProfile());
     bubble = new IncognitoMenuView(anchor_button, browser);
-#endif
   } else {
-    if (view_mode == profiles::BUBBLE_VIEW_MODE_INCOGNITO) {
-      DCHECK(browser->profile()->IsIncognitoProfile());
-      bubble = new IncognitoMenuView(anchor_button, browser);
-    } else {
-      DCHECK_EQ(profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER, view_mode);
+    DCHECK_EQ(profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER, view_mode);
 #if !defined(OS_CHROMEOS)
-      bubble = new ProfileMenuView(anchor_button, browser, access_point);
+    bubble = new ProfileMenuView(anchor_button, browser, access_point);
 #else
-      NOTREACHED();
-      return;
+    NOTREACHED();
+    return;
 #endif
-    }
   }
 
   views::BubbleDialogDelegateView::CreateBubble(bubble)->Show();
@@ -527,6 +516,11 @@
   return gfx::CreateVectorIcon(icon, kMaxImageSize, color);
 }
 
+void ProfileMenuViewBase::RecordClick(ActionableItem item) {
+  // TODO(tangltom): Separate metrics for incognito and guest menu.
+  base::UmaHistogramEnumeration("Profile.Menu.ClickedActionableItem", item);
+}
+
 ax::mojom::Role ProfileMenuViewBase::GetAccessibleWindowRole() {
   // Return |ax::mojom::Role::kDialog| which will make screen readers announce
   // the following in the listed order:
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
index 674221c..5ef742c 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -42,6 +42,30 @@
                             public views::StyledLabelListener,
                             public views::LinkListener {
  public:
+  // Enumeration of all actionable items in the profile menu.
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  enum class ActionableItem {
+    kManageGoogleAccountButton = 0,
+    kPasswordsButton = 1,
+    kCreditCardsButton = 2,
+    kAddressesButton = 3,
+    kGuestProfileButton = 4,
+    kManageProfilesButton = 5,
+    kLockButton = 6,
+    kExitProfileButton = 7,
+    kSyncErrorButton = 8,
+    kCurrentProfileCard = 9,
+    kSigninButton = 10,
+    kSigninAccountButton = 11,
+    kSignoutButton = 12,
+    kOtherProfileButton = 13,
+    kCookiesClearedOnExitLink = 14,
+    kAddNewProfileButton = 15,
+    kSyncSettingsButton = 16,
+    kMaxValue = kSyncSettingsButton,
+  };
+
   // MenuItems struct keeps the menu items and meta data for a group of items in
   // a menu. It takes the ownership of views and passes it to the menu when menu
   // is constructed.
@@ -127,6 +151,8 @@
                               float icon_to_image_ratio = 1.0f);
   gfx::ImageSkia ColoredImageForMenu(const gfx::VectorIcon& icon,
                                      SkColor color);
+  // Should be called inside each button/link action.
+  void RecordClick(ActionableItem item);
 
   // Initializes a new group of menu items. A separator is added before them if
   // |add_separator| is true.
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
index c56229e5..f340f3b 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
@@ -600,7 +600,7 @@
 // the correct action of the buttons in the profile menu. This is done by
 // advancing the focus to each button and simulating a click. It is expected
 // that each button records a histogram sample from
-// |ProfileMenuView::ActionableItem|.
+// |ProfileMenuViewBase::ActionableItem|.
 //
 // Subclasses have to implement |GetExpectedActionableItemAtIndex|. The test
 // itself should contain the setup and a call to |RunTest|. Example test suite
@@ -608,7 +608,7 @@
 //
 // class ProfileMenuClickTest_WithPrimaryAccount : public ProfileMenuClickTest {
 //   ...
-//   ProfileMenuView::ActionableItem GetExpectedActionableItemAtIndex(
+//   ProfileMenuViewBase::ActionableItem GetExpectedActionableItemAtIndex(
 //      size_t index) override {
 //     return ...;
 //   }
@@ -643,7 +643,7 @@
         ProfileSyncServiceHarness::SigninType::FAKE_SIGNIN);
   }
 
-  virtual ProfileMenuView::ActionableItem GetExpectedActionableItemAtIndex(
+  virtual ProfileMenuViewBase::ActionableItem GetExpectedActionableItemAtIndex(
       size_t index) = 0;
 
   // This should be called in the test body.
@@ -737,40 +737,42 @@
   DISALLOW_COPY_AND_ASSIGN(ProfileMenuClickTest);
 };
 
-#define PROFILE_MENU_CLICK_TEST(actionable_item_list, test_case_name) \
-  class test_case_name : public ProfileMenuClickTest {                \
-   public:                                                            \
-    test_case_name() = default;                                       \
-                                                                      \
-    ProfileMenuView::ActionableItem GetExpectedActionableItemAtIndex( \
-        size_t index) override {                                      \
-      return actionable_item_list[index];                             \
-    }                                                                 \
-                                                                      \
-    DISALLOW_COPY_AND_ASSIGN(test_case_name);                         \
-  };                                                                  \
-                                                                      \
-  INSTANTIATE_TEST_SUITE_P(                                           \
-      , test_case_name,                                               \
-      ::testing::Range(size_t(0), base::size(actionable_item_list))); \
-                                                                      \
+#define PROFILE_MENU_CLICK_TEST(actionable_item_list, test_case_name)     \
+  class test_case_name : public ProfileMenuClickTest {                    \
+   public:                                                                \
+    test_case_name() = default;                                           \
+                                                                          \
+    ProfileMenuViewBase::ActionableItem GetExpectedActionableItemAtIndex( \
+        size_t index) override {                                          \
+      return actionable_item_list[index];                                 \
+    }                                                                     \
+                                                                          \
+    DISALLOW_COPY_AND_ASSIGN(test_case_name);                             \
+  };                                                                      \
+                                                                          \
+  INSTANTIATE_TEST_SUITE_P(                                               \
+      , test_case_name,                                                   \
+      ::testing::Range(size_t(0), base::size(actionable_item_list)));     \
+                                                                          \
   IN_PROC_BROWSER_TEST_P(test_case_name, test_case_name)
 
 // List of actionable items in the correct order as they appear in the menu.
 // If a new button is added to the menu, it should also be added to this list.
-constexpr ProfileMenuView::ActionableItem kActionableItems_MultipleProfiles[] =
-    {ProfileMenuView::ActionableItem::kPasswordsButton,
-     ProfileMenuView::ActionableItem::kCreditCardsButton,
-     ProfileMenuView::ActionableItem::kAddressesButton,
-     ProfileMenuView::ActionableItem::kSigninButton,
-     ProfileMenuView::ActionableItem::kManageProfilesButton,
-     ProfileMenuView::ActionableItem::kOtherProfileButton,
-     ProfileMenuView::ActionableItem::kOtherProfileButton,
-     ProfileMenuView::ActionableItem::kGuestProfileButton,
-     ProfileMenuView::ActionableItem::kAddNewProfileButton,
-     // The first button is added again to finish the cycle and test that
-     // there are no other buttons at the end.
-     ProfileMenuView::ActionableItem::kPasswordsButton};
+constexpr ProfileMenuViewBase::ActionableItem
+    kActionableItems_MultipleProfiles[] = {
+        ProfileMenuViewBase::ActionableItem::kPasswordsButton,
+        ProfileMenuViewBase::ActionableItem::kCreditCardsButton,
+        ProfileMenuViewBase::ActionableItem::kAddressesButton,
+        ProfileMenuViewBase::ActionableItem::kSigninButton,
+        ProfileMenuViewBase::ActionableItem::kExitProfileButton,
+        ProfileMenuViewBase::ActionableItem::kManageProfilesButton,
+        ProfileMenuViewBase::ActionableItem::kOtherProfileButton,
+        ProfileMenuViewBase::ActionableItem::kOtherProfileButton,
+        ProfileMenuViewBase::ActionableItem::kGuestProfileButton,
+        ProfileMenuViewBase::ActionableItem::kAddNewProfileButton,
+        // The first button is added again to finish the cycle and test that
+        // there are no other buttons at the end.
+        ProfileMenuViewBase::ActionableItem::kPasswordsButton};
 
 PROFILE_MENU_CLICK_TEST(kActionableItems_MultipleProfiles,
                         ProfileMenuClickTest_MultipleProfiles) {
@@ -782,18 +784,19 @@
 
 // List of actionable items in the correct order as they appear in the menu.
 // If a new button is added to the menu, it should also be added to this list.
-constexpr ProfileMenuView::ActionableItem kActionableItems_SyncEnabled[] = {
-    ProfileMenuView::ActionableItem::kPasswordsButton,
-    ProfileMenuView::ActionableItem::kCreditCardsButton,
-    ProfileMenuView::ActionableItem::kAddressesButton,
-    ProfileMenuView::ActionableItem::kSyncSettingsButton,
-    ProfileMenuView::ActionableItem::kManageGoogleAccountButton,
-    ProfileMenuView::ActionableItem::kManageProfilesButton,
-    ProfileMenuView::ActionableItem::kGuestProfileButton,
-    ProfileMenuView::ActionableItem::kAddNewProfileButton,
+constexpr ProfileMenuViewBase::ActionableItem kActionableItems_SyncEnabled[] = {
+    ProfileMenuViewBase::ActionableItem::kPasswordsButton,
+    ProfileMenuViewBase::ActionableItem::kCreditCardsButton,
+    ProfileMenuViewBase::ActionableItem::kAddressesButton,
+    ProfileMenuViewBase::ActionableItem::kSyncSettingsButton,
+    ProfileMenuViewBase::ActionableItem::kManageGoogleAccountButton,
+    ProfileMenuViewBase::ActionableItem::kExitProfileButton,
+    ProfileMenuViewBase::ActionableItem::kManageProfilesButton,
+    ProfileMenuViewBase::ActionableItem::kGuestProfileButton,
+    ProfileMenuViewBase::ActionableItem::kAddNewProfileButton,
     // The first button is added again to finish the cycle and test that
     // there are no other buttons at the end.
-    ProfileMenuView::ActionableItem::kPasswordsButton};
+    ProfileMenuViewBase::ActionableItem::kPasswordsButton};
 
 PROFILE_MENU_CLICK_TEST(kActionableItems_SyncEnabled,
                         ProfileMenuClickTest_SyncEnabled) {
@@ -807,18 +810,19 @@
 
 // List of actionable items in the correct order as they appear in the menu.
 // If a new button is added to the menu, it should also be added to this list.
-constexpr ProfileMenuView::ActionableItem kActionableItems_SyncError[] = {
-    ProfileMenuView::ActionableItem::kPasswordsButton,
-    ProfileMenuView::ActionableItem::kCreditCardsButton,
-    ProfileMenuView::ActionableItem::kAddressesButton,
-    ProfileMenuView::ActionableItem::kSyncErrorButton,
-    ProfileMenuView::ActionableItem::kManageGoogleAccountButton,
-    ProfileMenuView::ActionableItem::kManageProfilesButton,
-    ProfileMenuView::ActionableItem::kGuestProfileButton,
-    ProfileMenuView::ActionableItem::kAddNewProfileButton,
+constexpr ProfileMenuViewBase::ActionableItem kActionableItems_SyncError[] = {
+    ProfileMenuViewBase::ActionableItem::kPasswordsButton,
+    ProfileMenuViewBase::ActionableItem::kCreditCardsButton,
+    ProfileMenuViewBase::ActionableItem::kAddressesButton,
+    ProfileMenuViewBase::ActionableItem::kSyncErrorButton,
+    ProfileMenuViewBase::ActionableItem::kManageGoogleAccountButton,
+    ProfileMenuViewBase::ActionableItem::kExitProfileButton,
+    ProfileMenuViewBase::ActionableItem::kManageProfilesButton,
+    ProfileMenuViewBase::ActionableItem::kGuestProfileButton,
+    ProfileMenuViewBase::ActionableItem::kAddNewProfileButton,
     // The first button is added again to finish the cycle and test that
     // there are no other buttons at the end.
-    ProfileMenuView::ActionableItem::kPasswordsButton};
+    ProfileMenuViewBase::ActionableItem::kPasswordsButton};
 
 PROFILE_MENU_CLICK_TEST(kActionableItems_SyncError,
                         ProfileMenuClickTest_SyncError) {
@@ -832,20 +836,21 @@
 
 // List of actionable items in the correct order as they appear in the menu.
 // If a new button is added to the menu, it should also be added to this list.
-constexpr ProfileMenuView::ActionableItem
+constexpr ProfileMenuViewBase::ActionableItem
     kActionableItems_WithUnconsentedPrimaryAccount[] = {
-        ProfileMenuView::ActionableItem::kPasswordsButton,
-        ProfileMenuView::ActionableItem::kCreditCardsButton,
-        ProfileMenuView::ActionableItem::kAddressesButton,
-        ProfileMenuView::ActionableItem::kSigninAccountButton,
-        ProfileMenuView::ActionableItem::kManageGoogleAccountButton,
-        ProfileMenuView::ActionableItem::kSignoutButton,
-        ProfileMenuView::ActionableItem::kManageProfilesButton,
-        ProfileMenuView::ActionableItem::kGuestProfileButton,
-        ProfileMenuView::ActionableItem::kAddNewProfileButton,
+        ProfileMenuViewBase::ActionableItem::kPasswordsButton,
+        ProfileMenuViewBase::ActionableItem::kCreditCardsButton,
+        ProfileMenuViewBase::ActionableItem::kAddressesButton,
+        ProfileMenuViewBase::ActionableItem::kSigninAccountButton,
+        ProfileMenuViewBase::ActionableItem::kManageGoogleAccountButton,
+        ProfileMenuViewBase::ActionableItem::kExitProfileButton,
+        ProfileMenuViewBase::ActionableItem::kSignoutButton,
+        ProfileMenuViewBase::ActionableItem::kManageProfilesButton,
+        ProfileMenuViewBase::ActionableItem::kGuestProfileButton,
+        ProfileMenuViewBase::ActionableItem::kAddNewProfileButton,
         // The first button is added again to finish the cycle and test that
         // there are no other buttons at the end.
-        ProfileMenuView::ActionableItem::kPasswordsButton};
+        ProfileMenuViewBase::ActionableItem::kPasswordsButton};
 
 // TODO(crbug.com/1012167): Flaky.
 PROFILE_MENU_CLICK_TEST(
@@ -861,7 +866,7 @@
   RunTest();
 
   if (GetExpectedActionableItemAtIndex(GetParam()) ==
-      ProfileMenuView::ActionableItem::kSigninAccountButton) {
+      ProfileMenuViewBase::ActionableItem::kSigninAccountButton) {
     // The sync confirmation dialog was opened after clicking the signin button
     // in the profile menu. It needs to be manually dismissed to not cause any
     // crashes during shutdown.
@@ -872,13 +877,14 @@
 
 // List of actionable items in the correct order as they appear in the menu.
 // If a new button is added to the menu, it should also be added to this list.
-constexpr ProfileMenuView::ActionableItem kActionableItems_GuestProfile[] = {
-    ProfileMenuView::ActionableItem::kManageProfilesButton,
-    ProfileMenuView::ActionableItem::kOtherProfileButton,
-    ProfileMenuView::ActionableItem::kAddNewProfileButton,
-    // The first button is added again to finish the cycle and test that
-    // there are no other buttons at the end.
-    ProfileMenuView::ActionableItem::kManageProfilesButton};
+constexpr ProfileMenuViewBase::ActionableItem kActionableItems_GuestProfile[] =
+    {ProfileMenuViewBase::ActionableItem::kExitProfileButton,
+     ProfileMenuViewBase::ActionableItem::kManageProfilesButton,
+     ProfileMenuViewBase::ActionableItem::kOtherProfileButton,
+     ProfileMenuViewBase::ActionableItem::kAddNewProfileButton,
+     // The first button is added again to finish the cycle and test that
+     // there are no other buttons at the end.
+     ProfileMenuViewBase::ActionableItem::kExitProfileButton};
 
 PROFILE_MENU_CLICK_TEST(kActionableItems_GuestProfile,
                         ProfileMenuClickTest_GuestProfile) {
@@ -894,17 +900,15 @@
 
 // List of actionable items in the correct order as they appear in the menu.
 // If a new button is added to the menu, it should also be added to this list.
-constexpr ProfileMenuView::ActionableItem kActionableItems_IncognitoProfile[] =
-    {ProfileMenuView::ActionableItem::kPasswordsButton,
-     ProfileMenuView::ActionableItem::kCreditCardsButton,
-     ProfileMenuView::ActionableItem::kAddressesButton,
-     // The first button is added again to finish the cycle and test that
-     // there are no other buttons at the end.
-     ProfileMenuView::ActionableItem::kPasswordsButton};
+constexpr ProfileMenuViewBase::ActionableItem
+    kActionableItems_IncognitoProfile[] = {
+        ProfileMenuViewBase::ActionableItem::kExitProfileButton,
+        // The first button is added again to finish the cycle and test that
+        // there are no other buttons at the end.
+        ProfileMenuViewBase::ActionableItem::kExitProfileButton};
 
-// TODO(crbug.com/1012167): Flaky.
 PROFILE_MENU_CLICK_TEST(kActionableItems_IncognitoProfile,
-                        DISABLED_ProfileMenuClickTest_IncognitoProfile) {
+                        ProfileMenuClickTest_IncognitoProfile) {
   SetTargetBrowser(CreateIncognitoBrowser(browser()->profile()));
 
   RunTest();
diff --git a/chrome/browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view.cc b/chrome/browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view.cc
index 1a12486..03454ea 100644
--- a/chrome/browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view.cc
+++ b/chrome/browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view.cc
@@ -84,12 +84,6 @@
   return ui::DIALOG_BUTTON_OK;
 }
 
-base::string16 RelaunchRecommendedBubbleView::GetDialogButtonLabel(
-    ui::DialogButton button) const {
-  DCHECK_EQ(button, ui::DIALOG_BUTTON_OK);
-  return l10n_util::GetStringUTF16(IDS_RELAUNCH_ACCEPT_BUTTON);
-}
-
 base::string16 RelaunchRecommendedBubbleView::GetWindowTitle() const {
   return relaunch_recommended_timer_.GetWindowTitle();
 }
@@ -160,6 +154,10 @@
           detection_time,
           base::BindRepeating(&RelaunchRecommendedBubbleView::UpdateWindowTitle,
                               base::Unretained(this))) {
+  DialogDelegate::set_button_label(
+      ui::DIALOG_BUTTON_OK,
+      l10n_util::GetStringUTF16(IDS_RELAUNCH_ACCEPT_BUTTON));
+
   chrome::RecordDialogCreation(chrome::DialogIdentifier::RELAUNCH_RECOMMENDED);
   set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
       views::TEXT, views::TEXT));
diff --git a/chrome/browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view.h b/chrome/browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view.h
index 6fb19e9d..6964ee6 100644
--- a/chrome/browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view.h
+++ b/chrome/browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view.h
@@ -36,7 +36,6 @@
   bool Accept() override;
   bool Close() override;
   int GetDialogButtons() const override;
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   base::string16 GetWindowTitle() const override;
   bool ShouldShowCloseButton() const override;
   gfx::ImageSkia GetWindowIcon() override;
diff --git a/chrome/browser/ui/views/relaunch_notification/relaunch_required_dialog_view.cc b/chrome/browser/ui/views/relaunch_notification/relaunch_required_dialog_view.cc
index 220aded0..2d8e397d 100644
--- a/chrome/browser/ui/views/relaunch_notification/relaunch_required_dialog_view.cc
+++ b/chrome/browser/ui/views/relaunch_notification/relaunch_required_dialog_view.cc
@@ -73,13 +73,6 @@
   return false;
 }
 
-base::string16 RelaunchRequiredDialogView::GetDialogButtonLabel(
-    ui::DialogButton button) const {
-  return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK
-                                       ? IDS_RELAUNCH_ACCEPT_BUTTON
-                                       : IDS_RELAUNCH_REQUIRED_CANCEL_BUTTON);
-}
-
 ui::ModalType RelaunchRequiredDialogView::GetModalType() const {
   return ui::MODAL_TYPE_WINDOW;
 }
@@ -121,6 +114,12 @@
           base::BindRepeating(&RelaunchRequiredDialogView::UpdateWindowTitle,
                               base::Unretained(this))) {
   DialogDelegate::set_default_button(ui::DIALOG_BUTTON_NONE);
+  DialogDelegate::set_button_label(
+      ui::DIALOG_BUTTON_OK,
+      l10n_util::GetStringUTF16(IDS_RELAUNCH_ACCEPT_BUTTON));
+  DialogDelegate::set_button_label(
+      ui::DIALOG_BUTTON_CANCEL,
+      l10n_util::GetStringUTF16(IDS_RELAUNCH_REQUIRED_CANCEL_BUTTON));
   SetLayoutManager(std::make_unique<views::FillLayout>());
   chrome::RecordDialogCreation(chrome::DialogIdentifier::RELAUNCH_REQUIRED);
   set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
diff --git a/chrome/browser/ui/views/relaunch_notification/relaunch_required_dialog_view.h b/chrome/browser/ui/views/relaunch_notification/relaunch_required_dialog_view.h
index c97f66e..84ce030 100644
--- a/chrome/browser/ui/views/relaunch_notification/relaunch_required_dialog_view.h
+++ b/chrome/browser/ui/views/relaunch_notification/relaunch_required_dialog_view.h
@@ -41,7 +41,6 @@
   // views::DialogDelegateView:
   bool Cancel() override;
   bool Accept() override;
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   ui::ModalType GetModalType() const override;
   base::string16 GetWindowTitle() const override;
   bool ShouldShowCloseButton() const override;
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
index 30da3e1..9f5944a 100644
--- a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
+++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
@@ -10,7 +10,9 @@
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/views/controls/label.h"
@@ -37,6 +39,10 @@
     : browser_(nullptr), controller_(controller) {
   DCHECK(controller_);
 
+  DialogDelegate::set_button_label(
+      ui::DIALOG_BUTTON_OK,
+      l10n_util::GetStringUTF16(IDS_SETTINGS_RESET_PROMPT_ACCEPT_BUTTON_LABEL));
+
   set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
       views::TEXT, views::TEXT));
   SetLayoutManager(std::make_unique<views::FillLayout>());
@@ -91,16 +97,6 @@
 
 // DialogDelegate overrides.
 
-base::string16 SettingsResetPromptDialog::GetDialogButtonLabel(
-    ui::DialogButton button) const {
-  DCHECK(button == ui::DIALOG_BUTTON_OK || button == ui::DIALOG_BUTTON_CANCEL);
-  DCHECK(controller_);
-
-  if (button == ui::DIALOG_BUTTON_OK)
-    return controller_->GetButtonLabel();
-  return DialogDelegate::GetDialogButtonLabel(button);
-}
-
 bool SettingsResetPromptDialog::Accept() {
   if (controller_) {
     controller_->Accept();
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.h b/chrome/browser/ui/views/settings_reset_prompt_dialog.h
index 6ff6041..d9ae7cc 100644
--- a/chrome/browser/ui/views/settings_reset_prompt_dialog.h
+++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.h
@@ -41,7 +41,6 @@
   bool ShouldShowCloseButton() const override;
 
   // views::DialogDelegate overrides.
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   bool Accept() override;
   bool Cancel() override;
   // We override |Close()| because we want to distinguish in our metrics between
diff --git a/chrome/browser/ui/views/simple_message_box_views.cc b/chrome/browser/ui/views/simple_message_box_views.cc
index 0a36db5..90fa4da6 100644
--- a/chrome/browser/ui/views/simple_message_box_views.cc
+++ b/chrome/browser/ui/views/simple_message_box_views.cc
@@ -177,13 +177,6 @@
   return ui::DIALOG_BUTTON_OK;
 }
 
-base::string16 SimpleMessageBoxViews::GetDialogButtonLabel(
-    ui::DialogButton button) const {
-  if (button == ui::DIALOG_BUTTON_CANCEL)
-    return no_text_;
-  return yes_text_;
-}
-
 bool SimpleMessageBoxViews::Close() {
   return can_close_ ? DialogDelegate::Close() : false;
 }
@@ -250,22 +243,27 @@
     bool can_close)
     : window_title_(title),
       type_(type),
-      yes_text_(yes_text),
-      no_text_(no_text),
       result_(chrome::MESSAGE_BOX_RESULT_NO),
       message_box_view_(new views::MessageBoxView(
           views::MessageBoxView::InitParams(message))),
       is_system_modal_(is_system_modal),
       can_close_(can_close) {
-  if (yes_text_.empty()) {
-    yes_text_ =
+  base::string16 ok_text = yes_text;
+  if (ok_text.empty()) {
+    ok_text =
         type_ == chrome::MESSAGE_BOX_TYPE_QUESTION
             ? l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL)
             : l10n_util::GetStringUTF16(IDS_OK);
   }
+  DialogDelegate::set_button_label(ui::DIALOG_BUTTON_OK, ok_text);
 
-  if (no_text_.empty() && type_ == chrome::MESSAGE_BOX_TYPE_QUESTION)
-    no_text_ = l10n_util::GetStringUTF16(IDS_CANCEL);
+  // Only MESSAGE_BOX_TYPE_QUESTION has a Cancel button.
+  if (type_ == chrome::MESSAGE_BOX_TYPE_QUESTION) {
+    base::string16 cancel_text = no_text;
+    if (cancel_text.empty())
+      cancel_text = l10n_util::GetStringUTF16(IDS_CANCEL);
+    DialogDelegate::set_button_label(ui::DIALOG_BUTTON_CANCEL, cancel_text);
+  }
 
   if (!checkbox_text.empty())
     message_box_view_->SetCheckBoxLabel(checkbox_text);
diff --git a/chrome/browser/ui/views/simple_message_box_views.h b/chrome/browser/ui/views/simple_message_box_views.h
index b9830ce..5e35dc54 100644
--- a/chrome/browser/ui/views/simple_message_box_views.h
+++ b/chrome/browser/ui/views/simple_message_box_views.h
@@ -30,7 +30,6 @@
 
   // views::DialogDelegate:
   int GetDialogButtons() const override;
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   bool Cancel() override;
   bool Accept() override;
   bool Close() override;
@@ -61,8 +60,6 @@
 
   const base::string16 window_title_;
   const chrome::MessageBoxType type_;
-  base::string16 yes_text_;
-  base::string16 no_text_;
   chrome::MessageBoxResult result_;
   views::MessageBoxView* message_box_view_;
   MessageBoxResultCallback result_callback_;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc
index 7cb442b2..247feb2 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc
@@ -29,7 +29,11 @@
                   gfx::Insets(0, GetLayoutConstant(TOOLBAR_ELEMENT_PADDING)));
 }
 
-ToolbarIconContainerView::~ToolbarIconContainerView() = default;
+ToolbarIconContainerView::~ToolbarIconContainerView() {
+  // As childred might be Observers of |this|, we need to destroy them before
+  // destroying |observers_|.
+  RemoveAllChildViews(true);
+}
 
 void ToolbarIconContainerView::UpdateAllIcons() {}
 
diff --git a/chrome/browser/ui/webui/domain_reliability_internals_ui.cc b/chrome/browser/ui/webui/domain_reliability_internals_ui.cc
index 148a714..ad01bdc 100644
--- a/chrome/browser/ui/webui/domain_reliability_internals_ui.cc
+++ b/chrome/browser/ui/webui/domain_reliability_internals_ui.cc
@@ -13,6 +13,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 
 DomainReliabilityInternalsUI::DomainReliabilityInternalsUI(
     content::WebUI* web_ui)
diff --git a/chrome/browser/ui/webui/download_internals/download_internals_ui_message_handler.cc b/chrome/browser/ui/webui/download_internals/download_internals_ui_message_handler.cc
index eb6d5d6..042cc501f 100644
--- a/chrome/browser/ui/webui/download_internals/download_internals_ui_message_handler.cc
+++ b/chrome/browser/ui/webui/download_internals/download_internals_ui_message_handler.cc
@@ -9,6 +9,7 @@
 #include "base/values.h"
 #include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "components/download/public/background_service/download_params.h"
 #include "components/download/public/background_service/download_service.h"
 #include "content/public/browser/web_ui.h"
diff --git a/chrome/browser/ui/webui/fileicon_source_unittest.cc b/chrome/browser/ui/webui/fileicon_source_unittest.cc
index 549f1716..b4da377 100644
--- a/chrome/browser/ui/webui/fileicon_source_unittest.cc
+++ b/chrome/browser/ui/webui/fileicon_source_unittest.cc
@@ -13,6 +13,7 @@
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/layout.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc b/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc
index 4ccdeee8..177f509 100644
--- a/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc
+++ b/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/webui/ntp/cookie_controls_handler.h"
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
diff --git a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
index 18e2ac8..27a6e11 100644
--- a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
+++ b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/offline_pages/prefetch/prefetched_pages_notifier.h"
 #include "chrome/browser/offline_pages/request_coordinator_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_content_client.h"
 #include "components/offline_pages/core/client_namespace_constants.h"
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 9686cf2..dcf8913b 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -315,9 +315,6 @@
   if (print_settings.FindIntKey(kSettingCopies).value_or(1) > 1)
     ReportPrintSettingHistogram(COPIES);
 
-  if (preview_settings.FindIntKey(kSettingScaleFactor).value_or(100) != 100)
-    ReportPrintSettingHistogram(SCALING);
-
   if (preview_settings.FindIntKey(kSettingPagesPerSheet).value_or(1) != 1)
     ReportPrintSettingHistogram(PAGES_PER_SHEET);
 
@@ -354,8 +351,14 @@
   if (preview_settings.FindBoolKey(kSettingRasterizePdf).value_or(false))
     ReportPrintSettingHistogram(PRINT_AS_IMAGE);
 
-  if (is_pdf &&
-      preview_settings.FindBoolKey(kSettingFitToPageEnabled).value_or(false)) {
+  ScalingType scaling_type =
+      static_cast<ScalingType>(preview_settings.FindIntKey(kSettingScalingType)
+                                   .value_or(ScalingType::DEFAULT));
+  if (scaling_type == ScalingType::CUSTOM) {
+    ReportPrintSettingHistogram(SCALING);
+  }
+
+  if (is_pdf && scaling_type == ScalingType::FIT_TO_PAGE) {
     ReportPrintSettingHistogram(FIT_TO_PAGE);
   }
 
diff --git a/chrome/browser/ui/webui/signin/signin_email_confirmation_ui.cc b/chrome/browser/ui/webui/signin/signin_email_confirmation_ui.cc
index fbdc4b4..b8bf3ff 100644
--- a/chrome/browser/ui/webui/signin/signin_email_confirmation_ui.cc
+++ b/chrome/browser/ui/webui/signin/signin_email_confirmation_ui.cc
@@ -27,7 +27,8 @@
   source->SetDefaultResource(IDR_SIGNIN_EMAIL_CONFIRMATION_HTML);
   source->AddResourcePath("signin_email_confirmation.js",
                           IDR_SIGNIN_EMAIL_CONFIRMATION_JS);
-  source->AddResourcePath("signin_shared_css.html", IDR_SIGNIN_SHARED_CSS_HTML);
+  source->AddResourcePath("signin_shared_old_css.html",
+                          IDR_SIGNIN_SHARED_OLD_CSS_HTML);
 
   static constexpr LocalizedString kStrings[] = {
       {"signinEmailConfirmationTitle", IDS_SIGNIN_EMAIL_CONFIRMATION_TITLE},
diff --git a/chrome/browser/ui/webui/signin/signin_error_ui.cc b/chrome/browser/ui/webui/signin/signin_error_ui.cc
index e7739d6..cef4339 100644
--- a/chrome/browser/ui/webui/signin/signin_error_ui.cc
+++ b/chrome/browser/ui/webui/signin/signin_error_ui.cc
@@ -69,7 +69,8 @@
   source->UseStringsJs();
   source->SetDefaultResource(IDR_SIGNIN_ERROR_HTML);
   source->AddResourcePath("signin_error.js", IDR_SIGNIN_ERROR_JS);
-  source->AddResourcePath("signin_shared_css.html", IDR_SIGNIN_SHARED_CSS_HTML);
+  source->AddResourcePath("signin_shared_old_css.html",
+                          IDR_SIGNIN_SHARED_OLD_CSS_HTML);
   source->AddBoolean("isSystemProfile", is_system_profile);
 
   // Retrieve the last signin error message and email used.
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
index 233b67c..761800b5 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
@@ -24,6 +24,7 @@
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/webui/web_ui_util.h"
+#include "ui/resources/grit/webui_resources.h"
 
 SyncConfirmationUI::SyncConfirmationUI(content::WebUI* web_ui)
     : SigninWebDialogUI(web_ui) {
@@ -34,16 +35,18 @@
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(chrome::kChromeUISyncConfirmationHost);
   source->UseStringsJs();
-  source->AddResourcePath("signin_shared_css.html", IDR_SIGNIN_SHARED_CSS_HTML);
+  source->EnableReplaceI18nInJS();
 
   if (is_sync_allowed) {
+    source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER);
+    source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER);
+    source->OverrideContentSecurityPolicyScriptSrc(
+        "script-src chrome://resources chrome://test 'self';");
+
     source->SetDefaultResource(IDR_SYNC_CONFIRMATION_HTML);
-    source->AddResourcePath("sync_confirmation_browser_proxy.html",
-                            IDR_SYNC_CONFIRMATION_BROWSER_PROXY_HTML);
+    source->AddResourcePath("signin_shared_css.js", IDR_SIGNIN_SHARED_CSS_JS);
     source->AddResourcePath("sync_confirmation_browser_proxy.js",
                             IDR_SYNC_CONFIRMATION_BROWSER_PROXY_JS);
-    source->AddResourcePath("sync_confirmation_app.html",
-                            IDR_SYNC_CONFIRMATION_APP_HTML);
     source->AddResourcePath("sync_confirmation_app.js",
                             IDR_SYNC_CONFIRMATION_APP_JS);
     source->AddResourcePath("sync_confirmation.js", IDR_SYNC_CONFIRMATION_JS);
@@ -81,6 +84,8 @@
     source->AddString("accountPictureUrl", custom_picture_url);
   } else {
     source->SetDefaultResource(IDR_SYNC_DISABLED_CONFIRMATION_HTML);
+    source->AddResourcePath("signin_shared_old_css.html",
+                            IDR_SIGNIN_SHARED_OLD_CSS_HTML);
     source->AddResourcePath("sync_disabled_confirmation.js",
                             IDR_SYNC_DISABLED_CONFIRMATION_JS);
 
diff --git a/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc b/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc
index 7d4027b..e2f7445 100644
--- a/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc
@@ -15,6 +15,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
 #include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h"
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
index e1d6785..ad525a9b 100644
--- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
+++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
@@ -184,6 +184,11 @@
     FireWebUIListener("tab-updated", GetTabData(contents, index));
   }
 
+  void TabBlockedStateChanged(content::WebContents* contents,
+                              int index) override {
+    FireWebUIListener("tab-updated", GetTabData(contents, index));
+  }
+
  protected:
   // content::WebUIMessageHandler:
   void RegisterMessages() override {
@@ -235,6 +240,7 @@
                         static_cast<int>(tab_renderer_data.network_state));
     tab_data.SetBoolean("shouldHideThrobber",
                         tab_renderer_data.should_hide_throbber);
+    tab_data.SetBoolean("blocked", tab_renderer_data.blocked);
     tab_data.SetBoolean("crashed", tab_renderer_data.IsCrashed());
     // TODO(johntlee): Add the rest of TabRendererData
 
@@ -292,6 +298,10 @@
     colors.SetString("--tabstrip-indicator-capturing-color",
                      color_utils::SkColorToRgbaString(tp.GetColor(
                          ThemeProperties::COLOR_TAB_ALERT_CAPTURING)));
+    colors.SetString("--tabstrip-tab-blocked-color",
+                     color_utils::SkColorToRgbaString(
+                         ui::NativeTheme::GetInstanceForWeb()->GetSystemColor(
+                             ui::NativeTheme::kColorId_ProminentButtonColor)));
 
     ResolveJavascriptCallback(callback_id, colors);
   }
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc
index cc006a1..80b40ae 100644
--- a/chrome/browser/ui/webui/theme_source.cc
+++ b/chrome/browser/ui/webui/theme_source.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/task/post_task.h"
 #include "build/branding_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
@@ -24,6 +25,8 @@
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/url_data_source.h"
+#include "content/public/common/url_constants.h"
 #include "net/url_request/url_request.h"
 #include "ui/base/layout.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -239,3 +242,15 @@
         base::BindOnce(callback, data));
   }
 }
+
+std::string ThemeSource::GetAccessControlAllowOriginForOrigin(
+    const std::string& origin) {
+  std::string allowed_origin_prefix = content::kChromeUIScheme;
+  allowed_origin_prefix += "://";
+  if (base::StartsWith(origin, allowed_origin_prefix,
+                       base::CompareCase::SENSITIVE)) {
+    return origin;
+  }
+
+  return content::URLDataSource::GetAccessControlAllowOriginForOrigin(origin);
+}
diff --git a/chrome/browser/ui/webui/theme_source.h b/chrome/browser/ui/webui/theme_source.h
index 321ea0b8..4ebcc70 100644
--- a/chrome/browser/ui/webui/theme_source.h
+++ b/chrome/browser/ui/webui/theme_source.h
@@ -33,6 +33,8 @@
   bool ShouldServiceRequest(const GURL& url,
                             content::ResourceContext* resource_context,
                             int render_process_id) override;
+  std::string GetAccessControlAllowOriginForOrigin(
+      const std::string& origin) override;
 
  private:
   // Fetches and sends the theme bitmap.
diff --git a/chrome/browser/ui/webui/theme_source_unittest.cc b/chrome/browser/ui/webui/theme_source_unittest.cc
index 55ee176..a17b7b4 100644
--- a/chrome/browser/ui/webui/theme_source_unittest.cc
+++ b/chrome/browser/ui/webui/theme_source_unittest.cc
@@ -94,3 +94,15 @@
   EXPECT_EQ(result_data_size_, empty_size);
 #endif
 }
+
+TEST_F(WebUISourcesTest, ThemeAllowedOrigin) {
+  EXPECT_EQ(
+      theme_source()->GetAccessControlAllowOriginForOrigin("chrome://settings"),
+      "chrome://settings");
+  EXPECT_EQ(theme_source()->GetAccessControlAllowOriginForOrigin(
+                "chrome-extensions://some-id"),
+            "");
+  EXPECT_EQ(
+      theme_source()->GetAccessControlAllowOriginForOrigin("http://google.com"),
+      "");
+}
diff --git a/chrome/browser/wake_lock/wake_lock_browsertest.cc b/chrome/browser/wake_lock/wake_lock_browsertest.cc
index 051c1f33..17f230f 100644
--- a/chrome/browser/wake_lock/wake_lock_browsertest.cc
+++ b/chrome/browser/wake_lock/wake_lock_browsertest.cc
@@ -119,7 +119,8 @@
   PermissionRequestObserver observer(
       browser()->tab_strip_model()->GetActiveWebContents());
   const std::string kWorkerScript =
-      "WakeLock.request('screen').catch(err => self.postMessage(err.name))";
+      "navigator.wakeLock.request('screen').catch(err => "
+      "    self.postMessage(err.name))";
   NavigateToAndRespondWithScript(
       "/workers/create_dedicated_worker.html?worker_url=/js-response",
       kWorkerScript);
@@ -136,7 +137,8 @@
   PermissionRequestObserver observer(
       browser()->tab_strip_model()->GetActiveWebContents());
   const std::string kWorkerScript =
-      "WakeLock.request('system').catch(err => self.postMessage(err.name))";
+      "navigator.wakeLock.request('system').catch(err => "
+      "    self.postMessage(err.name))";
   NavigateToAndRespondWithScript(
       "/workers/create_dedicated_worker.html?worker_url=/js-response",
       kWorkerScript);
@@ -156,7 +158,8 @@
       browser()->tab_strip_model()->GetActiveWebContents());
   EXPECT_EQ("granted", content::EvalJs(
                            browser()->tab_strip_model()->GetActiveWebContents(),
-                           "WakeLock.requestPermission('screen')"));
+                           "navigator.wakeLock.request('screen').then(lock => {"
+                           "    lock.release(); return 'granted'; });"));
   EXPECT_EQ(observer.request_shown(), false);
 }
 
@@ -171,7 +174,8 @@
   EXPECT_EQ(
       "granted",
       content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
-                      "WakeLock.requestPermission('screen')",
+                      "navigator.wakeLock.request('screen').then(lock => {"
+                      "    lock.release(); return 'granted'; });",
                       content::EvalJsOptions::EXECUTE_SCRIPT_NO_USER_GESTURE));
   EXPECT_EQ(observer.request_shown(), false);
 }
@@ -183,9 +187,11 @@
 
   PermissionRequestObserver observer(
       browser()->tab_strip_model()->GetActiveWebContents());
-  EXPECT_EQ("denied", content::EvalJs(
-                          browser()->tab_strip_model()->GetActiveWebContents(),
-                          "WakeLock.requestPermission('system')"));
+  EXPECT_EQ(
+      "NotAllowedError",
+      content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
+                      "navigator.wakeLock.request('system').catch(err => {"
+                      "    return err.name; });"));
   EXPECT_EQ(observer.request_shown(), false);
 }
 
@@ -198,9 +204,10 @@
   PermissionRequestObserver observer(
       browser()->tab_strip_model()->GetActiveWebContents());
   EXPECT_EQ(
-      "denied",
+      "NotAllowedError",
       content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
-                      "WakeLock.requestPermission('system')",
+                      "navigator.wakeLock.request('system').catch(err => {"
+                      "    return err.name; });",
                       content::EvalJsOptions::EXECUTE_SCRIPT_NO_USER_GESTURE));
   EXPECT_EQ(observer.request_shown(), false);
 }
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc
index 19833e4..f1cafc02 100644
--- a/chrome/browser/web_applications/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/chrome/installer/setup/BUILD.gn b/chrome/installer/setup/BUILD.gn
index abfb04b..5a7290a 100644
--- a/chrome/installer/setup/BUILD.gn
+++ b/chrome/installer/setup/BUILD.gn
@@ -10,8 +10,6 @@
 
 buildflag_header("buildflags") {
   header = "buildflags.h"
-
-  # Use ZUCCHINI since ZUCCHINI_ENABLED is too long a name for setup.rc.
   flags = [ "ZUCCHINI=$use_zucchini" ]
 }
 
@@ -26,13 +24,6 @@
       "uninstall.h",
     ]
 
-    if (is_chrome_branded) {
-      # The resource compiler can only handle macro functions up to 31 chars
-      # which the buildflag system produces for this. Make a define so we can
-      # toggle off of the enable-basic-printing flag in the .rc file.
-      defines = [ "GOOGLE_CHROME_BRANDING_FOR_RC" ]
-    }
-
     configs -= [ "//build/config/win:console" ]
     configs += [ "//build/config/win:windowed" ]
 
diff --git a/chrome/installer/setup/setup.rc b/chrome/installer/setup/setup.rc
index 9575e03..ad8eb34 100644
--- a/chrome/installer/setup/setup.rc
+++ b/chrome/installer/setup/setup.rc
@@ -14,6 +14,7 @@
 /////////////////////////////////////////////////////////////////////////////
 #undef APSTUDIO_READONLY_SYMBOLS
 
+#include "build/branding_buildflags.h"
 #include "chrome/installer/setup/buildflags.h"
 
 /////////////////////////////////////////////////////////////////////////////
@@ -58,10 +59,7 @@
 #endif    // English (U.S.) resources
 /////////////////////////////////////////////////////////////////////////////
 
-// This really should be using the buildflag but the resource compiler fails on
-// macro functions longer than 31 chars which this command produces. The BUILD
-// sets this regular define for this target only for this line to consume.
-#ifdef GOOGLE_CHROME_BRANDING_FOR_RC
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -118,7 +116,7 @@
 IDR_OEMPG_ZH_CN.HTML    HTML   "eula\\oem_zh-CN.html"
 IDR_OEMPG_ZH_TW.HTML    HTML   "eula\\oem_zh-TW.html"
 
-#endif  // GOOGLE_CHROME_BRANDING_FOR_RC
+#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
 #ifndef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index ef5ce97..7097bf2 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -5002,6 +5002,7 @@
       "../browser/ui/views/frame/web_contents_close_handler_unittest.cc",
       "../browser/ui/views/fullscreen_control/fullscreen_control_popup_unittest.cc",
       "../browser/ui/views/global_error_bubble_view_unittest.cc",
+      "../browser/ui/views/global_media_controls/media_notification_container_impl_view_unittest.cc",
       "../browser/ui/views/hover_button_unittest.cc",
       "../browser/ui/views/infobars/infobar_view_unittest.cc",
       "../browser/ui/views/intent_picker_bubble_view_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/BottomSheetTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/BottomSheetTestRule.java
index 6461feb..fe69b10 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/BottomSheetTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/BottomSheetTestRule.java
@@ -40,6 +40,12 @@
         /** A {@link CallbackHelper} that can wait for the onSheetContentChanged event. */
         public final CallbackHelper mContentChangedCallbackHelper = new CallbackHelper();
 
+        /** A {@link CallbackHelper} that can wait for the sheet to be in its full state. */
+        public final CallbackHelper mFullCallbackHelper = new CallbackHelper();
+
+        /** A {@link CallbackHelper} that can wait for the sheet to be hidden. */
+        public final CallbackHelper mHiddenCallbackHelper = new CallbackHelper();
+
         /** The last value that the onOffsetChanged event sent. */
         private float mLastOffsetChangedValue;
 
@@ -64,6 +70,15 @@
             mContentChangedCallbackHelper.notifyCalled();
         }
 
+        @Override
+        public void onSheetStateChanged(int newState) {
+            if (newState == BottomSheet.SheetState.HIDDEN) {
+                mHiddenCallbackHelper.notifyCalled();
+            } else if (newState == BottomSheet.SheetState.FULL) {
+                mFullCallbackHelper.notifyCalled();
+            }
+        }
+
         /** @return The last value passed in to {@link #onSheetOffsetChanged(float)}. */
         public float getLastOffsetChangedValue() {
             return mLastOffsetChangedValue;
diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc
index ad45e43b..5e3c3d32 100644
--- a/chrome/test/base/chrome_test_launcher.cc
+++ b/chrome/test/base/chrome_test_launcher.cc
@@ -20,6 +20,7 @@
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/test/test_file_util.h"
+#include "base/test/test_switches.h"
 #include "chrome/app/chrome_main_delegate.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
@@ -210,7 +211,7 @@
   // mimics the behavior in standalone Chrome, where this is done in
   // chrome/app/chrome_main.cc, which does not get called by tests.
   std::unique_ptr<MainThreadStackSamplingProfiler> sampling_profiler;
-  if (command_line.HasSwitch(content::kLaunchAsBrowser))
+  if (command_line.HasSwitch(switches::kLaunchAsBrowser))
     sampling_profiler = std::make_unique<MainThreadStackSamplingProfiler>();
 
 #if defined(OS_LINUX) || defined(OS_ANDROID)
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 28dbb2f..dfec885 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -20,6 +20,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/test_file_util.h"
+#include "base/test/test_switches.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "chrome/browser/after_startup_task_utils.h"
@@ -475,9 +476,9 @@
   base::CommandLine::SwitchMap switches =
       base::CommandLine::ForCurrentProcess()->GetSwitches();
   switches.erase(switches::kUserDataDir);
-  switches.erase(content::kSingleProcessTestsFlag);
+  switches.erase(switches::kSingleProcessTests);
   switches.erase(switches::kSingleProcess);
-  new_command_line.AppendSwitch(content::kLaunchAsBrowser);
+  new_command_line.AppendSwitch(switches::kLaunchAsBrowser);
 
   base::FilePath user_data_dir;
   base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index c5a2af4..2e354ad 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -23,6 +23,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "extensions/buildflags/buildflags.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "net/cookies/cookie_store.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
diff --git a/chrome/test/base/web_ui_browser_test.cc b/chrome/test/base/web_ui_browser_test.cc
index eaab1a4..0cceb38 100644
--- a/chrome/test/base/web_ui_browser_test.cc
+++ b/chrome/test/base/web_ui_browser_test.cc
@@ -16,6 +16,7 @@
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/test_switches.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_content_browser_client.h"
@@ -256,7 +257,7 @@
   libraries_preloaded_ = true;
 
   bool should_wait_flag = base::CommandLine::ForCurrentProcess()->HasSwitch(
-      ::content::kWaitForDebuggerWebUI);
+      ::switches::kWaitForDebuggerWebUI);
 
   if (should_wait_flag)
     RunJavascriptUsingHandler("setWaitUser", {}, false, false, preload_host);
diff --git a/chrome/test/data/local_ntp/realbox_browsertest.js b/chrome/test/data/local_ntp/realbox_browsertest.js
index 6d7586c0c..26fbcc1f 100644
--- a/chrome/test/data/local_ntp/realbox_browsertest.js
+++ b/chrome/test/data/local_ntp/realbox_browsertest.js
@@ -104,17 +104,21 @@
   chrome.embeddedSearch = {
     newTabPage: {},
     searchBox: {
+      deleteAutocompleteMatch(line) {
+        test.realbox.deletedLines.push(line);
+      },
       queryAutocomplete(query) {
         test.realbox.queries.push(query);
       },
-      deleteAutocompleteMatch(line) {
-        test.realbox.deletedLines.push(line);
-      }
+      stopAutocomplete(clearResult) {
+        test.realbox.stops.push(clearResult);
+      },
     },
   };
 
-  test.realbox.queries = [];
   test.realbox.deletedLines = [];
+  test.realbox.queries = [];
+  test.realbox.stops = [];
 
   initLocalNTP(/*isGooglePage=*/ true);
 
@@ -605,6 +609,15 @@
   assertEquals(1, test.realbox.deletedLines.length);
   assertEquals(0, test.realbox.deletedLines[0]);
 
+  assertEquals(0, test.realbox.stops.length);
+  icon.dispatchEvent(new Event('focusout', {
+    bubbles: true,
+    cancelable: true,
+    target: icon,
+    relatedTarget: document.body,
+  }));
+  assertEquals(0, test.realbox.stops.length);
+
   chrome.embeddedSearch.searchBox.ondeleteautocompletematch(
       {success: true, matches: []});
 
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index b04afc4..3eac81d 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -4103,6 +4103,9 @@
   "DeviceLoginScreenDefaultScreenMagnifierType" : {
   },
 
+  "DeviceLoginScreenScreenMagnifierType" : {
+  },
+
   "DeviceLoginScreenDefaultVirtualKeyboardEnabled" : {
   },
 
diff --git a/chrome/test/data/webui/print_preview/model_test.js b/chrome/test/data/webui/print_preview/model_test.js
index a0fec8b..e541f55 100644
--- a/chrome/test/data/webui/print_preview/model_test.js
+++ b/chrome/test/data/webui/print_preview/model_test.js
@@ -286,12 +286,12 @@
         printerType: print_preview.PrinterType.LOCAL_PRINTER,
         rasterizePDF: false,
         scaleFactor: 100,
+        scalingType: print_preview.ScalingType.DEFAULT,
         pagesPerSheet: 1,
         dpiHorizontal: 200,
         dpiVertical: 200,
         dpiDefault: true,
         deviceName: 'FooDevice',
-        fitToPageEnabled: false,
         pageWidth: 612,
         pageHeight: 792,
         showSystemDialog: false,
@@ -324,12 +324,12 @@
         printerType: print_preview.PrinterType.LOCAL_PRINTER,
         rasterizePDF: true,
         scaleFactor: 90,
+        scalingType: print_preview.ScalingType.CUSTOM,
         pagesPerSheet: 1,
         dpiHorizontal: 100,
         dpiVertical: 100,
         dpiDefault: false,
         deviceName: 'FooDevice',
-        fitToPageEnabled: false,
         pageWidth: 612,
         pageHeight: 792,
         showSystemDialog: false,
diff --git a/chrome/test/data/webui/print_preview/preview_generation_test.js b/chrome/test/data/webui/print_preview/preview_generation_test.js
index 2f5df0d..2562bf2f 100644
--- a/chrome/test/data/webui/print_preview/preview_generation_test.js
+++ b/chrome/test/data/webui/print_preview/preview_generation_test.js
@@ -7,7 +7,6 @@
   const TestNames = {
     Color: 'color',
     CssBackground: 'css background',
-    FitToPage: 'fit to page',
     HeaderFooter: 'header/footer',
     Layout: 'layout',
     Margins: 'margins',
@@ -17,6 +16,7 @@
     Rasterize: 'rasterize',
     PagesPerSheet: 'pages per sheet',
     Scaling: 'scaling',
+    ScalingPdf: 'scalingPdf',
     SelectionOnly: 'selection only',
     Destination: 'destination',
     ChangeMarginsByPagesPerSheet: 'change margins by pages per sheet',
@@ -128,17 +128,6 @@
           'cssBackground', false, true, 'shouldPrintBackgrounds', false, true);
     });
 
-    /** Validate changing the scalingTypePdf setting updates the preview. */
-    test(assert(TestNames.FitToPage), function() {
-      // Set PDF document so setting is available.
-      initialSettings.previewModifiable = false;
-      initialSettings.previewIsPdf = true;
-      return testSimpleSetting(
-          'scalingTypePdf', print_preview.ScalingType.DEFAULT,
-          print_preview.ScalingType.FIT_TO_PAGE, 'fitToPageEnabled', false,
-          true);
-    });
-
     /** Validate changing the header/footer setting updates the preview. */
     test(assert(TestNames.HeaderFooter), function() {
       return testSimpleSetting(
@@ -414,6 +403,112 @@
           });
     });
 
+    /** Validate changing the scalingTypePdf setting updates the preview. */
+    test(assert(TestNames.ScalingPdf), function() {
+      // Set PDF document so setting is available.
+      initialSettings.previewModifiable = false;
+      initialSettings.previewIsPdf = true;
+      return initialize()
+          .then(function(args) {
+            const ticket = JSON.parse(args.printTicket);
+            assertEquals(0, ticket.requestID);
+            assertEquals(100, ticket.scaleFactor);
+            nativeLayer.resetResolver('getPreview');
+            assertEquals('100', page.getSettingValue('scaling'));
+            assertEquals(
+                print_preview.ScalingType.DEFAULT,
+                page.getSettingValue('scalingTypePdf'));
+            // DEFAULT -> FIT_TO_PAGE
+            page.setSetting(
+                'scalingTypePdf', print_preview.ScalingType.FIT_TO_PAGE);
+            return nativeLayer.whenCalled('getPreview');
+          })
+          .then(function(args) {
+            const ticket = JSON.parse(args.printTicket);
+            assertEquals(100, ticket.scaleFactor);
+            assertEquals(1, ticket.requestID);
+            nativeLayer.resetResolver('getPreview');
+            assertEquals('100', page.getSettingValue('scaling'));
+            assertEquals(
+                print_preview.ScalingType.FIT_TO_PAGE,
+                page.getSettingValue('scalingTypePdf'));
+            // FIT_TO_PAGE -> CUSTOM
+            page.setSetting('scalingTypePdf', print_preview.ScalingType.CUSTOM);
+            return nativeLayer.whenCalled('getPreview');
+          })
+          .then(function(args) {
+            const ticket = JSON.parse(args.printTicket);
+            assertEquals(100, ticket.scaleFactor);
+            assertEquals(2, ticket.requestID);
+            nativeLayer.resetResolver('getPreview');
+            assertEquals('100', page.getSettingValue('scaling'));
+            assertEquals(
+                print_preview.ScalingType.CUSTOM,
+                page.getSettingValue('scalingTypePdf'));
+            // CUSTOM -> FIT_TO_PAGE
+            page.setSetting(
+                'scalingTypePdf', print_preview.ScalingType.FIT_TO_PAGE);
+            return nativeLayer.whenCalled('getPreview');
+          })
+          .then(function(args) {
+            const ticket = JSON.parse(args.printTicket);
+            assertEquals(100, ticket.scaleFactor);
+            assertEquals(3, ticket.requestID);
+            nativeLayer.resetResolver('getPreview');
+            assertEquals('100', page.getSettingValue('scaling'));
+            assertEquals(
+                print_preview.ScalingType.FIT_TO_PAGE,
+                page.getSettingValue('scalingTypePdf'));
+            // FIT_TO_PAGE -> DEFAULT
+            page.setSetting(
+                'scalingTypePdf', print_preview.ScalingType.DEFAULT);
+            return nativeLayer.whenCalled('getPreview');
+          })
+          .then(function(args) {
+            const ticket = JSON.parse(args.printTicket);
+            assertEquals(100, ticket.scaleFactor);
+            assertEquals(4, ticket.requestID);
+            nativeLayer.resetResolver('getPreview');
+            assertEquals('100', page.getSettingValue('scaling'));
+            assertEquals(
+                print_preview.ScalingType.DEFAULT,
+                page.getSettingValue('scalingTypePdf'));
+            // DEFAULT -> CUSTOM
+            page.setSetting('scalingTypePdf', print_preview.ScalingType.CUSTOM);
+            // Need to set custom value != 100 for preview to regenerate.
+            page.setSetting('scaling', '120');
+            return nativeLayer.whenCalled('getPreview');
+          })
+          .then(function(args) {
+            const ticket = JSON.parse(args.printTicket);
+            assertEquals(120, ticket.scaleFactor);
+            // DEFAULT -> CUSTOM will result in a scaling change only if the
+            // scale factor changes. Therefore, the requestId should only be one
+            // more than the last set of scaling changes.
+            assertEquals(5, ticket.requestID);
+            nativeLayer.resetResolver('getPreview');
+            assertEquals('120', page.getSettingValue('scaling'));
+            assertEquals(
+                print_preview.ScalingType.CUSTOM,
+                page.getSettingValue('scalingTypePdf'));
+            // CUSTOM -> DEFAULT
+            page.setSetting(
+                'scalingTypePdf', print_preview.ScalingType.DEFAULT);
+            // This should regenerate the preview, since the custom value is not
+            // 100.
+            return nativeLayer.whenCalled('getPreview');
+          })
+          .then(function(args) {
+            const ticket = JSON.parse(args.printTicket);
+            assertEquals(100, ticket.scaleFactor);
+            assertEquals(6, ticket.requestID);
+            assertEquals('120', page.getSettingValue('scaling'));
+            assertEquals(
+                print_preview.ScalingType.DEFAULT,
+                page.getSettingValue('scalingTypePdf'));
+          });
+    });
+
     /**
      * Validate changing the rasterize setting updates the preview. Only runs
      * on Linux and CrOS as setting is not available on other platforms.
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
index a17538f..4f626c1 100644
--- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
+++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -421,10 +421,6 @@
   this.runMochaTest(preview_generation_test.TestNames.CssBackground);
 });
 
-TEST_F('PrintPreviewPreviewGenerationTest', 'FitToPage', function() {
-  this.runMochaTest(preview_generation_test.TestNames.FitToPage);
-});
-
 TEST_F('PrintPreviewPreviewGenerationTest', 'HeaderFooter', function() {
   this.runMochaTest(preview_generation_test.TestNames.HeaderFooter);
 });
@@ -461,6 +457,10 @@
   this.runMochaTest(preview_generation_test.TestNames.Scaling);
 });
 
+TEST_F('PrintPreviewPreviewGenerationTest', 'ScalingPdf', function() {
+  this.runMochaTest(preview_generation_test.TestNames.ScalingPdf);
+});
+
 GEN('#if !defined(OS_WIN) && !defined(OS_MACOSX)');
 TEST_F('PrintPreviewPreviewGenerationTest', 'Rasterize', function() {
   this.runMochaTest(preview_generation_test.TestNames.Rasterize);
diff --git a/chrome/test/data/webui/signin/signin_browsertest.js b/chrome/test/data/webui/signin/signin_browsertest.js
index 90ac93e..6c5f244 100644
--- a/chrome/test/data/webui/signin/signin_browsertest.js
+++ b/chrome/test/data/webui/signin/signin_browsertest.js
@@ -9,6 +9,7 @@
 GEN('#include "base/command_line.h"');
 GEN('#include "build/branding_buildflags.h"');
 GEN('#include "chrome/test/data/webui/signin_browsertest.h"');
+GEN('#include "services/network/public/cpp/features.h"');
 
 /**
  * Test fixture for
@@ -24,19 +25,12 @@
 
   /** @override */
   get browsePreload() {
-    return 'chrome://sync-confirmation/sync_confirmation_app.html';
+    return 'chrome://sync-confirmation/test_loader.html?module=signin/sync_confirmation_test.js';
   }
 
   /** @override */
-  get extraLibraries() {
-    return [
-      ...super.extraLibraries,
-      '//chrome/test/data/webui/test_browser_proxy.js',
-      '//chrome/browser/resources/signin/sync_confirmation/' +
-          'sync_confirmation_browser_proxy.js',
-      'test_sync_confirmation_browser_proxy.js',
-      'sync_confirmation_test.js',
-    ];
+  get featureList() {
+    return {enabled: ['network::features::kOutOfBlinkCors']};
   }
 };
 
diff --git a/chrome/test/data/webui/signin/sync_confirmation_test.js b/chrome/test/data/webui/signin/sync_confirmation_test.js
index cd766e5..c843fed 100644
--- a/chrome/test/data/webui/signin/sync_confirmation_test.js
+++ b/chrome/test/data/webui/signin/sync_confirmation_test.js
@@ -2,87 +2,88 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-cr.define('signin_sync_confirmation', function() {
+import 'chrome://sync-confirmation/sync_confirmation_app.js';
 
-  suite('SigninSyncConfirmationTest', function() {
-    let app;
-    setup(function() {
-      PolymerTest.clearBody();
-      app = document.createElement('sync-confirmation-app');
-      let accountImageRequested = false;
-      registerMessageCallback('accountImageRequest', this, function() {
-        accountImageRequested = true;
-      });
-      document.body.append(app);
-      // Check that the account image is requested when the app element is
-      // attached to the document.
-      assertTrue(accountImageRequested);
+import {SyncConfirmationBrowserProxyImpl} from 'chrome://sync-confirmation/sync_confirmation_browser_proxy.js';
+import {TestSyncConfirmationBrowserProxy} from './test_sync_confirmation_browser_proxy.js';
+
+suite('SigninSyncConfirmationTest', function() {
+  let app;
+  setup(function() {
+    PolymerTest.clearBody();
+    app = document.createElement('sync-confirmation-app');
+    let accountImageRequested = false;
+    registerMessageCallback('accountImageRequest', this, function() {
+      accountImageRequested = true;
     });
+    document.body.append(app);
+    // Check that the account image is requested when the app element is
+    // attached to the document.
+    assertTrue(accountImageRequested);
+  });
 
-    // Tests that no DCHECKS are thrown during initialization of the UI.
-    test('LoadPage', function() {
+  // Tests that no DCHECKS are thrown during initialization of the UI.
+  test('LoadPage', function() {
+    assertEquals(
+        'Turn on sync?', app.$.syncConfirmationHeading.textContent.trim());
+  });
+});
+
+// This test suite verifies that the consent strings recorded in various
+// scenarios are as expected. If the corresponding HTML file was updated
+// without also updating the attributes referring to consent strings,
+// this test will break.
+suite('SigninSyncConfirmationConsentRecordingTest', function() {
+  let app;
+  let browserProxy;
+
+  setup(function() {
+    // This test suite makes comparisons with strings in their default locale,
+    // which is en-US.
+    assertEquals(
+        'en-US', navigator.language,
+        'Cannot verify strings for the ' + navigator.language + 'locale.');
+
+    browserProxy = new TestSyncConfirmationBrowserProxy();
+    SyncConfirmationBrowserProxyImpl.instance_ = browserProxy;
+
+    PolymerTest.clearBody();
+    app = document.createElement('sync-confirmation-app');
+    document.body.append(app);
+  });
+
+  const STANDARD_CONSENT_DESCRIPTION_TEXT = [
+    'Turn on sync?',
+    'Sync your bookmarks, passwords, history, and more on all your devices',
+    'Google may use your history to personalize Search, ads, and other ' +
+        'Google services',
+  ];
+
+
+  // Tests that the expected strings are recorded when clicking the Confirm
+  // button.
+  test('recordConsentOnConfirm', function() {
+    app.$$('#confirmButton').click();
+    return browserProxy.whenCalled('confirm').then(function(
+        [description, confirmation]) {
       assertEquals(
-          'Turn on sync?', app.$.syncConfirmationHeading.textContent.trim());
+          JSON.stringify(STANDARD_CONSENT_DESCRIPTION_TEXT),
+          JSON.stringify(description));
+      assertEquals('Yes, I\'m in', confirmation);
     });
   });
 
-  // This test suite verifies that the consent strings recorded in various
-  // scenarios are as expected. If the corresponding HTML file was updated
-  // without also updating the attributes referring to consent strings,
-  // this test will break.
-  suite('SigninSyncConfirmationConsentRecordingTest', function() {
-    let app;
-    let browserProxy;
-
-    setup(function() {
-      // This test suite makes comparisons with strings in their default locale,
-      // which is en-US.
+  // Tests that the expected strings are recorded when clicking the Confirm
+  // button.
+  test('recordConsentOnSettingsLink', function() {
+    app.$$('#settingsButton').click();
+    return browserProxy.whenCalled('goToSettings').then(function([
+      description, confirmation
+    ]) {
       assertEquals(
-          'en-US', navigator.language,
-          'Cannot verify strings for the ' + navigator.language + 'locale.');
-
-      browserProxy = new TestSyncConfirmationBrowserProxy();
-      sync.confirmation.SyncConfirmationBrowserProxyImpl.instance_ =
-          browserProxy;
-
-      PolymerTest.clearBody();
-      app = document.createElement('sync-confirmation-app');
-      document.body.append(app);
-    });
-
-    const STANDARD_CONSENT_DESCRIPTION_TEXT = [
-      'Turn on sync?',
-      'Sync your bookmarks, passwords, history, and more on all your devices',
-      'Google may use your history to personalize Search, ads, and other ' +
-          'Google services',
-    ];
-
-
-    // Tests that the expected strings are recorded when clicking the Confirm
-    // button.
-    test('recordConsentOnConfirm', function() {
-      app.$$('#confirmButton').click();
-      return browserProxy.whenCalled('confirm').then(function(
-          [description, confirmation]) {
-        assertEquals(
-            JSON.stringify(STANDARD_CONSENT_DESCRIPTION_TEXT),
-            JSON.stringify(description));
-        assertEquals('Yes, I\'m in', confirmation);
-      });
-    });
-
-    // Tests that the expected strings are recorded when clicking the Confirm
-    // button.
-    test('recordConsentOnSettingsLink', function() {
-      app.$$('#settingsButton').click();
-      return browserProxy.whenCalled('goToSettings').then(function([
-        description, confirmation
-      ]) {
-        assertEquals(
-            JSON.stringify(STANDARD_CONSENT_DESCRIPTION_TEXT),
-            JSON.stringify(description));
-        assertEquals('Settings', confirmation);
-      });
+          JSON.stringify(STANDARD_CONSENT_DESCRIPTION_TEXT),
+          JSON.stringify(description));
+      assertEquals('Settings', confirmation);
     });
   });
 });
diff --git a/chrome/test/data/webui/signin/test_sync_confirmation_browser_proxy.js b/chrome/test/data/webui/signin/test_sync_confirmation_browser_proxy.js
index 04ab608..799c1ab 100644
--- a/chrome/test/data/webui/signin/test_sync_confirmation_browser_proxy.js
+++ b/chrome/test/data/webui/signin/test_sync_confirmation_browser_proxy.js
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js';
+
 /** @implements {settings.ProfileInfoBrowserProxy} */
-class TestSyncConfirmationBrowserProxy extends TestBrowserProxy {
+export class TestSyncConfirmationBrowserProxy extends TestBrowserProxy {
   constructor() {
     super([
       'confirm',
diff --git a/chrome/test/data/webui/tab_strip/tab_test.js b/chrome/test/data/webui/tab_strip/tab_test.js
index c8c4ae4..1f0b738 100644
--- a/chrome/test/data/webui/tab_strip/tab_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_test.js
@@ -59,7 +59,8 @@
   });
 
   test(
-      'toggles a [hide-icon] attribute when the icon container should be shown',
+      'toggles a [hide-icon_] attribute when the icon container should be ' +
+          'shown',
       () => {
         tabElement.tab = Object.assign({}, tab, {showIcon: true});
         assertFalse(tabElement.hasAttribute('hide-icon_'));
@@ -67,14 +68,14 @@
         assertTrue(tabElement.hasAttribute('hide-icon_'));
       });
 
-  test('toggles a [pinned] attribute when pinned', () => {
+  test('toggles a [pinned_] attribute when pinned', () => {
     tabElement.tab = Object.assign({}, tab, {pinned: true});
     assertTrue(tabElement.hasAttribute('pinned_'));
     tabElement.tab = Object.assign({}, tab, {pinned: false});
     assertFalse(tabElement.hasAttribute('pinned_'));
   });
 
-  test('toggles a [loading] attribute when loading', () => {
+  test('toggles a [loading_] attribute when loading', () => {
     tabElement.tab =
         Object.assign({}, tab, {networkState: TabNetworkState.LOADING});
     assertTrue(tabElement.hasAttribute('loading_'));
@@ -83,7 +84,7 @@
     assertFalse(tabElement.hasAttribute('loading_'));
   });
 
-  test('toggles a [waiting] attribute when waiting', () => {
+  test('toggles a [waiting_] attribute when waiting', () => {
     tabElement.tab =
         Object.assign({}, tab, {networkState: TabNetworkState.WAITING});
     assertTrue(tabElement.hasAttribute('waiting_'));
@@ -92,6 +93,13 @@
     assertFalse(tabElement.hasAttribute('waiting_'));
   });
 
+  test('toggles a [blocked_] attribute when blocked', () => {
+    tabElement.tab = Object.assign({}, tab, {blocked: true});
+    assertTrue(tabElement.hasAttribute('blocked_'));
+    tabElement.tab = Object.assign({}, tab, {blocked: false});
+    assertFalse(tabElement.hasAttribute('blocked_'));
+  });
+
   test('toggles a [crashed] attribute when crashed', () => {
     tabElement.tab = Object.assign({}, tab, {crashed: true});
     assertTrue(tabElement.hasAttribute('crashed'));
diff --git a/chrome/test/data/webui/welcome/app_chooser_test.js b/chrome/test/data/webui/welcome/app_chooser_test.js
index 3bef6e0..bab1dea 100644
--- a/chrome/test/data/webui/welcome/app_chooser_test.js
+++ b/chrome/test/data/webui/welcome/app_chooser_test.js
@@ -4,13 +4,14 @@
 
 import 'chrome://welcome/google_apps/nux_google_apps.js';
 
-import {TestBookmarkProxy} from 'chrome://test/welcome/test_bookmark_proxy.js';
-import {TestGoogleAppProxy} from 'chrome://test/welcome/test_google_app_proxy.js';
-import {TestMetricsProxy} from 'chrome://test/welcome/test_metrics_proxy.js';
 import {GoogleAppProxyImpl} from 'chrome://welcome/google_apps/google_app_proxy.js';
 import {GoogleAppsMetricsProxyImpl} from 'chrome://welcome/google_apps/google_apps_metrics_proxy.js';
 import {BookmarkBarManager, BookmarkProxyImpl} from 'chrome://welcome/shared/bookmark_proxy.js';
 
+import {TestBookmarkProxy} from './test_bookmark_proxy.js';
+import {TestGoogleAppProxy} from './test_google_app_proxy.js';
+import {TestMetricsProxy} from './test_metrics_proxy.js';
+
 suite('AppChooserTest', function() {
   const apps = [
     {
diff --git a/chrome/test/data/webui/welcome/module_metrics_test.js b/chrome/test/data/webui/welcome/module_metrics_test.js
index 3d049e5..6feb7e5 100644
--- a/chrome/test/data/webui/welcome/module_metrics_test.js
+++ b/chrome/test/data/webui/welcome/module_metrics_test.js
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {TestMetricsProxy} from 'chrome://test/welcome/test_metrics_proxy.js';
 import {ModuleMetricsManager} from 'chrome://welcome/shared/module_metrics_proxy.js';
 
+import {TestMetricsProxy} from './test_metrics_proxy.js';
+
 suite('ModuleMetricsTest', function() {
   /** @type {ModuleMetricsProxy} */
   let testMetricsProxy;
diff --git a/chrome/test/data/webui/welcome/nux_ntp_background_test.js b/chrome/test/data/webui/welcome/nux_ntp_background_test.js
index 5815b86..84a41c2 100644
--- a/chrome/test/data/webui/welcome/nux_ntp_background_test.js
+++ b/chrome/test/data/webui/welcome/nux_ntp_background_test.js
@@ -4,11 +4,12 @@
 
 import 'chrome://welcome/ntp_background/nux_ntp_background.js';
 
-import {TestMetricsProxy} from 'chrome://test/welcome/test_metrics_proxy.js';
-import {TestNtpBackgroundProxy} from 'chrome://test/welcome/test_ntp_background_proxy.js';
 import {NtpBackgroundMetricsProxyImpl} from 'chrome://welcome/ntp_background/ntp_background_metrics_proxy.js';
 import {NtpBackgroundProxyImpl} from 'chrome://welcome/ntp_background/ntp_background_proxy.js';
 
+import {TestMetricsProxy} from './test_metrics_proxy.js';
+import {TestNtpBackgroundProxy} from './test_ntp_background_proxy.js';
+
 suite('NuxNtpBackgroundTest', function() {
   /** @type {!Array<!NtpBackgroundData} */
   let backgrounds = [
diff --git a/chrome/test/data/webui/welcome/nux_set_as_default_test.js b/chrome/test/data/webui/welcome/nux_set_as_default_test.js
index ae425a5..85fcb97f 100644
--- a/chrome/test/data/webui/welcome/nux_set_as_default_test.js
+++ b/chrome/test/data/webui/welcome/nux_set_as_default_test.js
@@ -6,9 +6,10 @@
 
 import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
 import {eventToPromise} from 'chrome://test/test_util.m.js';
-import {TestNuxSetAsDefaultProxy} from 'chrome://test/welcome/test_nux_set_as_default_proxy.js';
 import {NuxSetAsDefaultProxyImpl} from 'chrome://welcome/set_as_default/nux_set_as_default_proxy.js';
 
+import {TestNuxSetAsDefaultProxy} from './test_nux_set_as_default_proxy.js';
+
 suite('SetAsDefaultTest', function() {
   /** @type {NuxSetAsDefaultElement} */
   let testElement;
diff --git a/chrome/test/data/webui/welcome/signin_view_test.js b/chrome/test/data/webui/welcome/signin_view_test.js
index 7b11f4a..ac15373 100644
--- a/chrome/test/data/webui/welcome/signin_view_test.js
+++ b/chrome/test/data/webui/welcome/signin_view_test.js
@@ -4,11 +4,12 @@
 
 import 'chrome://welcome/signin_view.js';
 
-import {TestSigninViewProxy} from 'chrome://test/welcome/test_signin_view_proxy.js';
-import {TestWelcomeBrowserProxy} from 'chrome://test/welcome/test_welcome_browser_proxy.js';
 import {SigninViewProxyImpl} from 'chrome://welcome/signin_view_proxy.js';
 import {WelcomeBrowserProxyImpl} from 'chrome://welcome/welcome_browser_proxy.js';
 
+import {TestSigninViewProxy} from './test_signin_view_proxy.js';
+import {TestWelcomeBrowserProxy} from './test_welcome_browser_proxy.js';
+
 suite('SigninViewTest', function() {
   /** @type {SigninViewElement} */
   let testElement;
diff --git a/chrome/test/data/webui/welcome/welcome_app_test.js b/chrome/test/data/webui/welcome/welcome_app_test.js
index 3a38e6d..23eaa7e 100644
--- a/chrome/test/data/webui/welcome/welcome_app_test.js
+++ b/chrome/test/data/webui/welcome/welcome_app_test.js
@@ -5,11 +5,6 @@
 import 'chrome://welcome/welcome_app.js';
 
 import {waitBeforeNextRender} from 'chrome://test/test_util.m.js';
-import {TestBookmarkProxy} from 'chrome://test/welcome/test_bookmark_proxy.js';
-import {TestLandingViewProxy} from 'chrome://test/welcome/test_landing_view_proxy.js';
-import {TestMetricsProxy} from 'chrome://test/welcome/test_metrics_proxy.js';
-import {TestNuxSetAsDefaultProxy} from 'chrome://test/welcome/test_nux_set_as_default_proxy.js';
-import {TestWelcomeBrowserProxy} from 'chrome://test/welcome/test_welcome_browser_proxy.js';
 import {LandingViewProxyImpl} from 'chrome://welcome/landing_view_proxy.js';
 import {navigateTo, Routes} from 'chrome://welcome/navigation_behavior.js';
 import {NuxSetAsDefaultProxyImpl} from 'chrome://welcome/set_as_default/nux_set_as_default_proxy.js';
@@ -17,6 +12,12 @@
 import {ModuleMetricsProxyImpl} from 'chrome://welcome/shared/module_metrics_proxy.js';
 import {WelcomeBrowserProxyImpl} from 'chrome://welcome/welcome_browser_proxy.js';
 
+import {TestBookmarkProxy} from './test_bookmark_proxy.js';
+import {TestLandingViewProxy} from './test_landing_view_proxy.js';
+import {TestMetricsProxy} from './test_metrics_proxy.js';
+import {TestNuxSetAsDefaultProxy} from './test_nux_set_as_default_proxy.js';
+import {TestWelcomeBrowserProxy} from './test_welcome_browser_proxy.js';
+
 suite('WelcomeWelcomeAppTest', function() {
   /** @type {WelcomeAppElement} */
   let testElement;
diff --git a/chrome/test/data/webui/welcome/welcome_browsertest.js b/chrome/test/data/webui/welcome/welcome_browsertest.js
index 9d3843b..14ff4b3 100644
--- a/chrome/test/data/webui/welcome/welcome_browsertest.js
+++ b/chrome/test/data/webui/welcome/welcome_browsertest.js
@@ -17,14 +17,6 @@
   }
 
   /** @override */
-  get extraLibraries() {
-    return [
-      '//third_party/mocha/mocha.js',
-      '//chrome/test/data/webui/mocha_adapter.js',
-    ];
-  }
-
-  /** @override */
   get webuiHost() {
     return 'welcome';
   }
diff --git a/chromecast/browser/cast_extension_host.cc b/chromecast/browser/cast_extension_host.cc
index 3572655..7c160d15 100644
--- a/chromecast/browser/cast_extension_host.cc
+++ b/chromecast/browser/cast_extension_host.cc
@@ -108,7 +108,7 @@
 void CastExtensionHost::EnterFullscreenModeForTab(
     content::WebContents* web_contents,
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   SetFullscreen(web_contents, true);
 }
 void CastExtensionHost::ExitFullscreenModeForTab(
diff --git a/chromecast/browser/cast_extension_host.h b/chromecast/browser/cast_extension_host.h
index 47dba29..86e5cb8 100644
--- a/chromecast/browser/cast_extension_host.h
+++ b/chromecast/browser/cast_extension_host.h
@@ -48,7 +48,7 @@
   void EnterFullscreenModeForTab(
       content::WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override;
+      const blink::FullScreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents*) override;
   bool IsFullscreenForTabOrPending(
       const content::WebContents* web_contents) override;
diff --git a/chromeos/network/network_device_handler_impl.h b/chromeos/network/network_device_handler_impl.h
index 0270817..643eadd 100644
--- a/chromeos/network/network_device_handler_impl.h
+++ b/chromeos/network/network_device_handler_impl.h
@@ -139,16 +139,17 @@
 
   void Init(NetworkStateHandler* network_state_handler);
 
-  // Apply the current value of |cellular_allow_roaming_| to all existing
+  // Applies the current value of |cellular_allow_roaming_| to all existing
   // cellular devices of Shill.
   void ApplyCellularAllowRoamingToShill();
 
-  // Apply the current value of |mac_addr_randomization_enabled_| to wifi
+  // Applies the current value of |mac_addr_randomization_enabled_| to wifi
   // devices.
   void ApplyMACAddressRandomizationToShill();
 
-  // Apply the current value of |usb_ethernet_mac_address_source_| to primary
-  // enabled USB Ethernet device.
+  // Applies the current value of |usb_ethernet_mac_address_source_| to primary
+  // enabled USB Ethernet device. Does nothing if MAC address source is not
+  // specified yet.
   void ApplyUsbEthernetMacAddressSourceToShill();
 
   void OnSetUsbEthernetMacAddressSourceError(
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index a1863fb..9aaca42c 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -92,7 +92,7 @@
 // AutofillSaveCardImprovedUserConsent functionality to Chrome OS, Android, and
 // iOS without bringing the extended title string change with it.
 const base::Feature kAutofillSaveCardShowNoThanks{
-    "AutofillSaveCardShowNoThanks", base::FEATURE_DISABLED_BY_DEFAULT};
+    "AutofillSaveCardShowNoThanks", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Controls what title and bubble label for the credit card upload bubble are
 // shown to users.
diff --git a/components/autofill_assistant/browser/actions/collect_user_data_action.cc b/components/autofill_assistant/browser/actions/collect_user_data_action.cc
index 593e2e6..a999f1f 100644
--- a/components/autofill_assistant/browser/actions/collect_user_data_action.cc
+++ b/components/autofill_assistant/browser/actions/collect_user_data_action.cc
@@ -5,6 +5,7 @@
 #include "components/autofill_assistant/browser/actions/collect_user_data_action.h"
 
 #include <algorithm>
+#include <set>
 #include <utility>
 
 #include "base/android/locale_utils.h"
@@ -179,6 +180,46 @@
          CompareDateTimes(start, end) < 0;
 }
 
+bool IsValidUserFormSection(
+    const autofill_assistant::UserFormSectionProto& proto) {
+  if (proto.title().empty()) {
+    DVLOG(2) << "UserFormSectionProto: Empty title not allowed.";
+    return false;
+  }
+  switch (proto.section_case()) {
+    case autofill_assistant::UserFormSectionProto::kStaticTextSection:
+      if (proto.static_text_section().text().empty()) {
+        DVLOG(2) << "StaticTextSectionProto: Empty text not allowed.";
+        return false;
+      }
+      break;
+    case autofill_assistant::UserFormSectionProto::kTextInputSection: {
+      if (proto.text_input_section().input_fields().empty()) {
+        DVLOG(2) << "TextInputProto: At least one input must be specified.";
+        return false;
+      }
+      std::set<std::string> memory_keys;
+      for (const auto& input_field :
+           proto.text_input_section().input_fields()) {
+        if (input_field.client_memory_key().empty()) {
+          DVLOG(2) << "TextInputProto: Memory key must be specified.";
+          return false;
+        }
+        if (!memory_keys.insert(input_field.client_memory_key()).second) {
+          DVLOG(2) << "TextInputProto: Duplicate memory keys ("
+                   << input_field.client_memory_key() << ").";
+          return false;
+        }
+      }
+      break;
+    }
+    case autofill_assistant::UserFormSectionProto::SECTION_NOT_SET:
+      DVLOG(2) << "UserFormSectionProto: section oneof not set.";
+      return false;
+  }
+  return true;
+}
+
 }  // namespace
 
 namespace autofill_assistant {
@@ -305,6 +346,28 @@
       user_data->terms_and_conditions = REQUIRES_REVIEW;
       break;
   }
+  for (const auto& additional_section :
+       collect_user_data.additional_prepended_sections()) {
+    if (additional_section.section_case() ==
+        UserFormSectionProto::kTextInputSection) {
+      for (const auto& text_input :
+           additional_section.text_input_section().input_fields()) {
+        user_data->additional_values_to_store.emplace(
+            text_input.client_memory_key(), text_input.value());
+      }
+    }
+  }
+  for (const auto& additional_section :
+       collect_user_data.additional_appended_sections()) {
+    if (additional_section.section_case() ==
+        UserFormSectionProto::kTextInputSection) {
+      for (const auto& text_input :
+           additional_section.text_input_section().input_fields()) {
+        user_data->additional_values_to_store.emplace(
+            text_input.client_memory_key(), text_input.value());
+      }
+    }
+  }
 
   if (collect_user_data_options->request_login_choice &&
       collect_user_data_options->login_choices.empty()) {
@@ -436,6 +499,11 @@
            ->mutable_date_time_end() = user_data->date_time_range_end;
     }
 
+    for (const auto& value : user_data->additional_values_to_store) {
+      delegate_->GetClientMemory()->set_additional_value(value.first,
+                                                         value.second);
+    }
+
     processed_action_proto_->mutable_collect_user_data_result()
         ->set_is_terms_and_conditions_accepted(
             user_data->terms_and_conditions ==
@@ -549,6 +617,26 @@
         collect_user_data.date_time_range();
   }
 
+  for (const auto& section :
+       collect_user_data.additional_prepended_sections()) {
+    if (!IsValidUserFormSection(section)) {
+      DVLOG(1)
+          << "Invalid UserFormSectionProto in additional_prepended_sections";
+      return nullptr;
+    }
+    collect_user_data_options->additional_prepended_sections.emplace_back(
+        section);
+  }
+  for (const auto& section : collect_user_data.additional_appended_sections()) {
+    if (!IsValidUserFormSection(section)) {
+      DVLOG(1)
+          << "Invalid UserFormSectionProto in additional_appended_sections";
+      return nullptr;
+    }
+    collect_user_data_options->additional_appended_sections.emplace_back(
+        section);
+  }
+
   // TODO(crbug.com/806868): Maybe we could refactor this to make the confirm
   // chip and direct_action part of the additional_actions.
   std::string confirm_text = collect_user_data.confirm_button_text();
diff --git a/components/autofill_assistant/browser/actions/collect_user_data_action_unittest.cc b/components/autofill_assistant/browser/actions/collect_user_data_action_unittest.cc
index d3bc4ba..3c39e90 100644
--- a/components/autofill_assistant/browser/actions/collect_user_data_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/collect_user_data_action_unittest.cc
@@ -566,5 +566,172 @@
   action.ProcessAction(callback_.Get());
 }
 
+TEST_F(CollectUserDataActionTest, StaticSectionValid) {
+  ActionProto action_proto;
+  auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
+  collect_user_data_proto->set_request_terms_and_conditions(false);
+  ON_CALL(mock_action_delegate_, CollectUserData(_, _))
+      .WillByDefault(Invoke(
+          [](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+             std::unique_ptr<UserData> user_data) {
+            user_data->succeed = true;
+            std::move(collect_user_data_options->confirm_callback)
+                .Run(std::move(user_data));
+          }));
+
+  auto* static_section =
+      collect_user_data_proto->add_additional_prepended_sections();
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+    action.ProcessAction(callback_.Get());
+  }
+
+  static_section->set_title("Static section");
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+    action.ProcessAction(callback_.Get());
+  }
+
+  static_section->mutable_static_text_section()->set_text("Lorem ipsum.");
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+    action.ProcessAction(callback_.Get());
+  }
+}
+
+TEST_F(CollectUserDataActionTest, TextInputSectionValid) {
+  ActionProto action_proto;
+  auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
+  collect_user_data_proto->set_request_terms_and_conditions(false);
+  ON_CALL(mock_action_delegate_, CollectUserData(_, _))
+      .WillByDefault(Invoke(
+          [](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+             std::unique_ptr<UserData> user_data) {
+            user_data->succeed = true;
+            std::move(collect_user_data_options->confirm_callback)
+                .Run(std::move(user_data));
+          }));
+
+  auto* text_input_section =
+      collect_user_data_proto->add_additional_prepended_sections();
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+    action.ProcessAction(callback_.Get());
+  }
+
+  text_input_section->set_title("Text input section");
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+    action.ProcessAction(callback_.Get());
+  }
+
+  auto* input_field =
+      text_input_section->mutable_text_input_section()->add_input_fields();
+  input_field->set_value("12345");
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+    action.ProcessAction(callback_.Get());
+  }
+
+  input_field->set_input_type(TextInputProto::INPUT_ALPHANUMERIC);
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+    action.ProcessAction(callback_.Get());
+  }
+
+  input_field->set_client_memory_key("code");
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+    action.ProcessAction(callback_.Get());
+  }
+
+  // Duplicate input field fails due to duplicate memory key.
+  *text_input_section->mutable_text_input_section()->add_input_fields() =
+      *input_field;
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+    action.ProcessAction(callback_.Get());
+  }
+
+  text_input_section->mutable_text_input_section()
+      ->mutable_input_fields(1)
+      ->set_client_memory_key("something else");
+  {
+    CollectUserDataAction action(&mock_action_delegate_, action_proto);
+    EXPECT_CALL(
+        callback_,
+        Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+    action.ProcessAction(callback_.Get());
+  }
+}
+
+TEST_F(CollectUserDataActionTest, TextInputSectionWritesToClientMemory) {
+  ActionProto action_proto;
+  auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
+  collect_user_data_proto->set_request_terms_and_conditions(false);
+  ON_CALL(mock_action_delegate_, CollectUserData(_, _))
+      .WillByDefault(Invoke(
+          [](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+             std::unique_ptr<UserData> user_data) {
+            user_data->succeed = true;
+            user_data->additional_values_to_store["key2"] = "modified";
+            std::move(collect_user_data_options->confirm_callback)
+                .Run(std::move(user_data));
+          }));
+
+  auto* text_input_section =
+      collect_user_data_proto->add_additional_prepended_sections();
+  text_input_section->set_title("Text input section");
+
+  auto* input_field_1 =
+      text_input_section->mutable_text_input_section()->add_input_fields();
+  input_field_1->set_value("initial");
+  input_field_1->set_input_type(TextInputProto::INPUT_ALPHANUMERIC);
+  input_field_1->set_client_memory_key("key1");
+
+  auto* input_field_2 =
+      text_input_section->mutable_text_input_section()->add_input_fields();
+  input_field_2->set_value("initial");
+  input_field_2->set_input_type(TextInputProto::INPUT_ALPHANUMERIC);
+  input_field_2->set_client_memory_key("key2");
+
+  EXPECT_FALSE(client_memory_.has_additional_value("key1"));
+  EXPECT_FALSE(client_memory_.has_additional_value("key2"));
+  CollectUserDataAction action(&mock_action_delegate_, action_proto);
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+  action.ProcessAction(callback_.Get());
+  EXPECT_EQ(*client_memory_.additional_value("key1"), "initial");
+  EXPECT_EQ(*client_memory_.additional_value("key2"), "modified");
+}
+
 }  // namespace
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
index 10beaf3..c3615cf 100644
--- a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
+++ b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
@@ -100,6 +100,24 @@
         // Currently no check required.
         field_inputs_.emplace_back(/* value = */ keypress.text());
         break;
+      case SetFormFieldValueProto_KeyPress::kClientMemoryKey:
+        if (keypress.client_memory_key().empty()) {
+          DVLOG(1) << "SetFormFieldValueAction: empty |client_memory_key|";
+          EndAction(ClientStatus(INVALID_ACTION));
+          return;
+        }
+        if (!delegate_->GetClientMemory()->has_additional_value(
+                keypress.client_memory_key())) {
+          DVLOG(1) << "SetFormFieldValueAction: requested key '"
+                   << keypress.client_memory_key()
+                   << "' not available in client memory";
+          EndAction(ClientStatus(PRECONDITION_FAILED));
+          return;
+        }
+        field_inputs_.emplace_back(
+            /* value = */ *delegate_->GetClientMemory()->additional_value(
+                keypress.client_memory_key()));
+        break;
       default:
         DVLOG(1) << "Unrecognized field for SetFormFieldValueProto_KeyPress";
         EndAction(ClientStatus(INVALID_ACTION));
diff --git a/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc b/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc
index 10534d6..621f725 100644
--- a/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc
@@ -191,6 +191,33 @@
   action.ProcessAction(callback_.Get());
 }
 
+TEST_F(SetFormFieldValueActionTest, ClientMemoryKey) {
+  auto* value = set_form_field_proto_->add_value();
+  value->set_client_memory_key("key");
+  client_memory_.set_additional_value("key", "SomeText𠜎");
+  SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+  ON_CALL(mock_action_delegate_, OnGetFieldValue(_, _))
+      .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "SomeText𠜎"));
+  EXPECT_CALL(mock_action_delegate_,
+              OnSetFieldValue(fake_selector_, "SomeText𠜎", _, _, _))
+      .WillOnce(RunOnceCallback<4>(OkClientStatus()));
+
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+  action.ProcessAction(callback_.Get());
+}
+
+TEST_F(SetFormFieldValueActionTest, ClientMemoryKeyFailsIfNotInClientMemory) {
+  auto* value = set_form_field_proto_->add_value();
+  value->set_client_memory_key("key");
+  SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+
+  EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+                                              PRECONDITION_FAILED))));
+  action.ProcessAction(callback_.Get());
+}
+
 // Test that automatic fallback to simulate keystrokes works.
 TEST_F(SetFormFieldValueActionTest, Fallback) {
   auto* value = set_form_field_proto_->add_value();
diff --git a/components/autofill_assistant/browser/client_memory.cc b/components/autofill_assistant/browser/client_memory.cc
index b61a9a6..5790150 100644
--- a/components/autofill_assistant/browser/client_memory.cc
+++ b/components/autofill_assistant/browser/client_memory.cc
@@ -62,6 +62,23 @@
   return nullptr;
 }
 
+const std::string* ClientMemory::additional_value(const std::string& key) {
+  auto it = additional_values_.find(key);
+  if (it == additional_values_.end()) {
+    return nullptr;
+  }
+  return &it->second;
+}
+
+bool ClientMemory::has_additional_value(const std::string& key) {
+  return additional_values_.find(key) != additional_values_.end();
+}
+
+void ClientMemory::set_additional_value(const std::string& key,
+                                        const std::string& value) {
+  additional_values_[key] = value;
+}
+
 std::string ClientMemory::GetAllAddressKeyNames() const {
   std::vector<std::string> entries;
   for (const auto& entry : selected_addresses_) {
diff --git a/components/autofill_assistant/browser/client_memory.h b/components/autofill_assistant/browser/client_memory.h
index ee24fb35..b3e4af6 100644
--- a/components/autofill_assistant/browser/client_memory.h
+++ b/components/autofill_assistant/browser/client_memory.h
@@ -55,6 +55,15 @@
   // The selected login or nullptr if no login was selected.
   const WebsiteLoginFetcher::Login* selected_login() const;
 
+  // The additional value for |key|, or nullptr if it does not exist.
+  const std::string* additional_value(const std::string& key);
+
+  // Returns true if an additional value is stored for |key|.
+  bool has_additional_value(const std::string& key);
+
+  // Sets the additional value for |key|.
+  void set_additional_value(const std::string& key, const std::string& value);
+
   std::string GetAllAddressKeyNames() const;
 
  private:
@@ -64,6 +73,8 @@
   // The address key requested by the autofill action.
   std::map<std::string, std::unique_ptr<autofill::AutofillProfile>>
       selected_addresses_;
+  // Maps keys to additional values.
+  std::map<std::string, std::string> additional_values_;
 };
 
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index 2594a4f..021541a 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -1018,6 +1018,23 @@
   UpdateCollectUserDataActions();
 }
 
+void Controller::SetAdditionalValue(const std::string& client_memory_key,
+                                    const std::string& value) {
+  if (!user_data_)
+    return;
+  auto it = user_data_->additional_values_to_store.find(client_memory_key);
+  if (it == user_data_->additional_values_to_store.end()) {
+    NOTREACHED() << client_memory_key << " not found";
+    return;
+  }
+  it->second.assign(value);
+  for (ControllerObserver& observer : observers_) {
+    observer.OnUserDataChanged(user_data_.get());
+  }
+  // It is currently not necessary to call |UpdateCollectUserDataActions|
+  // because all additional values are optional.
+}
+
 void Controller::SetShippingAddress(
     std::unique_ptr<autofill::AutofillProfile> address) {
   if (!user_data_)
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h
index b3ce880..36c636c 100644
--- a/components/autofill_assistant/browser/controller.h
+++ b/components/autofill_assistant/browser/controller.h
@@ -163,13 +163,14 @@
                              int hour,
                              int minute,
                              int second) override;
-
   void SetDateTimeRangeEnd(int year,
                            int month,
                            int day,
                            int hour,
                            int minute,
                            int second) override;
+  void SetAdditionalValue(const std::string& client_memory_key,
+                          const std::string& value) override;
   void GetTouchableArea(std::vector<RectF>* area) const override;
   void GetRestrictedArea(std::vector<RectF>* area) const override;
   void GetVisualViewport(RectF* visual_viewport) const override;
diff --git a/components/autofill_assistant/browser/controller_unittest.cc b/components/autofill_assistant/browser/controller_unittest.cc
index 064ed887..6446653 100644
--- a/components/autofill_assistant/browser/controller_unittest.cc
+++ b/components/autofill_assistant/browser/controller_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/guid.h"
 #include "base/test/gmock_callback_support.h"
+#include "base/test/gtest_util.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
@@ -1596,6 +1597,33 @@
       Eq(0));
 }
 
+TEST_F(ControllerTest, SetAdditionalValues) {
+  auto options = std::make_unique<MockCollectUserDataOptions>();
+  auto user_data = std::make_unique<UserData>();
+
+  user_data->additional_values_to_store["key1"] = "123456789";
+  user_data->additional_values_to_store["key2"] = "";
+  user_data->additional_values_to_store["key3"] = "";
+
+  testing::InSequence seq;
+  EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+                                  Property(&UserAction::enabled, Eq(true)))))
+      .Times(1);
+  controller_->SetCollectUserDataOptions(std::move(options),
+                                         std::move(user_data));
+
+  EXPECT_CALL(mock_observer_, OnUserDataChanged(Not(nullptr))).Times(2);
+  controller_->SetAdditionalValue("key2", "value2");
+  controller_->SetAdditionalValue("key3", "value3");
+  EXPECT_EQ(controller_->GetUserData()->additional_values_to_store.at("key1"),
+            "123456789");
+  EXPECT_EQ(controller_->GetUserData()->additional_values_to_store.at("key2"),
+            "value2");
+  EXPECT_EQ(controller_->GetUserData()->additional_values_to_store.at("key3"),
+            "value3");
+  EXPECT_DCHECK_DEATH(controller_->SetAdditionalValue("key4", "someValue"));
+}
+
 TEST_F(ControllerTest, SetOverlayColors) {
   EXPECT_CALL(
       mock_observer_,
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index d83c72e..c4f91cb 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -1211,6 +1211,45 @@
   optional string end_label = 6;
 }
 
+// A section showing a simple text message.
+message StaticTextSectionProto {
+  // The text to display. Can contain markup tags like <b>.
+  optional string text = 1;
+}
+
+// A single text input.
+message TextInputProto {
+  optional string hint = 1;
+  enum InputType {
+    UNDEFINED = 0;
+    // Regular text, no special formatting rules.
+    INPUT_TEXT = 1;
+    // An alphanumeric input, e.g. postal code or discount code.
+    INPUT_ALPHANUMERIC = 2;
+  }
+  optional InputType input_type = 2;
+
+  // The client memory key to store the result in.
+  optional string client_memory_key = 3;
+
+  // The initial value of the text input.
+  optional string value = 4;
+}
+
+// A section containing one or multiple text inputs.
+message TextInputSectionProto {
+  repeated TextInputProto input_fields = 1;
+}
+
+message UserFormSectionProto {
+  optional string title = 1;
+
+  oneof section {
+    StaticTextSectionProto static_text_section = 2;
+    TextInputSectionProto text_input_section = 3;
+  }
+}
+
 // Asks to provide the data used by UseAddressAction and
 // UseCreditCardAction.
 message CollectUserDataProto {
@@ -1271,6 +1310,10 @@
   optional LoginDetailsProto login_details = 16;
   // The date/time range that should be gathered.
   optional DateTimeRangeProto date_time_range = 17;
+  // An optional list of additional sections, which is above all other sections.
+  repeated UserFormSectionProto additional_prepended_sections = 18;
+  // An optional list of additional sections, which is below all other sections.
+  repeated UserFormSectionProto additional_appended_sections = 19;
 }
 
 // Resets Autofill Assistant: clears any state and server payload.
@@ -1420,6 +1463,8 @@
       // Use the password from the Chrome password manager login previously
       // selected in a CollectUserDataAction.
       bool use_password = 5;
+      // Use the value stored at the specified memory location.
+      string client_memory_key = 6;
     }
   }
 
diff --git a/components/autofill_assistant/browser/ui_delegate.h b/components/autofill_assistant/browser/ui_delegate.h
index 07924f78..e6703bec1 100644
--- a/components/autofill_assistant/browser/ui_delegate.h
+++ b/components/autofill_assistant/browser/ui_delegate.h
@@ -139,6 +139,10 @@
                                    int minute,
                                    int second) = 0;
 
+  // Sets an additional value.
+  virtual void SetAdditionalValue(const std::string& client_memory_key,
+                                  const std::string& value) = 0;
+
   // Adds the rectangles that correspond to the current touchable area to
   // the given vector.
   //
diff --git a/components/autofill_assistant/browser/user_data.h b/components/autofill_assistant/browser/user_data.h
index 20d5c5b..1936bbaa 100644
--- a/components/autofill_assistant/browser/user_data.h
+++ b/components/autofill_assistant/browser/user_data.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_USER_DATA_H_
 #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_USER_DATA_H_
 
+#include <map>
 #include <memory>
 #include <string>
 #include <vector>
@@ -29,6 +30,11 @@
   REQUIRES_REVIEW = 2,
 };
 
+// GENERATED_JAVA_ENUM_PACKAGE: (
+// org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections)
+// GENERATED_JAVA_CLASS_NAME_OVERRIDE: AssistantTextInputType
+enum TextInputType { INPUT_TEXT = 0, INPUT_ALPHANUMERIC = 1 };
+
 // Represents a concrete login choice in the UI, e.g., 'Guest checkout' or
 // a particular Chrome PWM login account.
 struct LoginChoice {
@@ -57,6 +63,9 @@
   TermsAndConditionsState terms_and_conditions = NOT_SELECTED;
   DateTimeProto date_time_range_start;
   DateTimeProto date_time_range_end;
+
+  // A set of additional key/value pairs to be stored in client_memory.
+  std::map<std::string, std::string> additional_values_to_store;
 };
 
 // Struct for holding the payment request options.
@@ -87,6 +96,8 @@
   std::vector<UserActionProto> additional_actions;
   TermsAndConditionsState initial_terms_and_conditions = NOT_SELECTED;
   DateTimeRangeProto date_time_range;
+  std::vector<UserFormSectionProto> additional_prepended_sections;
+  std::vector<UserFormSectionProto> additional_appended_sections;
 
   base::OnceCallback<void(std::unique_ptr<UserData>)> confirm_callback;
   base::OnceCallback<void(int)> additional_actions_callback;
diff --git a/components/certificate_transparency/tools/make_ct_known_logs_list.py b/components/certificate_transparency/tools/make_ct_known_logs_list.py
index fcb1c8c..f1563dbe 100755
--- a/components/certificate_transparency/tools/make_ct_known_logs_list.py
+++ b/components/certificate_transparency/tools/make_ct_known_logs_list.py
@@ -84,7 +84,7 @@
 def _is_log_disqualified(log):
   # Disqualified logs are denoted with state="retired"
   assert (len(log.get("state").keys()) == 1)
-  log_state = log.get("state").keys()[0]
+  log_state = list(log.get("state"))[0]
   return log_state == "retired"
 
 
@@ -158,7 +158,7 @@
 
 def _is_log_once_or_currently_qualified(log):
   assert (len(log.get("state").keys()) == 1)
-  return log.get("state").keys()[0] not in ("pending", "rejected")
+  return list(log.get("state"))[0] not in ("pending", "rejected")
 
 
 def generate_cpp_file(input_file, f):
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
index c11118d..4931e0c 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -180,7 +180,8 @@
   DCHECK(service);
   DCHECK(config_service_url_.is_valid());
   DCHECK(!params::IsIncludedInHoldbackFieldTrial() ||
-         previews::params::IsLitePageServerPreviewsEnabled());
+         previews::params::IsLitePageServerPreviewsEnabled() ||
+         params::ForceEnableClientConfigServiceForAllDataSaverUsers());
 
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
@@ -434,7 +435,8 @@
 void DataReductionProxyConfigServiceClient::RetrieveRemoteConfig() {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!params::IsIncludedInHoldbackFieldTrial() ||
-         previews::params::IsLitePageServerPreviewsEnabled());
+         previews::params::IsLitePageServerPreviewsEnabled() ||
+         params::ForceEnableClientConfigServiceForAllDataSaverUsers());
 
   CreateClientConfigRequest request;
   std::string serialized_request;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
index f3cd6f4..98d7f48e 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
@@ -95,7 +95,8 @@
   // synchronously on the UI thread, and |this| outlives the caller (since the
   // caller is owned by |this|.
   if (!params::IsIncludedInHoldbackFieldTrial() ||
-      previews::params::IsLitePageServerPreviewsEnabled()) {
+      previews::params::IsLitePageServerPreviewsEnabled() ||
+      params::ForceEnableClientConfigServiceForAllDataSaverUsers()) {
     config_client_ = std::make_unique<DataReductionProxyConfigServiceClient>(
         GetBackoffPolicy(), request_options_.get(), raw_mutable_config,
         config_.get(), this, network_connection_tracker_,
@@ -512,7 +513,8 @@
     const std::string& serialized_config) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!params::IsIncludedInHoldbackFieldTrial() ||
-         previews::params::IsLitePageServerPreviewsEnabled());
+         previews::params::IsLitePageServerPreviewsEnabled() ||
+         params::ForceEnableClientConfigServiceForAllDataSaverUsers());
 
   SetStringPref(prefs::kDataReductionProxyConfig, serialized_config);
   SetInt64Pref(prefs::kDataReductionProxyLastConfigRetrievalTime,
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
index ef5e55f..2871d80 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -112,6 +112,16 @@
   return base::FieldTrialList::FindFullName("DataCompressionProxyHoldback");
 }
 
+bool ForceEnableClientConfigServiceForAllDataSaverUsers() {
+  // Client config is enabled for all data users that are not in the
+  // kDataReductionProxyHoldback. Users that have kDataReductionProxyHoldback
+  // enabled have config service client enabled only if
+  // |force_enable_config_service_fetches| is set to true.
+  return GetFieldTrialParamByFeatureAsBool(
+      data_reduction_proxy::features::kDataReductionProxyHoldback,
+      "force_enable_config_service_fetches", false);
+}
+
 bool FetchWarmupProbeURLEnabled() {
   return !base::CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kDisableDataReductionProxyWarmupURLFetch);
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
index e79a7b7..6324387 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -48,6 +48,10 @@
 // not included in a group.
 std::string HoldbackFieldTrialGroup();
 
+// Returns true if DRP config service should always be fetched even if DRP
+// holdback is enabled.
+bool ForceEnableClientConfigServiceForAllDataSaverUsers();
+
 // Returns true if this client has the command line switch to enable forced
 // pageload metrics pingbacks on every page load.
 bool IsForcePingbackEnabledViaFlags();
diff --git a/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DomDistillerService.java b/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DomDistillerService.java
index 65894a7..6cd6fc6b 100644
--- a/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DomDistillerService.java
+++ b/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DomDistillerService.java
@@ -15,29 +15,18 @@
 @JNINamespace("dom_distiller::android")
 public final class DomDistillerService {
 
-    private final long mDomDistillerServiceAndroid;
     private final DistilledPagePrefs mDistilledPagePrefs;
 
     private DomDistillerService(long nativeDomDistillerAndroidServicePtr) {
-        mDomDistillerServiceAndroid = nativeDomDistillerAndroidServicePtr;
-        mDistilledPagePrefs = new DistilledPagePrefs(
-                DomDistillerServiceJni.get().getDistilledPagePrefsPtr(mDomDistillerServiceAndroid));
+        mDistilledPagePrefs =
+                new DistilledPagePrefs(DomDistillerServiceJni.get().getDistilledPagePrefsPtr(
+                        nativeDomDistillerAndroidServicePtr));
     }
 
     public DistilledPagePrefs getDistilledPagePrefs() {
         return mDistilledPagePrefs;
     }
 
-    public boolean hasEntry(String entryId) {
-        return DomDistillerServiceJni.get().hasEntry(
-                mDomDistillerServiceAndroid, DomDistillerService.this, entryId);
-    }
-
-    public String getUrlForEntry(String entryId) {
-        return DomDistillerServiceJni.get().getUrlForEntry(
-                mDomDistillerServiceAndroid, DomDistillerService.this, entryId);
-    }
-
     @CalledByNative
     private static DomDistillerService create(long nativeDomDistillerServiceAndroid) {
         ThreadUtils.assertOnUiThread();
@@ -46,10 +35,6 @@
 
     @NativeMethods
     interface Natives {
-        boolean hasEntry(
-                long nativeDomDistillerServiceAndroid, DomDistillerService caller, String entryId);
-        String getUrlForEntry(
-                long nativeDomDistillerServiceAndroid, DomDistillerService caller, String entryId);
         long getDistilledPagePrefsPtr(long nativeDomDistillerServiceAndroid);
     }
 }
diff --git a/components/dom_distiller/core/dom_distiller_service_android.cc b/components/dom_distiller/core/dom_distiller_service_android.cc
index 0d001186..2924a4bb 100644
--- a/components/dom_distiller/core/dom_distiller_service_android.cc
+++ b/components/dom_distiller/core/dom_distiller_service_android.cc
@@ -30,20 +30,6 @@
 
 DomDistillerServiceAndroid::~DomDistillerServiceAndroid() {}
 
-bool DomDistillerServiceAndroid::HasEntry(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jstring>& j_entry_id) {
-  return false;
-}
-
-ScopedJavaLocalRef<jstring> DomDistillerServiceAndroid::GetUrlForEntry(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jstring>& j_entry_id) {
-  return ConvertUTF8ToJavaString(env, std::string());
-}
-
 jlong DomDistillerServiceAndroid::GetDistilledPagePrefsPtr(JNIEnv* env) {
   return reinterpret_cast<intptr_t>(service_->GetDistilledPagePrefs());
 }
diff --git a/components/dom_distiller/core/dom_distiller_service_android.h b/components/dom_distiller/core/dom_distiller_service_android.h
index a0d94aec..6a91cde5 100644
--- a/components/dom_distiller/core/dom_distiller_service_android.h
+++ b/components/dom_distiller/core/dom_distiller_service_android.h
@@ -24,15 +24,6 @@
   // Returns native pointer to native DistilledPagePrefs registered with
   // DomDistillerService.
   jlong GetDistilledPagePrefsPtr(JNIEnv* env);
-  // TODO(crbug.com/1007942): Remove HasEntry and GetUrlForEntry, they always
-  // return false / empty string.
-  bool HasEntry(JNIEnv* env,
-                const base::android::JavaParamRef<jobject>& obj,
-                const base::android::JavaParamRef<jstring>& entry_id);
-  base::android::ScopedJavaLocalRef<jstring> GetUrlForEntry(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& obj,
-      const base::android::JavaParamRef<jstring>& entry_id);
 
  private:
   // Friend class so that DomDistillerServiceFactoryAndroid has access to
diff --git a/components/domain_reliability/quic_error_mapping.cc b/components/domain_reliability/quic_error_mapping.cc
index 521488c07c..60cc435 100644
--- a/components/domain_reliability/quic_error_mapping.cc
+++ b/components/domain_reliability/quic_error_mapping.cc
@@ -309,6 +309,8 @@
      "quic.window.update.received.on.read.unidirectional.stream"},
     {quic::QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
      "quic.too.many.buffered.control.frames"},
+    {quic::QUIC_TRANSPORT_INVALID_CLIENT_INDICATION,
+     "quic.transport.invalid.client.indication"},
 
     // QUIC_INVALID_APPLICATION_CLOSE_DATA was code 101. The code has been
     // deprecated, but to keep the assert below happy, there needs to be
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.cc b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
index a7de4a9..09f8b0c 100644
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.cc
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
@@ -343,7 +343,7 @@
 void WebContentsDelegateAndroid::EnterFullscreenModeForTab(
     WebContents* web_contents,
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
   if (obj.is_null())
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.h b/components/embedder_support/android/delegate/web_contents_delegate_android.h
index 3127006a..d3b2ca4 100644
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.h
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.h
@@ -100,7 +100,7 @@
   void EnterFullscreenModeForTab(
       content::WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override;
+      const blink::FullScreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
   bool IsFullscreenForTabOrPending(
       const content::WebContents* web_contents) override;
diff --git a/components/media_message_center/media_notification_view.cc b/components/media_message_center/media_notification_view.cc
index e645791..4b8cca4 100644
--- a/components/media_message_center/media_notification_view.cc
+++ b/components/media_message_center/media_notification_view.cc
@@ -385,7 +385,11 @@
       action_button->InvalidateLayout();
   }
 
-  container_->OnVisibleActionsChanged(visible_actions);
+  // We want to give the container a list of all possibly visible actions, and
+  // not just currently visible actions so it can make a decision on whether or
+  // not to force an expanded state.
+  container_->OnVisibleActionsChanged(GetTopVisibleActions(
+      enabled_actions_, ignored_actions, GetMaxNumActions(true)));
 }
 
 void MediaNotificationView::UpdateViewForExpandedState() {
@@ -427,10 +431,9 @@
   }
 
   header_row_->SetExpanded(expanded);
+  container_->OnExpanded(expanded);
 
   UpdateActionButtonsVisibility();
-
-  container_->OnExpanded(expanded);
 }
 
 void MediaNotificationView::CreateMediaButton(
diff --git a/components/media_message_center/media_notification_view_unittest.cc b/components/media_message_center/media_notification_view_unittest.cc
index faaa41eb..1cf2384c 100644
--- a/components/media_message_center/media_notification_view_unittest.cc
+++ b/components/media_message_center/media_notification_view_unittest.cc
@@ -650,10 +650,12 @@
 }
 
 TEST_F(MAYBE_MediaNotificationViewTest, Buttons_WhenCollapsed) {
-  EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
-                               {MediaSessionAction::kPlay,
-                                MediaSessionAction::kPreviousTrack,
-                                MediaSessionAction::kNextTrack})));
+  EXPECT_CALL(
+      container(),
+      OnVisibleActionsChanged(std::set<MediaSessionAction>(
+          {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
+           MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
+           MediaSessionAction::kSeekForward})));
   EnableAllActions();
   view()->SetExpanded(false);
   testing::Mock::VerifyAndClearExpectations(&container());
@@ -666,18 +668,21 @@
   EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekBackward));
   EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward));
 
-  EXPECT_CALL(container(),
-              OnVisibleActionsChanged(std::set<MediaSessionAction>(
-                  {MediaSessionAction::kPlay, MediaSessionAction::kSeekBackward,
-                   MediaSessionAction::kNextTrack})));
+  EXPECT_CALL(
+      container(),
+      OnVisibleActionsChanged(std::set<MediaSessionAction>(
+          {MediaSessionAction::kPlay, MediaSessionAction::kSeekBackward,
+           MediaSessionAction::kNextTrack, MediaSessionAction::kSeekForward})));
   DisableAction(MediaSessionAction::kPreviousTrack);
   testing::Mock::VerifyAndClearExpectations(&container());
   EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack));
 
-  EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
-                               {MediaSessionAction::kPlay,
-                                MediaSessionAction::kPreviousTrack,
-                                MediaSessionAction::kNextTrack})));
+  EXPECT_CALL(
+      container(),
+      OnVisibleActionsChanged(std::set<MediaSessionAction>(
+          {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
+           MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
+           MediaSessionAction::kSeekForward})));
   EnableAction(MediaSessionAction::kPreviousTrack);
   testing::Mock::VerifyAndClearExpectations(&container());
   EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack));
@@ -685,25 +690,30 @@
   EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
                                {MediaSessionAction::kPlay,
                                 MediaSessionAction::kPreviousTrack,
-                                MediaSessionAction::kNextTrack})));
+                                MediaSessionAction::kNextTrack,
+                                MediaSessionAction::kSeekBackward})));
   DisableAction(MediaSessionAction::kSeekForward);
   testing::Mock::VerifyAndClearExpectations(&container());
   EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward));
 
-  EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
-                               {MediaSessionAction::kPlay,
-                                MediaSessionAction::kPreviousTrack,
-                                MediaSessionAction::kNextTrack})));
+  EXPECT_CALL(
+      container(),
+      OnVisibleActionsChanged(std::set<MediaSessionAction>(
+          {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
+           MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
+           MediaSessionAction::kSeekForward})));
   EnableAction(MediaSessionAction::kSeekForward);
   testing::Mock::VerifyAndClearExpectations(&container());
   EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward));
 }
 
 TEST_F(MAYBE_MediaNotificationViewTest, Buttons_WhenExpanded) {
-  EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
-                               {MediaSessionAction::kPlay,
-                                MediaSessionAction::kPreviousTrack,
-                                MediaSessionAction::kNextTrack})));
+  EXPECT_CALL(
+      container(),
+      OnVisibleActionsChanged(std::set<MediaSessionAction>(
+          {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
+           MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
+           MediaSessionAction::kSeekForward})));
   EnableAllActions();
   testing::Mock::VerifyAndClearExpectations(&container());
 
diff --git a/components/omnibox/browser/autocomplete_match_type.h b/components/omnibox/browser/autocomplete_match_type.h
index ef95e76..6d08fdc5 100644
--- a/components/omnibox/browser/autocomplete_match_type.h
+++ b/components/omnibox/browser/autocomplete_match_type.h
@@ -98,10 +98,6 @@
       const base::string16& match_text,
       bool is_tab_switch_button_focused,
       int* label_prefix_length = nullptr);
-
-  // Used for tab switch button message when reverse logic feature is selected.
-  static const char kAlternateTabSwitchButtonMessage[];
-  static const char kAlternateTabSwitchMessage[];
 };
 
 #endif  // COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_MATCH_TYPE_H_
diff --git a/components/performance_manager/performance_manager_lock_observer.cc b/components/performance_manager/performance_manager_lock_observer.cc
index 680af5c..c9e1414 100644
--- a/components/performance_manager/performance_manager_lock_observer.cc
+++ b/components/performance_manager/performance_manager_lock_observer.cc
@@ -22,6 +22,19 @@
     frame_node->SetIsHoldingWebLock(is_holding_web_lock);
 }
 
+void SetIsHoldingIndexedDBConnections(int render_process_id,
+                                      int render_frame_id,
+                                      bool is_holding_indexed_db_connection,
+                                      GraphImpl* graph) {
+  FrameNodeImpl* frame_node =
+      graph->GetFrameNodeById(render_process_id, render_frame_id);
+  // TODO(https://crbug.com/980533): Rename
+  // FrameNodeImpl::SetIsHoldingIndexedDBLock() to
+  // SetIsHoldingIndexedDBConnections().
+  if (frame_node)
+    frame_node->SetIsHoldingIndexedDBLock(is_holding_indexed_db_connection);
+}
+
 }  // namespace
 
 PerformanceManagerLockObserver::PerformanceManagerLockObserver() = default;
@@ -47,4 +60,20 @@
                                 render_frame_id, false));
 }
 
+void PerformanceManagerLockObserver::OnFrameStartsHoldingIndexedDBConnections(
+    int render_process_id,
+    int render_frame_id) {
+  PerformanceManagerImpl::CallOnGraphImpl(
+      FROM_HERE, base::BindOnce(&SetIsHoldingIndexedDBConnections,
+                                render_process_id, render_frame_id, true));
+}
+
+void PerformanceManagerLockObserver::OnFrameStopsHoldingIndexedDBConnections(
+    int render_process_id,
+    int render_frame_id) {
+  PerformanceManagerImpl::CallOnGraphImpl(
+      FROM_HERE, base::BindOnce(&SetIsHoldingIndexedDBConnections,
+                                render_process_id, render_frame_id, false));
+}
+
 }  // namespace performance_manager
diff --git a/components/performance_manager/performance_manager_lock_observer.h b/components/performance_manager/performance_manager_lock_observer.h
index 766f479..b0342d8e 100644
--- a/components/performance_manager/performance_manager_lock_observer.h
+++ b/components/performance_manager/performance_manager_lock_observer.h
@@ -19,6 +19,10 @@
                                     int render_frame_id) override;
   void OnFrameStopsHoldingWebLocks(int render_process_id,
                                    int render_frame_id) override;
+  void OnFrameStartsHoldingIndexedDBConnections(int render_process_id,
+                                                int render_frame_id) override;
+  void OnFrameStopsHoldingIndexedDBConnections(int render_process_id,
+                                               int render_frame_id) override;
 };
 
 }  // namespace performance_manager
diff --git a/components/policy/core/browser/browser_policy_connector_base.cc b/components/policy/core/browser/browser_policy_connector_base.cc
index ad6944c..29718da 100644
--- a/components/policy/core/browser/browser_policy_connector_base.cc
+++ b/components/policy/core/browser/browser_policy_connector_base.cc
@@ -57,8 +57,9 @@
     g_testing_provider->Shutdown();
   for (const auto& provider : policy_providers_)
     provider->Shutdown();
-  // Drop g_testing_provider so that tests executed with --single_process can
-  // call SetPolicyProviderForTesting() again. It is still owned by the test.
+  // Drop g_testing_provider so that tests executed with --single-process-tests
+  // can call SetPolicyProviderForTesting() again. It is still owned by the
+  // test.
   g_testing_provider = nullptr;
   g_created_policy_service = false;
 }
diff --git a/components/policy/core/common/cloud/cloud_policy_util.cc b/components/policy/core/common/cloud/cloud_policy_util.cc
index 8cff60c..1e7289c 100644
--- a/components/policy/core/common/cloud/cloud_policy_util.cc
+++ b/components/policy/core/common/cloud/cloud_policy_util.cc
@@ -111,7 +111,7 @@
 }
 
 std::string GetOSVersion() {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) || defined(OS_MACOSX)
+#if defined(OS_LINUX) || defined(OS_MACOSX)
   return base::SysInfo::OperatingSystemVersion();
 #elif defined(OS_WIN)
   base::win::OSInfo::VersionNumber version_number =
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto
index 6cc3da3..e131b43 100644
--- a/components/policy/proto/chrome_device_policy.proto
+++ b/components/policy/proto/chrome_device_policy.proto
@@ -787,6 +787,24 @@
   optional bool login_screen_keyboard_focus_highlight_enabled = 28;
   optional PolicyOptions login_screen_keyboard_focus_highlight_enabled_options =
       29;
+
+  // Sets the state of the screen magnifier accessibility feature on the login
+  // screen. If this policy is set to 1, the screen magnifier will be enabled
+  // in full-screen magnifier mode, when the login screen is shown. If this
+  // policy is set to 2, the screen magnifier will be enabled in docked
+  // magnifier mode, when the screen magnifier is shown. If this policy is set
+  // to 0, the screen magnifier will be disabled, when the screen magnifier is
+  // shown. If the PolicyOptions mode was being mandatory then the user won't be
+  // able to change these settings. Only if PolicyOptions was being set as
+  // recommended users can temporarily override this setting by changing the
+  // screen magnifier state the. However, the user's choice is not persistent
+  // and the default is restored whenever the login screen is shown anew or the
+  // user remains idle on the login screen for a minute. If this policy is left
+  // unset, the screen magnifier is disabled when the login screen is first
+  // shown. Users can enable or disable the screen magnifier anytime and its
+  // status on the login screen is persisted between users.
+  optional int64 login_screen_screen_magnifier_type = 30;
+  optional PolicyOptions login_screen_screen_magnifier_type_options = 31;
 }
 
 message SupervisedUsersSettingsProto {
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 00581b4..800d0c62b 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -655,6 +655,7 @@
         'DeviceLoginScreenAutoclickEnabled',
         'DeviceLoginScreenStickyKeysEnabled',
         'DeviceLoginScreenKeyboardFocusHighlightEnabled',
+        'DeviceLoginScreenScreenMagnifierType',
       ],
     },
     {
@@ -10610,6 +10611,53 @@
           If this policy is left unset, the screen magnifier is disabled when the login screen is first shown. Users can enable or disable the screen magnifier anytime and its status on the login screen is persisted between users.''',
     },
     {
+      'name': 'DeviceLoginScreenScreenMagnifierType',
+      'owners': ['amraboelkher@chromium.org', 'emaxx@chromium.org'],
+      'type': 'int-enum',
+      'schema': {
+        'type': 'integer',
+        'enum': [ 0, 1, 2 ],
+      },
+      'items': [
+        {
+          'name': 'None',
+          'value': 0,
+          'caption': '''Screen magnifier disabled''',
+        },
+        {
+          'name': 'Full-screen',
+          'value': 1,
+          'caption': '''Full-screen magnifier enabled''',
+        },
+        {
+          'name': 'Docked',
+          'value': 2,
+          'caption': '''Docked magnifier enabled''',
+        },
+      ],
+      'supported_on': ['chrome_os:79-'],
+      'device_only': True,
+      'features': {
+        'can_be_recommended': True,
+        'dynamic_refresh': True,
+      },
+      'example_value': True,
+      'id': 628,
+      'caption': '''Set the screen magnifier type on the login screen''',
+      'tags': [],
+      'desc': '''If this policy is set, it controls the type of screen magnifier that is enabled.
+
+          If this policy is set to "Full-screen", the screen magnifier will always be enabled in full-screen magnifier mode on the login screen.
+
+          If this policy is set to "Docked", the screen magnifier will always be enabled in docked magnifier mode on the login screen.
+
+          If this policy is set to "None", the screen magnifier will always be disabled on the login screen.
+
+          If you set this policy, users cannot change or override it.
+
+          If this policy is left unset, the dictation is disabled on the login screen initially but can be enabled by the user anytime.''',
+    },
+    {
       'name': 'DeviceLoginScreenDictationEnabled',
       'owners': ['amraboelkher@chromium.org', 'emaxx@chromium.org'],
       'type': 'main',
@@ -18675,6 +18723,7 @@
     'DeviceLoginScreenDefaultHighContrastEnabled': 'accessibility_settings.login_screen_default_high_contrast_enabled',
     'DeviceLoginScreenHighContrastEnabled': 'accessibility_settings.login_screen_high_contrast_enabled',
     'DeviceLoginScreenDefaultScreenMagnifierType': 'accessibility_settings.login_screen_default_screen_magnifier_type',
+    'DeviceLoginScreenScreenMagnifierType': 'accessibility_settings.login_screen_screen_magnifier_type',
     'DeviceLoginScreenDefaultVirtualKeyboardEnabled': 'accessibility_settings.login_screen_default_virtual_keyboard_enabled',
     'DeviceLoginScreenVirtualKeyboardEnabled': 'accessibility_settings.login_screen_virtual_keyboard_enabled',
     'DeviceLoginScreenDictationEnabled': 'accessibility_settings.login_screen_dictation_enabled',
@@ -19194,6 +19243,6 @@
   ],
   'placeholders': [],
   'deleted_policy_ids': [412, 546, 562, 569],
-  'highest_id_currently_used': 627,
+  'highest_id_currently_used': 628,
   'highest_atomic_group_id_currently_used': 38
 }
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 685d066..4c0553a 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -444,14 +444,10 @@
                    ConvertUnit(page_size.height(), dpi, kPointsPerInch));
 }
 
-bool FitToPageEnabled(const base::DictionaryValue& job_settings) {
-  return job_settings.FindBoolKey(kSettingFitToPageEnabled).value();
-}
-
-bool FitToPaperEnabled(const base::DictionaryValue& job_settings) {
-  // TODO(dhoss): Bug 989978: Should have a value. Will fix when
-  // |job_settings| contains a "fitToPaperEnabled" boolean field.
-  return job_settings.FindBoolKey(kSettingFitToPaperEnabled).value_or(false);
+ScalingType ScalingTypeFromJobSettings(
+    const base::DictionaryValue& job_settings) {
+  int scaling_type = job_settings.FindIntKey(kSettingScalingType).value();
+  return static_cast<ScalingType>(scaling_type);
 }
 
 // Returns the print scaling option to retain/scale/crop the source page size
@@ -478,19 +474,16 @@
     return blink::kWebPrintScalingOptionSourceSize;
 
   if (!source_is_html) {
-    bool fit_to_page = FitToPageEnabled(job_settings);
-    bool fit_to_paper = FitToPaperEnabled(job_settings);
-
+    ScalingType scaling_type = ScalingTypeFromJobSettings(job_settings);
     // The following conditions are ordered for an optimization that avoids
     // calling PDFShouldDisableScaling(), which has to make a call using PPAPI.
-    if (!fit_to_page && !fit_to_paper)
+    if (scaling_type == DEFAULT || scaling_type == CUSTOM)
       return blink::kWebPrintScalingOptionNone;
-
-    bool no_plugin_scaling = PDFShouldDisableScaling(frame, node, params, true);
-    if (params.is_first_request && no_plugin_scaling)
+    if (params.is_first_request &&
+        PDFShouldDisableScaling(frame, node, params, true)) {
       return blink::kWebPrintScalingOptionNone;
-
-    if (fit_to_paper)
+    }
+    if (scaling_type == FIT_TO_PAPER)
       return blink::kWebPrintScalingOptionFitToPaper;
   }
   return blink::kWebPrintScalingOptionFitToPrintableArea;
diff --git a/components/query_parser/BUILD.gn b/components/query_parser/BUILD.gn
index e627455d..35cf8d0d 100644
--- a/components/query_parser/BUILD.gn
+++ b/components/query_parser/BUILD.gn
@@ -39,5 +39,6 @@
   deps = [
     ":query_parser",
     "//base:base",
+    "//base:i18n",
   ]
 }
diff --git a/components/query_parser/query_parser_fuzzer.cc b/components/query_parser/query_parser_fuzzer.cc
index 38b1c6f..8cbad96 100644
--- a/components/query_parser/query_parser_fuzzer.cc
+++ b/components/query_parser/query_parser_fuzzer.cc
@@ -6,16 +6,22 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "base/i18n/icu_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/query_parser/query_parser.h"
 
+struct Environment {
+  Environment() { CHECK(base::i18n::InitializeICU()); }
+};
+
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  static Environment env;
   FuzzedDataProvider data_provider(data, size);
 
   const query_parser::MatchingAlgorithm matching_alg =
       data_provider.ConsumeEnum<query_parser::MatchingAlgorithm>();
-  const base::string16 query16(base::UTF8ToUTF16(
-      data_provider.ConsumeBytesAsString(data_provider.remaining_bytes())));
+  const base::string16 query16 = base::UTF8ToUTF16(
+      data_provider.ConsumeBytesAsString(data_provider.remaining_bytes()));
 
   query_parser::QueryParser parser;
   std::vector<base::string16> words;
diff --git a/components/safe_browsing/password_protection/metrics_util.cc b/components/safe_browsing/password_protection/metrics_util.cc
index 28390f7..ac61553 100644
--- a/components/safe_browsing/password_protection/metrics_util.cc
+++ b/components/safe_browsing/password_protection/metrics_util.cc
@@ -265,6 +265,10 @@
   }
 }
 
+void LogPasswordProtectionSampleReportSent() {
+  base::UmaHistogramBoolean("PasswordProtection.SampleReportSent", true);
+}
+
 void LogWarningAction(WarningUIType ui_type,
                       WarningAction action,
                       ReusedPasswordAccountType password_account_type) {
diff --git a/components/safe_browsing/password_protection/metrics_util.h b/components/safe_browsing/password_protection/metrics_util.h
index c9a8c4c..f3965283 100644
--- a/components/safe_browsing/password_protection/metrics_util.h
+++ b/components/safe_browsing/password_protection/metrics_util.h
@@ -185,6 +185,9 @@
     int response_code,
     const base::TimeTicks& request_start_time);
 
+// Logs when a sample ping of allowlist URLs is sent to Safe Browsing.
+void LogPasswordProtectionSampleReportSent();
+
 // Records user action on warnings to corresponding UMA histograms.
 void LogWarningAction(WarningUIType ui_type,
                       WarningAction action,
diff --git a/components/safe_browsing/password_protection/password_protection_request.cc b/components/safe_browsing/password_protection/password_protection_request.cc
index 4170d54..f329e04 100644
--- a/components/safe_browsing/password_protection/password_protection_request.cc
+++ b/components/safe_browsing/password_protection/password_protection_request.cc
@@ -201,6 +201,7 @@
   // If a sample ping is send, only the URL and referrer chain is sent in the
   // request.
   if (is_sampled_ping) {
+    LogPasswordProtectionSampleReportSent();
     request_proto_->set_report_type(
         LoginReputationClientRequest::SAMPLE_REPORT);
     request_proto_->clear_trigger_type();
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 169176b6..74ef7a1 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -993,7 +993,8 @@
     "indexed_db/indexed_db_database_error.h",
     "indexed_db/indexed_db_dispatcher_host.cc",
     "indexed_db/indexed_db_dispatcher_host.h",
-    "indexed_db/indexed_db_execution_context.h",
+    "indexed_db/indexed_db_execution_context_connection_tracker.cc",
+    "indexed_db/indexed_db_execution_context_connection_tracker.h",
     "indexed_db/indexed_db_factory.h",
     "indexed_db/indexed_db_factory_impl.cc",
     "indexed_db/indexed_db_factory_impl.h",
diff --git a/content/browser/DEPS b/content/browser/DEPS
index cf3c7ede..891679f 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -127,7 +127,6 @@
   "+third_party/blink/public/web/web_context_menu_data.h",
   "+third_party/blink/public/web/web_device_emulation_params.h",
   "+third_party/blink/public/web/web_drag_status.h",
-  "+third_party/blink/public/web/web_fullscreen_options.h",
   "+third_party/blink/public/web/web_ime_text_span.h",
   "+third_party/blink/public/web/web_media_player_action.h",
   "+third_party/blink/public/web/web_serialized_script_value_version.h",
diff --git a/content/browser/accessibility/fullscreen_browsertest.cc b/content/browser/accessibility/fullscreen_browsertest.cc
index 3d3fb9d..67587aa 100644
--- a/content/browser/accessibility/fullscreen_browsertest.cc
+++ b/content/browser/accessibility/fullscreen_browsertest.cc
@@ -53,7 +53,7 @@
 
   void EnterFullscreenModeForTab(WebContents*,
                                  const GURL&,
-                                 const blink::WebFullscreenOptions&) override {
+                                 const blink::FullScreenOptions&) override {
     is_fullscreen_ = true;
   }
 
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index ebba4a6b..10ddb8e 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -59,7 +59,7 @@
 }
 
 namespace blink {
-struct WebFullscreenOptions;
+struct FullScreenOptions;
 namespace mojom {
 class FileChooserParams;
 }
@@ -265,8 +265,7 @@
   // Notification that the frame wants to go into fullscreen mode.
   // |origin| represents the origin of the frame that requests fullscreen.
   virtual void EnterFullscreenMode(const GURL& origin,
-                                   const blink::WebFullscreenOptions& options) {
-  }
+                                   const blink::FullScreenOptions& options) {}
 
   // Notification that the frame wants to go out of fullscreen mode.
   // |will_cause_resize| indicates whether the fullscreen change causes a
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 6fe07e1..1c48427 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -3740,7 +3740,7 @@
 // TODO(alexmos): When the allowFullscreen flag is known in the browser
 // process, use it to double-check that fullscreen can be entered here.
 void RenderFrameHostImpl::OnEnterFullscreen(
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   // Entering fullscreen from a cross-process subframe also affects all
   // renderers for ancestor frames, which will need to apply fullscreen CSS to
   // appropriate ancestor <iframe> elements, fire fullscreenchange events, etc.
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index af4f6aa..fc20d45 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -135,7 +135,7 @@
 class AssociatedInterfaceRegistry;
 struct FramePolicy;
 struct TransferableMessage;
-struct WebFullscreenOptions;
+struct FullScreenOptions;
 struct WebScrollIntoViewParams;
 
 namespace mojom {
@@ -1382,7 +1382,7 @@
       ax::mojom::Event event_to_fire);
   void OnAccessibilitySnapshotResponse(int callback_id,
                                        const AXContentTreeUpdate& snapshot);
-  void OnEnterFullscreen(const blink::WebFullscreenOptions& options);
+  void OnEnterFullscreen(const blink::FullScreenOptions& options);
   void OnExitFullscreen();
   void OnSuddenTerminationDisablerChanged(
       bool present,
diff --git a/content/browser/indexed_db/indexed_db_connection.cc b/content/browser/indexed_db/indexed_db_connection.cc
index d247a73..d970dd7 100644
--- a/content/browser/indexed_db/indexed_db_connection.cc
+++ b/content/browser/indexed_db/indexed_db_connection.cc
@@ -27,7 +27,8 @@
 }  // namespace
 
 IndexedDBConnection::IndexedDBConnection(
-    const IndexedDBExecutionContext& execution_context,
+    IndexedDBExecutionContextConnectionTracker::Handle
+        execution_context_connection_handle,
     IndexedDBOriginStateHandle origin_state_handle,
     IndexedDBClassFactory* indexed_db_class_factory,
     base::WeakPtr<IndexedDBDatabase> database,
@@ -35,7 +36,8 @@
     base::OnceCallback<void(IndexedDBConnection*)> on_close,
     scoped_refptr<IndexedDBDatabaseCallbacks> callbacks)
     : id_(g_next_indexed_db_connection_id++),
-      execution_context_(execution_context),
+      execution_context_connection_handle_(
+          std::move(execution_context_connection_handle)),
       origin_state_handle_(std::move(origin_state_handle)),
       indexed_db_class_factory_(indexed_db_class_factory),
       database_(std::move(database)),
@@ -43,6 +45,7 @@
       on_close_(std::move(on_close)),
       callbacks_(callbacks) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!execution_context_connection_handle_.is_null());
 }
 
 IndexedDBConnection::~IndexedDBConnection() {
diff --git a/content/browser/indexed_db/indexed_db_connection.h b/content/browser/indexed_db/indexed_db_connection.h
index 280c402..4c0b381b 100644
--- a/content/browser/indexed_db/indexed_db_connection.h
+++ b/content/browser/indexed_db/indexed_db_connection.h
@@ -14,7 +14,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "content/browser/indexed_db/indexed_db_database.h"
-#include "content/browser/indexed_db/indexed_db_execution_context.h"
+#include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
 #include "content/browser/indexed_db/indexed_db_origin_state_handle.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 
@@ -27,7 +27,8 @@
 
 class CONTENT_EXPORT IndexedDBConnection {
  public:
-  IndexedDBConnection(const IndexedDBExecutionContext& execution_context,
+  IndexedDBConnection(IndexedDBExecutionContextConnectionTracker::Handle
+                          execution_context_connection_handle,
                       IndexedDBOriginStateHandle origin_state_handle,
                       IndexedDBClassFactory* indexed_db_class_factory,
                       base::WeakPtr<IndexedDBDatabase> database,
@@ -59,7 +60,9 @@
   virtual void RemoveObservers(const std::vector<int32_t>& remove_observer_ids);
 
   int32_t id() const { return id_; }
-  int child_process_id() const { return execution_context_.render_process_id; }
+  int child_process_id() const {
+    return execution_context_connection_handle_.render_process_id();
+  }
 
   base::WeakPtr<IndexedDBDatabase> database() const { return database_; }
   IndexedDBDatabaseCallbacks* callbacks() const { return callbacks_.get(); }
@@ -106,8 +109,10 @@
 
   const int32_t id_;
 
-  // The frame or worker that owns this connection.
-  const IndexedDBExecutionContext execution_context_;
+  // Allows IndexedDBExecutionContextConnectionTracker to keep track of the
+  // number of connections per execution context.
+  const IndexedDBExecutionContextConnectionTracker::Handle
+      execution_context_connection_handle_;
 
   // Keeps the factory for this origin alive.
   IndexedDBOriginStateHandle origin_state_handle_;
diff --git a/content/browser/indexed_db/indexed_db_connection_coordinator.cc b/content/browser/indexed_db/indexed_db_connection_coordinator.cc
index 452c009..3797ae27 100644
--- a/content/browser/indexed_db/indexed_db_connection_coordinator.cc
+++ b/content/browser/indexed_db/indexed_db_connection_coordinator.cc
@@ -123,15 +123,14 @@
               IndexedDBDatabase* db,
               std::unique_ptr<IndexedDBPendingConnection> pending_connection,
               IndexedDBConnectionCoordinator* connection_coordinator,
-
               TasksAvailableCallback tasks_available_callback)
       : ConnectionRequest(std::move(origin_state_handle),
                           db,
                           connection_coordinator,
-
                           std::move(tasks_available_callback)),
         pending_(std::move(pending_connection)) {
     db_->metadata_.was_cold_open = pending_->was_cold_open;
+    DCHECK(!pending_->execution_context_connection_handle.is_null());
   }
 
   // Note: the |tasks_available_callback_| is NOT called here because the state
@@ -171,9 +170,9 @@
       // DEFAULT_VERSION throws exception.)
       DCHECK(is_new_database);
       pending_->callbacks->OnSuccess(
-          db_->CreateConnection(std::move(origin_state_handle_),
-                                pending_->database_callbacks,
-                                pending_->execution_context),
+          db_->CreateConnection(
+              std::move(origin_state_handle_), pending_->database_callbacks,
+              std::move(pending_->execution_context_connection_handle)),
           db_->metadata_);
       state_ = RequestState::kDone;
       return;
@@ -183,9 +182,9 @@
         (new_version == old_version ||
          new_version == IndexedDBDatabaseMetadata::NO_VERSION)) {
       pending_->callbacks->OnSuccess(
-          db_->CreateConnection(std::move(origin_state_handle_),
-                                pending_->database_callbacks,
-                                pending_->execution_context),
+          db_->CreateConnection(
+              std::move(origin_state_handle_), pending_->database_callbacks,
+              std::move(pending_->execution_context_connection_handle)),
           db_->metadata_);
       state_ = RequestState::kDone;
       return;
@@ -278,9 +277,9 @@
     DCHECK(state_ == RequestState::kPendingLocks);
 
     DCHECK(!lock_receiver_.locks.empty());
-    connection_ = db_->CreateConnection(std::move(origin_state_handle_),
-                                        pending_->database_callbacks,
-                                        pending_->execution_context);
+    connection_ = db_->CreateConnection(
+        std::move(origin_state_handle_), pending_->database_callbacks,
+        std::move(pending_->execution_context_connection_handle));
     DCHECK(!connection_ptr_for_close_comparision_);
     connection_ptr_for_close_comparision_ = connection_.get();
     DCHECK_EQ(db_->connections().count(connection_.get()), 1UL);
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc
index 06a46a95..11520bd 100644
--- a/content/browser/indexed_db/indexed_db_database.cc
+++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -30,7 +30,6 @@
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_cursor.h"
-#include "content/browser/indexed_db/indexed_db_execution_context.h"
 #include "content/browser/indexed_db/indexed_db_factory.h"
 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
 #include "content/browser/indexed_db/indexed_db_index_writer.h"
@@ -1672,10 +1671,14 @@
 std::unique_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection(
     IndexedDBOriginStateHandle origin_state_handle,
     scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
-    const IndexedDBExecutionContext& execution_context) {
+    IndexedDBExecutionContextConnectionTracker::Handle
+        execution_context_connection_handle) {
+  const int render_process_id =
+      execution_context_connection_handle.render_process_id();
   std::unique_ptr<IndexedDBConnection> connection =
       std::make_unique<IndexedDBConnection>(
-          execution_context, std::move(origin_state_handle), class_factory_,
+          std::move(execution_context_connection_handle),
+          std::move(origin_state_handle), class_factory_,
           weak_factory_.GetWeakPtr(),
           base::BindRepeating(&IndexedDBDatabase::VersionChangeIgnored,
                               weak_factory_.GetWeakPtr()),
@@ -1683,8 +1686,7 @@
                          weak_factory_.GetWeakPtr()),
           database_callbacks);
   connections_.insert(connection.get());
-  backing_store_->GrantChildProcessPermissions(
-      execution_context.render_process_id);
+  backing_store_->GrantChildProcessPermissions(render_process_id);
   return connection;
 }
 
diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h
index 7416337..2c3ab73 100644
--- a/content/browser/indexed_db/indexed_db_database.h
+++ b/content/browser/indexed_db/indexed_db_database.h
@@ -27,6 +27,7 @@
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
 #include "content/browser/indexed_db/indexed_db_callbacks.h"
 #include "content/browser/indexed_db/indexed_db_connection_coordinator.h"
+#include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
 #include "content/browser/indexed_db/indexed_db_observer.h"
 #include "content/browser/indexed_db/indexed_db_origin_state_handle.h"
 #include "content/browser/indexed_db/indexed_db_pending_connection.h"
@@ -55,7 +56,6 @@
 class IndexedDBClassFactory;
 class IndexedDBConnection;
 class IndexedDBDatabaseCallbacks;
-struct IndexedDBExecutionContext;
 class IndexedDBFactory;
 class IndexedDBMetadataCoding;
 class IndexedDBOriginStateHandle;
@@ -359,7 +359,8 @@
   std::unique_ptr<IndexedDBConnection> CreateConnection(
       IndexedDBOriginStateHandle origin_state_handle,
       scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
-      const IndexedDBExecutionContext& execution_context);
+      IndexedDBExecutionContextConnectionTracker::Handle
+          execution_context_connection_handle);
 
   // Ack that one of the connections notified with a "versionchange" event did
   // not promptly close. Therefore a "blocked" event should be fired at the
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc
index 06c30a0..f94b056 100644
--- a/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -25,7 +25,7 @@
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_cursor.h"
-#include "content/browser/indexed_db/indexed_db_execution_context.h"
+#include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
@@ -50,8 +50,6 @@
 void CreateAndBindTransactionPlaceholder(
     base::WeakPtr<IndexedDBTransaction> transaction) {}
 
-constexpr IndexedDBExecutionContext kTestExecutionContext(4, 2);
-
 }  // namespace
 
 class IndexedDBDatabaseTest : public ::testing::Test {
@@ -125,8 +123,10 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection1(
       std::make_unique<IndexedDBPendingConnection>(
-          request1, callbacks1, kTestExecutionContext, transaction_id1,
-          IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+          request1, callbacks1,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
           std::move(create_transaction_callback1)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection1));
@@ -140,8 +140,10 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection2(
       std::make_unique<IndexedDBPendingConnection>(
-          request2, callbacks2, kTestExecutionContext, transaction_id2,
-          IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+          request2, callbacks2,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id2, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
           std::move(create_transaction_callback2)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection2));
@@ -169,8 +171,10 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection(
       std::make_unique<IndexedDBPendingConnection>(
-          request, callbacks, kTestExecutionContext, upgrade_transaction_id,
-          IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+          request, callbacks,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          upgrade_transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
           std::move(create_transaction_callback)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection));
@@ -230,8 +234,10 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection(
       std::make_unique<IndexedDBPendingConnection>(
-          request1, callbacks1, kTestExecutionContext, transaction_id1,
-          IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+          request1, callbacks1,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
           std::move(create_transaction_callback1)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection));
@@ -279,8 +285,11 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection1(
       std::make_unique<IndexedDBPendingConnection>(
-          request1, callbacks1, kTestExecutionContext, transaction_id1,
-          kDatabaseVersion, std::move(create_transaction_callback1)));
+          request1, callbacks1,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id1, kDatabaseVersion,
+          std::move(create_transaction_callback1)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection1));
   RunPostedTasks();
@@ -298,8 +307,11 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection2(
       std::make_unique<IndexedDBPendingConnection>(
-          request2, callbacks2, kTestExecutionContext, transaction_id2,
-          kDatabaseVersion, std::move(create_transaction_callback2)));
+          request2, callbacks2,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id2, kDatabaseVersion,
+          std::move(create_transaction_callback2)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection2));
   RunPostedTasks();
@@ -317,8 +329,11 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection3(
       std::make_unique<IndexedDBPendingConnection>(
-          request3, callbacks3, kTestExecutionContext, transaction_id3,
-          kDatabaseVersion, std::move(create_transaction_callback3)));
+          request3, callbacks3,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id3, kDatabaseVersion,
+          std::move(create_transaction_callback3)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection3));
   RunPostedTasks();
@@ -350,8 +365,10 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection(
       std::make_unique<IndexedDBPendingConnection>(
-          request1, callbacks1, kTestExecutionContext, transaction_id1,
-          IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+          request1, callbacks1,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
           std::move(create_transaction_callback1)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection));
@@ -387,8 +404,10 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection(
       std::make_unique<IndexedDBPendingConnection>(
-          request1, callbacks1, kTestExecutionContext, transaction_id1,
-          IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+          request1, callbacks1,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
           std::move(create_transaction_callback1)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection));
@@ -407,8 +426,10 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection2(
       std::make_unique<IndexedDBPendingConnection>(
-          request1, callbacks1, kTestExecutionContext, transaction_id2, 3,
-          std::move(create_transaction_callback2)));
+          request1, callbacks1,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id2, 3, std::move(create_transaction_callback2)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection2));
   RunPostedTasks();
@@ -430,11 +451,12 @@
   const int64_t transaction_id1 = 1;
   auto create_transaction_callback1 =
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
-  std::unique_ptr<IndexedDBPendingConnection> connection =
-      std::make_unique<IndexedDBPendingConnection>(
-          request1, callbacks1, kTestExecutionContext, transaction_id1,
-          IndexedDBDatabaseMetadata::DEFAULT_VERSION,
-          std::move(create_transaction_callback1));
+  std::unique_ptr<IndexedDBPendingConnection> connection = std::make_unique<
+      IndexedDBPendingConnection>(
+      request1, callbacks1,
+      IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+      transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+      std::move(create_transaction_callback1));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection));
   RunPostedTasks();
@@ -450,8 +472,10 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   std::unique_ptr<IndexedDBPendingConnection> connection2(
       std::make_unique<IndexedDBPendingConnection>(
-          request1, callbacks1, kTestExecutionContext, transaction_id2, 3,
-          std::move(create_transaction_callback2)));
+          request1, callbacks1,
+          IndexedDBExecutionContextConnectionTracker::Handle::
+              CreateForTesting(),
+          transaction_id2, 3, std::move(create_transaction_callback2)));
   db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                               std::move(connection2));
   RunPostedTasks();
@@ -507,8 +531,10 @@
         base::BindOnce(&CreateAndBindTransactionPlaceholder);
     std::unique_ptr<IndexedDBPendingConnection> connection(
         std::make_unique<IndexedDBPendingConnection>(
-            request_, callbacks_, kTestExecutionContext, transaction_id,
-            IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+            request_, callbacks_,
+            IndexedDBExecutionContextConnectionTracker::Handle::
+                CreateForTesting(),
+            transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
             std::move(create_transaction_callback1)));
     db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(),
                                 std::move(connection));
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index d4799ba..8a5794b 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -19,7 +19,6 @@
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_cursor.h"
 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
-#include "content/browser/indexed_db/indexed_db_execution_context.h"
 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
 #include "content/browser/indexed_db/indexed_db_pending_connection.h"
 #include "content/browser/indexed_db/transaction_impl.h"
@@ -88,7 +87,9 @@
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(render_process_id, ipc_process_id_);
-  receivers_.Add(this, std::move(pending_receiver), {origin, render_frame_id});
+  receivers_.Add(this, std::move(pending_receiver),
+                 {origin, IndexedDBExecutionContextConnectionTracker(
+                              render_process_id, render_frame_id)});
 }
 
 void IndexedDBDispatcherHost::AddDatabaseBinding(
@@ -194,12 +195,10 @@
   auto create_transaction_callback = base::BindOnce(
       &IndexedDBDispatcherHost::CreateAndBindTransactionImpl, AsWeakPtr(),
       std::move(transaction_receiver), context.origin);
-  const IndexedDBExecutionContext execution_context(ipc_process_id_,
-                                                    context.render_frame_id);
   std::unique_ptr<IndexedDBPendingConnection> connection =
       std::make_unique<IndexedDBPendingConnection>(
           std::move(callbacks), std::move(database_callbacks),
-          execution_context, transaction_id, version,
+          context.connection_tracker.CreateHandle(), transaction_id, version,
           std::move(create_transaction_callback));
   // TODO(dgrogan): Don't let a non-existing database be opened (and therefore
   // created) if this origin is already over quota.
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h
index cd0b153..c5b2c3e 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -18,6 +18,7 @@
 #include "base/sequence_checker.h"
 #include "base/strings/string16.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host_observer.h"
@@ -141,9 +142,9 @@
   // State for each client held in |receivers_|.
   struct ReceiverState {
     url::Origin origin;
-    // The frame identifier, or MSG_ROUTING_NONE if this describes a worker
-    // (this means that dedicated/shared/service workers are not distinguished).
-    int render_frame_id;
+
+    // Tracks connections for this receiver.
+    IndexedDBExecutionContextConnectionTracker connection_tracker;
   };
 
   mojo::ReceiverSet<blink::mojom::IDBFactory, ReceiverState> receivers_;
diff --git a/content/browser/indexed_db/indexed_db_execution_context.h b/content/browser/indexed_db/indexed_db_execution_context.h
deleted file mode 100644
index b3aa968..0000000
--- a/content/browser/indexed_db/indexed_db_execution_context.h
+++ /dev/null
@@ -1,26 +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 CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_EXECUTION_CONTEXT_H_
-#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_EXECUTION_CONTEXT_H_
-
-namespace content {
-
-// Identifies the frame or worker holding an IndexedDB object.
-struct IndexedDBExecutionContext {
-  constexpr IndexedDBExecutionContext(int render_process_id,
-                                      int render_frame_id)
-      : render_process_id(render_process_id),
-        render_frame_id(render_frame_id) {}
-
-  // The process hosting the frame or worker.
-  const int render_process_id;
-
-  // The frame id, or MSG_ROUTING_NONE if this identifies a worker.
-  const int render_frame_id;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_EXECUTION_CONTEXT_H_
diff --git a/content/browser/indexed_db/indexed_db_execution_context_connection_tracker.cc b/content/browser/indexed_db/indexed_db_execution_context_connection_tracker.cc
new file mode 100644
index 0000000..b095b14
--- /dev/null
+++ b/content/browser/indexed_db/indexed_db_execution_context_connection_tracker.cc
@@ -0,0 +1,84 @@
+// 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 "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
+
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/lock_observer.h"
+#include "content/public/common/content_client.h"
+
+namespace content {
+
+namespace {
+
+LockObserver* GetLockObserver() {
+  return GetContentClient()->browser()->GetLockObserver();
+}
+
+}  // namespace
+
+IndexedDBExecutionContextConnectionTracker::Handle::Handle(
+    scoped_refptr<State> state)
+    : state_(std::move(state)) {
+  DCHECK(state_);
+  int prev_num_connections = state_->num_connections++;
+  if (state_->IsFrame() && prev_num_connections == 0) {
+    LockObserver* lock_observer = GetLockObserver();
+    if (lock_observer) {
+      lock_observer->OnFrameStartsHoldingIndexedDBConnections(
+          state_->render_process_id, state_->render_frame_id);
+    }
+  }
+}
+
+IndexedDBExecutionContextConnectionTracker::Handle::Handle(Handle&& other) =
+    default;
+
+IndexedDBExecutionContextConnectionTracker::Handle&
+IndexedDBExecutionContextConnectionTracker::Handle::operator=(Handle&& other) =
+    default;
+
+IndexedDBExecutionContextConnectionTracker::Handle::~Handle() {
+  if (state_ && state_->IsFrame()) {
+    DCHECK_GT(state_->num_connections, 0);
+    --state_->num_connections;
+    if (state_->num_connections == 0) {
+      LockObserver* lock_observer = GetLockObserver();
+      if (lock_observer) {
+        lock_observer->OnFrameStopsHoldingIndexedDBConnections(
+            state_->render_process_id, state_->render_frame_id);
+      }
+    }
+  }
+}
+
+// static
+IndexedDBExecutionContextConnectionTracker::Handle
+IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting() {
+  return Handle(
+      base::MakeRefCounted<State>(MSG_ROUTING_NONE, MSG_ROUTING_NONE));
+}
+
+IndexedDBExecutionContextConnectionTracker::
+    IndexedDBExecutionContextConnectionTracker(int render_process_id,
+                                               int render_frame_id)
+    : state_(base::MakeRefCounted<State>(render_process_id, render_frame_id)) {}
+
+IndexedDBExecutionContextConnectionTracker::
+    IndexedDBExecutionContextConnectionTracker(
+        IndexedDBExecutionContextConnectionTracker&& other) = default;
+
+IndexedDBExecutionContextConnectionTracker::
+    ~IndexedDBExecutionContextConnectionTracker() {}
+
+IndexedDBExecutionContextConnectionTracker::Handle
+IndexedDBExecutionContextConnectionTracker::CreateHandle() const {
+  return Handle(state_);
+}
+
+IndexedDBExecutionContextConnectionTracker::State::State(int render_process_id,
+                                                         int render_frame_id)
+    : render_process_id(render_process_id), render_frame_id(render_frame_id) {}
+
+}  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h b/content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h
new file mode 100644
index 0000000..2d74c6c
--- /dev/null
+++ b/content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h
@@ -0,0 +1,102 @@
+// 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 CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_EXECUTION_CONTEXT_CONNECTION_TRACKER_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_EXECUTION_CONTEXT_CONNECTION_TRACKER_H_
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_message.h"
+
+namespace content {
+
+// Tracks the number of connections (pending or active) for an execution
+// context. Notifies content::LockObserver when the number switches between zero
+// and non-zero.
+//
+// There should be one IndexedDBExecutionContextConnectionTracker per execution
+// context that uses IndexedDB. Each connection (pending or active) should own a
+// Handle obtained from that IndexedDBExecutionContextConnectionTracker.
+//
+// TODO(https://crbug.com/980533): Currently, this only notifies LockObserver
+// for connections held by frame. We should also notify for connections held by
+// worker. This requires finding a unique type to identify a frame or a worker.
+class CONTENT_EXPORT IndexedDBExecutionContextConnectionTracker {
+ private:
+  struct State;
+
+ public:
+  // Each connection (pending or active) should own a non-null Handle that
+  // allows keeping track of the number of connections for the parent execution
+  // context.
+  class CONTENT_EXPORT Handle {
+   public:
+    Handle(scoped_refptr<State> state);
+    Handle(Handle&& other);
+    Handle& operator=(Handle&& other);
+    ~Handle();
+
+    // Creates a dummy non-null Handle for testing.
+    static Handle CreateForTesting();
+
+    // Returns true if this Handle is null. A connection should be associated
+    // with a non-null Handle.
+    bool is_null() const { return !state_; }
+
+    // Returns the routing id of the process hosting the execution context for
+    // which this Handle tracks connections.
+    int render_process_id() const {
+      DCHECK(!is_null());
+      return state_->render_process_id;
+    }
+
+   private:
+    scoped_refptr<State> state_;
+
+    Handle(const Handle&) = delete;
+    Handle& operator=(const Handle& other) = delete;
+  };
+
+  // |render_process_id| identifies the process hosting the execution context.
+  // |render_frame_id| identifies the frame if the execution context is a frame,
+  // or is MSG_ROUTING_NONE if the execution context is a worker.
+  IndexedDBExecutionContextConnectionTracker(int render_process_id,
+                                             int render_frame_id);
+
+  IndexedDBExecutionContextConnectionTracker(
+      IndexedDBExecutionContextConnectionTracker&& other);
+
+  ~IndexedDBExecutionContextConnectionTracker();
+
+  // Creates a handle that will be owned by a connection (pending or active) in
+  // the execution context.
+  Handle CreateHandle() const;
+
+ private:
+  struct State : public base::RefCounted<State> {
+    State(int render_process_id, int render_frame_id);
+
+    bool IsFrame() const { return render_frame_id != MSG_ROUTING_NONE; }
+
+    const int render_process_id;
+    const int render_frame_id;
+    int num_connections = 0;
+
+   private:
+    friend class base::RefCounted<State>;
+    ~State() = default;
+  };
+
+  scoped_refptr<State> state_;
+
+  IndexedDBExecutionContextConnectionTracker(
+      const IndexedDBExecutionContextConnectionTracker&) = delete;
+  IndexedDBExecutionContextConnectionTracker& operator=(
+      const IndexedDBExecutionContextConnectionTracker& other) = delete;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_EXECUTION_CONTEXT_CONNECTION_TRACKER_H_
diff --git a/content/browser/indexed_db/indexed_db_execution_context_connection_tracker_browsertest.cc b/content/browser/indexed_db/indexed_db_execution_context_connection_tracker_browsertest.cc
new file mode 100644
index 0000000..9d6f1d3
--- /dev/null
+++ b/content/browser/indexed_db/indexed_db_execution_context_connection_tracker_browsertest.cc
@@ -0,0 +1,347 @@
+// 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 "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
+
+#include "base/macros.h"
+#include "base/test/test_timeouts.h"
+#include "build/build_config.h"
+#include "components/network_session_configurator/common/network_switches.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/lock_observer.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
+
+namespace content {
+
+namespace {
+
+void RunLoopWithTimeout() {
+  base::RunLoop run_loop;
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
+  run_loop.Run();
+}
+
+class TestBrowserClient : public ContentBrowserClient {
+ public:
+  explicit TestBrowserClient(LockObserver* lock_observer)
+      : lock_observer_(lock_observer) {}
+  ~TestBrowserClient() override = default;
+
+  LockObserver* GetLockObserver() override { return lock_observer_; }
+
+ private:
+  LockObserver* const lock_observer_;
+
+  TestBrowserClient(const TestBrowserClient&) = delete;
+  TestBrowserClient& operator=(const TestBrowserClient&) = delete;
+};
+
+class MockObserver : public LockObserver {
+ public:
+  MockObserver() = default;
+  ~MockObserver() = default;
+
+  // LockObserver:
+  MOCK_METHOD2(OnFrameStartsHoldingWebLocks,
+               void(int render_process_id, int render_frame_id));
+  MOCK_METHOD2(OnFrameStopsHoldingWebLocks,
+               void(int render_process_id, int render_frame_id));
+  MOCK_METHOD2(OnFrameStartsHoldingIndexedDBConnections,
+               void(int render_process_id, int render_frame_id));
+  MOCK_METHOD2(OnFrameStopsHoldingIndexedDBConnections,
+               void(int render_process_id, int render_frame_id));
+};
+
+class IndexedDBExecutionContextConnectionTrackerBrowserTest
+    : public ContentBrowserTest {
+ public:
+  IndexedDBExecutionContextConnectionTrackerBrowserTest() = default;
+  ~IndexedDBExecutionContextConnectionTrackerBrowserTest() override = default;
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ContentBrowserTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
+  }
+
+  void SetUpOnMainThread() override {
+    ContentBrowserTest::SetUpOnMainThread();
+
+    // TODO(https://crbug.com/1011765): Navigation fails on Android Kit Kat.
+    if (!ShouldRunTest())
+      return;
+
+    original_client_ = SetBrowserClientForTesting(&test_browser_client_);
+
+    host_resolver()->AddRule("*", "127.0.0.1");
+    server_.ServeFilesFromSourceDirectory(GetTestDataFilePath());
+    ASSERT_TRUE(server_.Start());
+
+    ASSERT_TRUE(NavigateToURL(shell(), GetTestURL("a.com")));
+  }
+
+  void TearDownOnMainThread() override {
+    ContentBrowserTest::TearDownOnMainThread();
+    if (original_client_)
+      SetBrowserClientForTesting(original_client_);
+  }
+
+  bool ShouldRunTest() const {
+#if defined(OS_ANDROID)
+    // Don't run the test if we couldn't override BrowserClient. It happens only
+    // on Android Kitkat or older systems.
+    if (!original_client_)
+      return false;
+
+    // TODO(https://crbug.com/1011765): Navigation fails on Android Kit Kat.
+    if (base::android::BuildInfo::GetInstance()->sdk_int() <=
+        base::android::SDK_VERSION_KITKAT) {
+      return false;
+    }
+#endif
+    return true;
+  }
+
+  GURL GetTestURL(const std::string& hostname) const {
+    return server_.GetURL(hostname,
+                          "/indexeddb/open_connection/open_connection.html");
+  }
+
+  testing::StrictMock<MockObserver> mock_observer_;
+
+ private:
+  net::EmbeddedTestServer server_{net::EmbeddedTestServer::TYPE_HTTPS};
+  ContentBrowserClient* original_client_ = nullptr;
+  TestBrowserClient test_browser_client_{&mock_observer_};
+
+  IndexedDBExecutionContextConnectionTrackerBrowserTest(
+      const IndexedDBExecutionContextConnectionTrackerBrowserTest&) = delete;
+  IndexedDBExecutionContextConnectionTrackerBrowserTest& operator=(
+      const IndexedDBExecutionContextConnectionTrackerBrowserTest&) = delete;
+};
+
+bool OpenConnectionA(RenderFrameHost* rfh) {
+  return EvalJs(rfh, R"(
+      (async () => {
+        return await OpenConnection('A');
+      }) ();
+  )")
+      .ExtractBool();
+}
+
+bool OpenConnectionB(RenderFrameHost* rfh) {
+  return EvalJs(rfh, R"(
+      (async () => {
+        return await OpenConnection('B');
+      }) ();
+  )")
+      .ExtractBool();
+}
+
+}  // namespace
+
+// Verify that content::LockObserver is notified when a frame opens/closes an
+// IndexedDB connection.
+IN_PROC_BROWSER_TEST_F(IndexedDBExecutionContextConnectionTrackerBrowserTest,
+                       ObserverSingleConnection) {
+  if (!ShouldRunTest())
+    return;
+
+  RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+  int frame_id = rfh->GetRoutingID();
+  int process_id = rfh->GetProcess()->GetID();
+
+  {
+    // Open a connection. Expect observer notification.
+    base::RunLoop run_loop;
+    EXPECT_CALL(mock_observer_,
+                OnFrameStartsHoldingIndexedDBConnections(process_id, frame_id))
+        .WillOnce([&](int, int) { run_loop.Quit(); });
+    EXPECT_TRUE(OpenConnectionA(rfh));
+    // Quit when OnFrameStartsHoldingIndexedDBConnections(process_id, frame_id)
+    // is invoked.
+    run_loop.Run();
+  }
+
+  {
+    // Close the connection. Expect observer notification.
+    base::RunLoop run_loop;
+    EXPECT_CALL(mock_observer_,
+                OnFrameStopsHoldingIndexedDBConnections(process_id, frame_id))
+        .WillOnce([&](int, int) { run_loop.Quit(); });
+    EXPECT_TRUE(ExecJs(rfh, "CloseConnection('A');"));
+    // Quit when OnFrameStopsHoldingIndexedDBConnections(process_id, frame_id)
+    // is invoked.
+    run_loop.Run();
+  }
+}
+
+// Verify that content::LockObserver is notified when a frame opens multiple
+// IndexedDB connections (notifications only when the number of held connections
+// switches between zero and non-zero).
+IN_PROC_BROWSER_TEST_F(IndexedDBExecutionContextConnectionTrackerBrowserTest,
+                       ObserverTwoLocks) {
+  if (!ShouldRunTest())
+    return;
+
+  RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+  int frame_id = rfh->GetRoutingID();
+  int process_id = rfh->GetProcess()->GetID();
+
+  {
+    // Open a connection. Expect observer notification.
+    base::RunLoop run_loop;
+    EXPECT_CALL(mock_observer_,
+                OnFrameStartsHoldingIndexedDBConnections(process_id, frame_id))
+        .WillOnce([&](int, int) { run_loop.Quit(); });
+    EXPECT_TRUE(OpenConnectionA(rfh));
+    // Quit when OnFrameStartsHoldingIndexedDBConnections(process_id, frame_id)
+    // is invoked.
+    run_loop.Run();
+  }
+
+  // Open a second connection. Don't expect a notification.
+  EXPECT_TRUE(OpenConnectionB(rfh));
+  // Wait a short timeout to make sure that the observer is not notified.
+  RunLoopWithTimeout();
+
+  // Close the connection. Don't expect a notification.
+  EXPECT_TRUE(ExecJs(rfh, "CloseConnection('B');"));
+  // Wait a short timeout to make sure that the observer is not notified.
+  RunLoopWithTimeout();
+
+  {
+    // Close the connection. Expect observer notification.
+    base::RunLoop run_loop;
+    EXPECT_CALL(mock_observer_,
+                OnFrameStopsHoldingIndexedDBConnections(process_id, frame_id))
+        .WillOnce([&](int, int) { run_loop.Quit(); });
+    EXPECT_TRUE(ExecJs(rfh, "CloseConnection('A');"));
+    // Quit when OnFrameStopsHoldingIndexedDBConnections(process_id, frame_id)
+    // is invoked.
+    run_loop.Run();
+  }
+}
+
+// Verify that content::LockObserver is notified when a frame with active
+// IndexedDB connections is navigated away.
+IN_PROC_BROWSER_TEST_F(IndexedDBExecutionContextConnectionTrackerBrowserTest,
+                       ObserverNavigate) {
+  if (!ShouldRunTest())
+    return;
+
+  RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+  int frame_id = rfh->GetRoutingID();
+  int process_id = rfh->GetProcess()->GetID();
+
+  {
+    // Open a connection. Expect observer notification.
+    base::RunLoop run_loop;
+    EXPECT_CALL(mock_observer_,
+                OnFrameStartsHoldingIndexedDBConnections(process_id, frame_id))
+        .WillOnce([&](int, int) { run_loop.Quit(); });
+    EXPECT_TRUE(OpenConnectionA(rfh));
+    // Quit when OnFrameStartsHoldingIndexedDBConnections(process_id, frame_id)
+    // is invoked.
+    run_loop.Run();
+  }
+
+  {
+    // Navigate away. Expect observer notification.
+    base::RunLoop run_loop;
+    EXPECT_CALL(mock_observer_,
+                OnFrameStopsHoldingIndexedDBConnections(process_id, frame_id))
+        .WillOnce([&](int, int) { run_loop.Quit(); });
+    EXPECT_TRUE(NavigateToURL(shell(), GetTestURL("b.com")));
+    // Quit when OnFrameStopsHoldingIndexedDBConnections(process_id, frame_id)
+    // is invoked.
+    run_loop.Run();
+  }
+}
+
+// Verify that content::LockObserver is *not* notified when a dedicated worker
+// opens/closes an IndexedDB connection.
+IN_PROC_BROWSER_TEST_F(IndexedDBExecutionContextConnectionTrackerBrowserTest,
+                       ObserverDedicatedWorker) {
+  if (!ShouldRunTest())
+    return;
+
+  RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+
+  // Use EvalJs() instead of ExecJs() to ensure that this doesn't return before
+  // the lock is acquired and released by the worker.
+  EXPECT_TRUE(EvalJs(rfh, R"(
+      (async () => {
+        await OpenConnectionFromDedicatedWorker();
+        return true;
+      }) ();
+  )")
+                  .ExtractBool());
+
+  // Wait a short timeout to make sure that the observer is not notified.
+  RunLoopWithTimeout();
+}
+
+// SharedWorkers are not enabled on Android. https://crbug.com/154571
+#if !defined(OS_ANDROID)
+// Verify that content::LockObserver is *not* notified when a shared worker
+// opens/closes an IndexedDB connection.
+IN_PROC_BROWSER_TEST_F(IndexedDBExecutionContextConnectionTrackerBrowserTest,
+                       ObserverSharedWorker) {
+  if (!ShouldRunTest())
+    return;
+
+  RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+
+  // Use EvalJs() instead of ExecJs() to ensure that this doesn't return before
+  // the lock is acquired and released by the worker.
+  EXPECT_TRUE(EvalJs(rfh, R"(
+      (async () => {
+        await OpenConnectionFromSharedWorker();
+        return true;
+      }) ();
+  )")
+                  .ExtractBool());
+
+  // Wait a short timeout to make sure that the observer is not notified.
+  RunLoopWithTimeout();
+}
+#endif  // !defined(OS_ANDROID)
+
+// Verify that content::LockObserver is *not* notified when a service worker
+// opens/closes an IndexedDB connection.
+IN_PROC_BROWSER_TEST_F(IndexedDBExecutionContextConnectionTrackerBrowserTest,
+                       ObserverServiceWorker) {
+  if (!ShouldRunTest())
+    return;
+
+  RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+
+  // Use EvalJs() instead of ExecJs() to ensure that this doesn't return before
+  // the lock is acquired and released by the worker.
+  EXPECT_TRUE(EvalJs(rfh, R"(
+      (async () => {
+        await OpenConnectionFromServiceWorker();
+        return true;
+      }) ();
+  )")
+                  .ExtractBool());
+
+  // Wait a short timeout to make sure that the observer is not notified.
+  RunLoopWithTimeout();
+}
+
+}  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_execution_context_connection_tracker_unittest.cc b/content/browser/indexed_db/indexed_db_execution_context_connection_tracker_unittest.cc
new file mode 100644
index 0000000..a3c6d38
--- /dev/null
+++ b/content/browser/indexed_db/indexed_db_execution_context_connection_tracker_unittest.cc
@@ -0,0 +1,167 @@
+// 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 "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
+
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/lock_observer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace content {
+
+namespace {
+
+class TestBrowserClient : public ContentBrowserClient {
+ public:
+  explicit TestBrowserClient(LockObserver* lock_observer)
+      : lock_observer_(lock_observer) {}
+  ~TestBrowserClient() override = default;
+
+  LockObserver* GetLockObserver() override { return lock_observer_; }
+
+ private:
+  LockObserver* const lock_observer_;
+
+  TestBrowserClient(const TestBrowserClient&) = delete;
+  TestBrowserClient& operator=(const TestBrowserClient&) = delete;
+};
+
+class MockObserver : public LockObserver {
+ public:
+  MockObserver() = default;
+  ~MockObserver() = default;
+
+  // LockObserver:
+  MOCK_METHOD2(OnFrameStartsHoldingWebLocks,
+               void(int render_process_id, int render_frame_id));
+  MOCK_METHOD2(OnFrameStopsHoldingWebLocks,
+               void(int render_process_id, int render_frame_id));
+  MOCK_METHOD2(OnFrameStartsHoldingIndexedDBConnections,
+               void(int render_process_id, int render_frame_id));
+  MOCK_METHOD2(OnFrameStopsHoldingIndexedDBConnections,
+               void(int render_process_id, int render_frame_id));
+};
+
+constexpr int kTestRenderProcessId = 4;
+constexpr int kTestRenderFrameId = 2;
+
+class IndexedDBExecutionContextConnectionTrackerTest : public testing::Test {
+ protected:
+  IndexedDBExecutionContextConnectionTrackerTest() = default;
+
+  void SetUp() {
+    testing::Test::SetUp();
+    original_client_ = SetBrowserClientForTesting(&test_browser_client_);
+  }
+
+  void TearDown() {
+    SetBrowserClientForTesting(original_client_);
+    testing::Test::TearDown();
+  }
+
+  testing::StrictMock<MockObserver> observer_;
+
+ private:
+  TestBrowserClient test_browser_client_{&observer_};
+  ContentBrowserClient* original_client_ = nullptr;
+};
+
+}  // namespace
+
+TEST_F(IndexedDBExecutionContextConnectionTrackerTest, SingleHandle) {
+  IndexedDBExecutionContextConnectionTracker tracker(kTestRenderProcessId,
+                                                     kTestRenderFrameId);
+
+  {
+    // Expect a notification that the execution context started holding
+    // connections when the first handle is created.
+    EXPECT_CALL(observer_, OnFrameStartsHoldingIndexedDBConnections(
+                               kTestRenderProcessId, kTestRenderFrameId));
+    IndexedDBExecutionContextConnectionTracker::Handle handle =
+        tracker.CreateHandle();
+    testing::Mock::VerifyAndClear(&observer_);
+
+    // Expect a notification that the execution context stopped holding
+    // connections when the handle goes out of scope.
+    EXPECT_CALL(observer_, OnFrameStopsHoldingIndexedDBConnections(
+                               kTestRenderProcessId, kTestRenderFrameId));
+  }
+  testing::Mock::VerifyAndClear(&observer_);
+}
+
+TEST_F(IndexedDBExecutionContextConnectionTrackerTest, TwoHandles) {
+  IndexedDBExecutionContextConnectionTracker tracker(kTestRenderProcessId,
+                                                     kTestRenderFrameId);
+
+  {
+    // Expect a notification that the execution context started holding
+    // connections when the first handle is created.
+    EXPECT_CALL(observer_, OnFrameStartsHoldingIndexedDBConnections(
+                               kTestRenderProcessId, kTestRenderFrameId));
+    IndexedDBExecutionContextConnectionTracker::Handle handle =
+        tracker.CreateHandle();
+    testing::Mock::VerifyAndClear(&observer_);
+
+    {
+      // Don't expect notifications when a second handle is created and
+      // destroyed.
+      IndexedDBExecutionContextConnectionTracker::Handle other_handle =
+          tracker.CreateHandle();
+    }
+
+    // Expect a notification that the execution context stopped holding
+    // connections when the handle goes out of scope.
+    EXPECT_CALL(observer_, OnFrameStopsHoldingIndexedDBConnections(
+                               kTestRenderProcessId, kTestRenderFrameId));
+  }
+  testing::Mock::VerifyAndClear(&observer_);
+}
+
+TEST_F(IndexedDBExecutionContextConnectionTrackerTest, MoveHandle) {
+  IndexedDBExecutionContextConnectionTracker tracker(kTestRenderProcessId,
+                                                     kTestRenderFrameId);
+  std::unique_ptr<IndexedDBExecutionContextConnectionTracker::Handle>
+      moved_handle;
+
+  {
+    // Expect a notification that the execution context started holding
+    // connections when the first handle is created.
+    EXPECT_CALL(observer_, OnFrameStartsHoldingIndexedDBConnections(
+                               kTestRenderProcessId, kTestRenderFrameId));
+    IndexedDBExecutionContextConnectionTracker::Handle handle =
+        tracker.CreateHandle();
+    testing::Mock::VerifyAndClear(&observer_);
+
+    // Move |handle| to |moved_handle|.
+    moved_handle =
+        std::make_unique<IndexedDBExecutionContextConnectionTracker::Handle>(
+            std::move(handle));
+
+    // Don't expect a notification when |handle| goes out of scope, because it
+    // was moved to |moved_handle|.
+  }
+
+  // Expect a notification that the execution context stopped holding
+  // connections when |moved_handle| is destroyed.
+  EXPECT_CALL(observer_, OnFrameStopsHoldingIndexedDBConnections(
+                             kTestRenderProcessId, kTestRenderFrameId));
+  moved_handle.reset();
+  testing::Mock::VerifyAndClear(&observer_);
+}
+
+TEST_F(IndexedDBExecutionContextConnectionTrackerTest, WorkerHandle) {
+  // Passing MSG_ROUTING_NONE as |render_frame_id| to indicate that this is a
+  // worker execution context.
+  IndexedDBExecutionContextConnectionTracker tracker(kTestRenderProcessId,
+                                                     MSG_ROUTING_NONE);
+
+  {
+    // Don't expect observer notifications when a handle is created and goes out
+    // of scope.
+    IndexedDBExecutionContextConnectionTracker::Handle handle =
+        tracker.CreateHandle();
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index 3b2955c3..2563efc 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -23,7 +23,7 @@
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_data_format_version.h"
-#include "content/browser/indexed_db/indexed_db_execution_context.h"
+#include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
 #include "content/browser/indexed_db/indexed_db_origin_state.h"
 #include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
@@ -60,8 +60,6 @@
 void CreateAndBindTransactionPlaceholder(
     base::WeakPtr<IndexedDBTransaction> transaction) {}
 
-constexpr IndexedDBExecutionContext kTestExecutionContext(4, 2);
-
 }  // namespace
 
 class IndexedDBFactoryTest : public testing::Test {
@@ -150,8 +148,9 @@
     auto create_transaction_callback =
         base::BindOnce(&CreateAndBindTransactionPlaceholder);
     auto connection = std::make_unique<IndexedDBPendingConnection>(
-        callbacks, db_callbacks, kTestExecutionContext, transaction_id,
-        IndexedDBDatabaseMetadata::NO_VERSION,
+        callbacks, db_callbacks,
+        IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+        transaction_id, IndexedDBDatabaseMetadata::NO_VERSION,
         std::move(create_transaction_callback));
 
     // Do the first half of the upgrade, and request the upgrade from renderer.
@@ -449,8 +448,9 @@
   auto create_transaction_callback =
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   auto connection = std::make_unique<IndexedDBPendingConnection>(
-      callbacks, db_callbacks, kTestExecutionContext, transaction_id,
-      IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+      callbacks, db_callbacks,
+      IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+      transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
       std::move(create_transaction_callback));
   factory()->Open(ASCIIToUTF16("db"), std::move(connection), origin,
                   context()->data_path());
@@ -510,8 +510,9 @@
   auto create_transaction_callback =
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   auto connection = std::make_unique<IndexedDBPendingConnection>(
-      callbacks, db_callbacks, kTestExecutionContext, transaction_id,
-      IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+      callbacks, db_callbacks,
+      IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+      transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
       std::move(create_transaction_callback));
   factory()->Open(ASCIIToUTF16("db"), std::move(connection), origin,
                   context()->data_path());
@@ -541,8 +542,9 @@
   auto create_transaction_callback =
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   auto connection = std::make_unique<IndexedDBPendingConnection>(
-      callbacks, db_callbacks, kTestExecutionContext, transaction_id,
-      IndexedDBDatabaseMetadata::NO_VERSION,
+      callbacks, db_callbacks,
+      IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+      transaction_id, IndexedDBDatabaseMetadata::NO_VERSION,
       std::move(create_transaction_callback));
 
   // Do the first half of the upgrade, and request the upgrade from renderer.
@@ -578,8 +580,9 @@
   auto create_transaction_callback =
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   auto connection = std::make_unique<IndexedDBPendingConnection>(
-      callbacks, db_callbacks, kTestExecutionContext, transaction_id,
-      IndexedDBDatabaseMetadata::NO_VERSION,
+      callbacks, db_callbacks,
+      IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+      transaction_id, IndexedDBDatabaseMetadata::NO_VERSION,
       std::move(create_transaction_callback));
 
   // Do the first half of the upgrade, and request the upgrade from renderer.
@@ -717,7 +720,8 @@
   auto create_transaction_callback =
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   auto connection = std::make_unique<IndexedDBPendingConnection>(
-      callbacks, dummy_database_callbacks, kTestExecutionContext,
+      callbacks, dummy_database_callbacks,
+      IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
       /*transaction_id=*/1, /*version=*/1,
       std::move(create_transaction_callback));
   factory()->Open(name, std::move(connection), origin, context()->data_path());
@@ -757,8 +761,9 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
 
   auto connection = std::make_unique<IndexedDBPendingConnection>(
-      callbacks, db_callbacks, kTestExecutionContext, transaction_id,
-      db_version, std::move(create_transaction_callback));
+      callbacks, db_callbacks,
+      IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+      transaction_id, db_version, std::move(create_transaction_callback));
   {
     base::RunLoop loop;
     callbacks->CallOnUpgradeNeeded(
@@ -791,7 +796,8 @@
     auto create_transaction_callback =
         base::BindOnce(&CreateAndBindTransactionPlaceholder);
     auto connection = std::make_unique<IndexedDBPendingConnection>(
-        failed_open_callbacks, db_callbacks2, kTestExecutionContext,
+        failed_open_callbacks, db_callbacks2,
+        IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
         transaction_id, db_version, std::move(create_transaction_callback));
     factory()->Open(db_name, std::move(connection), origin,
                     context()->data_path());
@@ -838,7 +844,9 @@
     auto create_transaction_callback =
         base::BindOnce(&CreateAndBindTransactionPlaceholder);
     auto pending_connection = std::make_unique<IndexedDBPendingConnection>(
-        callbacks, db_callbacks, kTestExecutionContext, transaction_id,
+        callbacks, db_callbacks,
+        IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+        transaction_id,
         /*version=*/1, std::move(create_transaction_callback));
 
     {
diff --git a/content/browser/indexed_db/indexed_db_pending_connection.cc b/content/browser/indexed_db/indexed_db_pending_connection.cc
index cc1c53b..3e11fa2b 100644
--- a/content/browser/indexed_db/indexed_db_pending_connection.cc
+++ b/content/browser/indexed_db/indexed_db_pending_connection.cc
@@ -6,22 +6,28 @@
 
 #include <utility>
 
+#include "base/logging.h"
+
 namespace content {
 
 IndexedDBPendingConnection::IndexedDBPendingConnection(
     scoped_refptr<IndexedDBCallbacks> callbacks,
     scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
-    const IndexedDBExecutionContext& execution_context,
+    IndexedDBExecutionContextConnectionTracker::Handle
+        execution_context_connection_handle,
     int64_t transaction_id,
     int64_t version,
     base::OnceCallback<void(base::WeakPtr<IndexedDBTransaction>)>
         create_transaction_callback)
     : callbacks(callbacks),
       database_callbacks(database_callbacks),
-      execution_context(execution_context),
+      execution_context_connection_handle(
+          std::move(execution_context_connection_handle)),
       transaction_id(transaction_id),
       version(version),
-      create_transaction_callback(std::move(create_transaction_callback)) {}
+      create_transaction_callback(std::move(create_transaction_callback)) {
+  DCHECK(!this->execution_context_connection_handle.is_null());
+}
 
 IndexedDBPendingConnection::~IndexedDBPendingConnection() {}
 
diff --git a/content/browser/indexed_db/indexed_db_pending_connection.h b/content/browser/indexed_db/indexed_db_pending_connection.h
index 21a85bb2..f23a678 100644
--- a/content/browser/indexed_db/indexed_db_pending_connection.h
+++ b/content/browser/indexed_db/indexed_db_pending_connection.h
@@ -12,7 +12,7 @@
 #include "content/browser/indexed_db/indexed_db_callbacks.h"
 #include "content/browser/indexed_db/indexed_db_data_loss_info.h"
 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
-#include "content/browser/indexed_db/indexed_db_execution_context.h"
+#include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
 #include "content/common/content_export.h"
 #include "url/origin.h"
 
@@ -25,7 +25,8 @@
   IndexedDBPendingConnection(
       scoped_refptr<IndexedDBCallbacks> callbacks,
       scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
-      const IndexedDBExecutionContext& execution_context,
+      IndexedDBExecutionContextConnectionTracker::Handle
+          execution_context_connection_handle,
       int64_t transaction_id,
       int64_t version,
       base::OnceCallback<void(base::WeakPtr<IndexedDBTransaction>)>
@@ -33,7 +34,8 @@
   ~IndexedDBPendingConnection();
   scoped_refptr<IndexedDBCallbacks> callbacks;
   scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks;
-  IndexedDBExecutionContext execution_context;
+  IndexedDBExecutionContextConnectionTracker::Handle
+      execution_context_connection_handle;
   int64_t transaction_id;
   int64_t version;
   IndexedDBDataLossInfo data_loss_info;
diff --git a/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/content/browser/indexed_db/indexed_db_transaction_unittest.cc
index 20a896d..4b27a9afa 100644
--- a/content/browser/indexed_db/indexed_db_transaction_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -18,7 +18,7 @@
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_database_error.h"
-#include "content/browser/indexed_db/indexed_db_execution_context.h"
+#include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
@@ -39,8 +39,6 @@
   *value = true;
 }
 
-constexpr IndexedDBExecutionContext kTestExecutionContext(4, 2);
-
 }  // namespace
 
 class AbortObserver {
@@ -121,11 +119,12 @@
   }
 
   std::unique_ptr<IndexedDBConnection> CreateConnection() {
-    auto connection = std::unique_ptr<IndexedDBConnection>(
-        std::make_unique<IndexedDBConnection>(
-            kTestExecutionContext, IndexedDBOriginStateHandle(),
-            IndexedDBClassFactory::Get(), db_->AsWeakPtr(), base::DoNothing(),
-            base::DoNothing(), new MockIndexedDBDatabaseCallbacks()));
+    auto connection = std::unique_ptr<
+        IndexedDBConnection>(std::make_unique<IndexedDBConnection>(
+        IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+        IndexedDBOriginStateHandle(), IndexedDBClassFactory::Get(),
+        db_->AsWeakPtr(), base::DoNothing(), base::DoNothing(),
+        new MockIndexedDBDatabaseCallbacks()));
     db_->AddConnectionForTesting(connection.get());
     return connection;
   }
diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc
index b050e79..5cfb32e3 100644
--- a/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/time/default_clock.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
-#include "content/browser/indexed_db/indexed_db_execution_context.h"
+#include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h"
 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
 #include "content/browser/indexed_db/indexed_db_origin_state.h"
 #include "content/browser/indexed_db/leveldb/leveldb_env.h"
@@ -40,8 +40,6 @@
 namespace content {
 namespace {
 
-constexpr IndexedDBExecutionContext kTestExecutionContext(4, 2);
-
 base::FilePath CreateAndReturnTempDir(base::ScopedTempDir* temp_dir) {
   CHECK(temp_dir->CreateUniqueTempDir());
   return temp_dir->GetPath();
@@ -254,7 +252,9 @@
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   factory->Open(base::ASCIIToUTF16("opendb"),
                 std::make_unique<IndexedDBPendingConnection>(
-                    open_callbacks, open_db_callbacks, kTestExecutionContext,
+                    open_callbacks, open_db_callbacks,
+                    IndexedDBExecutionContextConnectionTracker::Handle::
+                        CreateForTesting(),
                     host_transaction_id, version,
                     std::move(create_transaction_callback1)),
                 kTestOrigin, context()->data_path());
@@ -265,7 +265,9 @@
   factory->Open(base::ASCIIToUTF16("closeddb"),
                 std::make_unique<IndexedDBPendingConnection>(
                     closed_callbacks, closed_db_callbacks,
-                    kTestExecutionContext, host_transaction_id, version,
+                    IndexedDBExecutionContextConnectionTracker::Handle::
+                        CreateForTesting(),
+                    host_transaction_id, version,
                     std::move(create_transaction_callback2)),
                 kTestOrigin, context()->data_path());
   RunPostedTasks();
@@ -319,8 +321,9 @@
   auto create_transaction_callback1 =
       base::BindOnce(&CreateAndBindTransactionPlaceholder);
   auto connection = std::make_unique<IndexedDBPendingConnection>(
-      callbacks, db_callbacks, kTestExecutionContext, transaction_id,
-      IndexedDBDatabaseMetadata::DEFAULT_VERSION,
+      callbacks, db_callbacks,
+      IndexedDBExecutionContextConnectionTracker::Handle::CreateForTesting(),
+      transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
       std::move(create_transaction_callback1));
   factory->Open(base::ASCIIToUTF16("db"), std::move(connection),
                 Origin(kTestOrigin), context()->data_path());
diff --git a/content/browser/keyboard_lock_browsertest.cc b/content/browser/keyboard_lock_browsertest.cc
index 05a707e5..1f11a97 100644
--- a/content/browser/keyboard_lock_browsertest.cc
+++ b/content/browser/keyboard_lock_browsertest.cc
@@ -24,7 +24,7 @@
 #include "content/test/content_browser_test_utils_internal.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
-#include "third_party/blink/public/web/web_fullscreen_options.h"
+#include "third_party/blink/public/common/fullscreen/fullscreen_options.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
 #include "ui/events/keycodes/keyboard_code_conversion.h"
@@ -149,7 +149,7 @@
   void EnterFullscreenModeForTab(
       WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override;
+      const blink::FullScreenOptions& options) override;
   void ExitFullscreenModeForTab(WebContents* web_contents) override;
   bool IsFullscreenForTabOrPending(const WebContents* web_contents) override;
   void RequestKeyboardLock(WebContents* web_contents,
@@ -166,7 +166,7 @@
 void FakeKeyboardLockWebContentsDelegate::EnterFullscreenModeForTab(
     WebContents* web_contents,
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   is_fullscreen_ = true;
   if (keyboard_lock_requested_)
     web_contents->GotResponseToKeyboardLockRequest(/*allowed=*/true);
@@ -348,7 +348,7 @@
 
 void KeyboardLockBrowserTest::EnterFullscreen(const base::Location& from_here,
                                               const GURL& gurl) {
-  web_contents()->EnterFullscreenMode(gurl, blink::WebFullscreenOptions());
+  web_contents()->EnterFullscreenMode(gurl, blink::FullScreenOptions());
 
   ASSERT_TRUE(web_contents()->IsFullscreenForCurrentTab())
       << "Location: " << from_here.ToString();
diff --git a/content/browser/locks/lock_manager_browsertest.cc b/content/browser/locks/lock_manager_browsertest.cc
index 94a9636..558760f 100644
--- a/content/browser/locks/lock_manager_browsertest.cc
+++ b/content/browser/locks/lock_manager_browsertest.cc
@@ -53,6 +53,10 @@
                void(int render_process_id, int render_frame_id));
   MOCK_METHOD2(OnFrameStopsHoldingWebLocks,
                void(int render_process_id, int render_frame_id));
+  MOCK_METHOD2(OnFrameStartsHoldingIndexedDBConnections,
+               void(int render_process_id, int render_frame_id));
+  MOCK_METHOD2(OnFrameStopsHoldingIndexedDBConnections,
+               void(int render_process_id, int render_frame_id));
 };
 
 void RunLoopWithTimeout() {
@@ -71,6 +75,8 @@
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     ContentBrowserTest::SetUpCommandLine(command_line);
+    // This is required to allow navigation to test https:// URLs. Service
+    // workers are not exposed to http:// URLs.
     cert_verifier_.SetUpCommandLine(command_line);
   }
 
diff --git a/content/browser/native_file_system/file_system_chooser_browsertest.cc b/content/browser/native_file_system/file_system_chooser_browsertest.cc
index be94ea4..d90c1bf 100644
--- a/content/browser/native_file_system/file_system_chooser_browsertest.cc
+++ b/content/browser/native_file_system/file_system_chooser_browsertest.cc
@@ -68,7 +68,7 @@
   void EnterFullscreen(GURL url) {
     WebContentsImpl* web_contents_impl =
         static_cast<WebContentsImpl*>(shell()->web_contents());
-    web_contents_impl->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+    web_contents_impl->EnterFullscreenMode(url, blink::FullScreenOptions());
   }
 
   base::FilePath CreateTestFile(const std::string& contents) {
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc
index 56550d4..d44f908 100644
--- a/content/browser/portal/portal_browsertest.cc
+++ b/content/browser/portal/portal_browsertest.cc
@@ -993,10 +993,11 @@
 }
 #endif
 
+// TODO(crbug.com/1010675): Test fails flakily.
 // Touch input transfer is only implemented in the content layer for Aura.
 #if defined(USE_AURA)
 IN_PROC_BROWSER_TEST_F(PortalBrowserTest,
-                       TouchInputTransferAcrossReactivation) {
+                       DISABLED_TouchInputTransferAcrossReactivation) {
   EXPECT_TRUE(NavigateToURL(
       shell(), embedded_test_server()->GetURL(
                    "portal.test",
diff --git a/content/browser/screen_orientation/screen_orientation_provider_unittest.cc b/content/browser/screen_orientation/screen_orientation_provider_unittest.cc
index a4b0c9a..8d214a3 100644
--- a/content/browser/screen_orientation/screen_orientation_provider_unittest.cc
+++ b/content/browser/screen_orientation/screen_orientation_provider_unittest.cc
@@ -63,7 +63,7 @@
   void EnterFullscreenModeForTab(
       WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override {
+      const blink::FullScreenOptions& options) override {
     fullscreened_contents_ = web_contents;
   }
 
@@ -182,7 +182,7 @@
 
   // Simulates entering full screen.
   main_test_rfh()->OnMessageReceived(FrameHostMsg_EnterFullscreen(
-      main_test_rfh()->GetRoutingID(), blink::WebFullscreenOptions()));
+      main_test_rfh()->GetRoutingID(), blink::FullScreenOptions()));
   ASSERT_TRUE(contents()->IsFullscreenForCurrentTab());
 
   base::Optional<ScreenOrientationLockResult> result_2;
@@ -285,7 +285,7 @@
 
   // Simulates entering full screen.
   main_test_rfh()->OnMessageReceived(FrameHostMsg_EnterFullscreen(
-      main_test_rfh()->GetRoutingID(), blink::WebFullscreenOptions()));
+      main_test_rfh()->GetRoutingID(), blink::FullScreenOptions()));
   ASSERT_TRUE(contents()->IsFullscreenForCurrentTab());
 
   base::Optional<ScreenOrientationLockResult> result;
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index ceca07c..5277980 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -4160,8 +4160,9 @@
 
 // Test that HasReceivedUserGesture and HasReceivedUserGestureBeforeNavigation
 // are propagated correctly across origins.
+// Flaky. https://crbug.com/1014175
 IN_PROC_BROWSER_TEST_F(SitePerProcessAutoplayBrowserTest,
-                       PropagateUserGestureFlag) {
+                       DISABLED_PropagateUserGestureFlag) {
   GURL main_url(embedded_test_server()->GetURL(
       "example.com", "/media/autoplay/autoplay-enabled.html"));
   GURL foo_url(embedded_test_server()->GetURL(
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index e18ce79..e9e7bfa6 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2533,7 +2533,7 @@
 
 void WebContentsImpl::EnterFullscreenMode(
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   // This method is being called to enter renderer-initiated fullscreen mode.
   // Make sure any existing fullscreen widget is shut down first.
   RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView();
@@ -3142,7 +3142,7 @@
     if (delegate_ && delegate_->EmbedsFullscreenWidget()) {
       widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
       delegate_->EnterFullscreenModeForTab(this, GURL(),
-                                           blink::WebFullscreenOptions());
+                                           blink::FullScreenOptions());
     } else {
       widget_host_view->InitAsFullscreen(view);
     }
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 47de584..c60ee5225 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -574,7 +574,7 @@
   void GetNFC(mojo::PendingReceiver<device::mojom::NFC> receiver) override;
 #endif
   void EnterFullscreenMode(const GURL& origin,
-                           const blink::WebFullscreenOptions& options) override;
+                           const blink::FullScreenOptions& options) override;
   void ExitFullscreenMode(bool will_cause_resize) override;
   void FullscreenStateChanged(RenderFrameHost* rfh,
                               bool is_fullscreen) override;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index aac23b3..ad7cd58 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -2379,7 +2379,7 @@
   void EnterFullscreenModeForTab(
       WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override {
+      const blink::FullScreenOptions& options) override {
     is_fullscreen_ = true;
   }
 
@@ -2943,7 +2943,7 @@
   EXPECT_TRUE(NavigateToURL(shell(), url));
 
   // alert
-  wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  wc->EnterFullscreenMode(url, blink::FullScreenOptions());
   EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
   std::string script = "alert('hi')";
   test_delegate.WillWaitForDialog();
@@ -2952,7 +2952,7 @@
   EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
 
   // confirm
-  wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  wc->EnterFullscreenMode(url, blink::FullScreenOptions());
   EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
   script = "confirm('hi')";
   test_delegate.WillWaitForDialog();
@@ -2961,7 +2961,7 @@
   EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
 
   // prompt
-  wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  wc->EnterFullscreenMode(url, blink::FullScreenOptions());
   EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
   script = "prompt('hi')";
   test_delegate.WillWaitForDialog();
@@ -2970,7 +2970,7 @@
   EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
 
   // beforeunload
-  wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  wc->EnterFullscreenMode(url, blink::FullScreenOptions());
   EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
   // Disable the hang monitor (otherwise there will be a race between the
   // beforeunload dialog and the beforeunload hang timer) and give the page a
@@ -3014,7 +3014,7 @@
 
   // A dialog from the inner WebContents should make the outer contents lose
   // fullscreen.
-  top_contents->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  top_contents->EnterFullscreenMode(url, blink::FullScreenOptions());
   EXPECT_TRUE(top_contents->IsFullscreenForCurrentTab());
   script = "alert('hi')";
   inner_test_delegate.WillWaitForDialog();
@@ -3030,7 +3030,7 @@
   GURL url("about:blank");
   EXPECT_TRUE(NavigateToURL(shell(), url));
 
-  wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  wc->EnterFullscreenMode(url, blink::FullScreenOptions());
   EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
   wc->RunFileChooser(wc->GetMainFrame(),
                      std::make_unique<MockFileSelectListener>(),
@@ -3047,7 +3047,7 @@
   EXPECT_TRUE(NavigateToURL(shell(), url));
 
   // popup
-  wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  wc->EnterFullscreenMode(url, blink::FullScreenOptions());
   EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
   std::string script = "window.open('', '', 'width=200,height=100')";
   test_delegate.WillWaitForNewContents();
@@ -3075,7 +3075,7 @@
       static_cast<WebContentsImpl*>(test_delegate.last_popup());
 
   // Put the original page into fullscreen.
-  wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  wc->EnterFullscreenMode(url, blink::FullScreenOptions());
   EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
 
   // Have the popup open a popup.
@@ -3105,7 +3105,7 @@
   test_delegate.Wait();
 
   // Put the main contents into fullscreen ...
-  wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  wc->EnterFullscreenMode(url, blink::FullScreenOptions());
   EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
 
   // ... and ensure that a call to window.focus() from it causes loss of
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 09ced62..3f7b9ab 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -348,7 +348,7 @@
   void EnterFullscreenModeForTab(
       WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override {
+      const blink::FullScreenOptions& options) override {
     fullscreened_contents_ = web_contents;
   }
 
@@ -1408,7 +1408,7 @@
   EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
   EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
   orig_rfh->OnMessageReceived(FrameHostMsg_EnterFullscreen(
-      orig_rfh->GetRoutingID(), blink::WebFullscreenOptions()));
+      orig_rfh->GetRoutingID(), blink::FullScreenOptions()));
   EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
   EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));
 
@@ -1447,7 +1447,7 @@
   for (int i = 0; i < 2; ++i) {
     // Toggle fullscreen mode on (as if initiated via IPC from renderer).
     orig_rfh->OnMessageReceived(FrameHostMsg_EnterFullscreen(
-        orig_rfh->GetRoutingID(), blink::WebFullscreenOptions()));
+        orig_rfh->GetRoutingID(), blink::FullScreenOptions()));
     EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
     EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));
 
@@ -1479,7 +1479,7 @@
   EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
   EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
   main_test_rfh()->OnMessageReceived(FrameHostMsg_EnterFullscreen(
-      main_test_rfh()->GetRoutingID(), blink::WebFullscreenOptions()));
+      main_test_rfh()->GetRoutingID(), blink::FullScreenOptions()));
   EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
   EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));
 
diff --git a/content/common/DEPS b/content/common/DEPS
index 5c351c1..f8e1124 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -63,7 +63,7 @@
   "+third_party/blink/public/web/web_device_emulation_params.h",
   "+third_party/blink/public/web/web_drag_status.h",
   "+third_party/blink/public/web/web_frame_owner_properties.h",
-  "+third_party/blink/public/web/web_fullscreen_options.h",
+  "+third_party/blink/public/common/fullscreen/fullscreen_options.h",
   "+third_party/blink/public/web/web_ime_text_span.h",
   "+third_party/blink/public/web/web_media_player_action.h",
   "+third_party/blink/public/web/WebSharedWorkerCreationContextType.h",
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index b5a09976..8b981c5a 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -57,6 +57,7 @@
 #include "third_party/blink/public/common/frame/frame_policy.h"
 #include "third_party/blink/public/common/frame/occlusion_state.h"
 #include "third_party/blink/public/common/frame/user_activation_update_type.h"
+#include "third_party/blink/public/common/fullscreen/fullscreen_options.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
 #include "third_party/blink/public/common/messaging/transferable_message.h"
 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
@@ -72,7 +73,6 @@
 #include "third_party/blink/public/platform/web_scroll_types.h"
 #include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h"
 #include "third_party/blink/public/web/web_frame_owner_properties.h"
-#include "third_party/blink/public/web/web_fullscreen_options.h"
 #include "third_party/blink/public/web/web_media_player_action.h"
 #include "third_party/blink/public/web/web_tree_scope_type.h"
 #include "third_party/blink/public/web/web_triggering_event_info.h"
@@ -181,7 +181,7 @@
   IPC_STRUCT_TRAITS_MEMBER(has_height)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(blink::WebFullscreenOptions)
+IPC_STRUCT_TRAITS_BEGIN(blink::FullScreenOptions)
   IPC_STRUCT_TRAITS_MEMBER(prefers_navigation_bar)
 IPC_STRUCT_TRAITS_END()
 
@@ -1372,7 +1372,7 @@
 
 // Puts the browser into "tab fullscreen" mode for the sending renderer.
 // See the comment in chrome/browser/ui/browser.h for more details.
-IPC_MESSAGE_ROUTED1(FrameHostMsg_EnterFullscreen, blink::WebFullscreenOptions)
+IPC_MESSAGE_ROUTED1(FrameHostMsg_EnterFullscreen, blink::FullScreenOptions)
 
 // Exits the browser from "tab fullscreen" mode for the sending renderer.
 // See the comment in chrome/browser/ui/browser.h for more details.
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/WakeLockTest.java b/content/public/android/javatests/src/org/chromium/content/browser/WakeLockTest.java
index 36eb758..57c1fdb 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/WakeLockTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/WakeLockTest.java
@@ -44,7 +44,7 @@
     }
 
     private void getWakeLock(String type) throws TimeoutException {
-        final String code = "WakeLock.request('" + type + "');";
+        final String code = "navigator.wakeLock.request('" + type + "');";
         JavaScriptUtils.executeJavaScriptAndWaitForResult(mActivityTestRule.getWebContents(), code);
     }
 
diff --git a/content/public/browser/lock_observer.h b/content/public/browser/lock_observer.h
index 473846a..bb46c8e0 100644
--- a/content/public/browser/lock_observer.h
+++ b/content/public/browser/lock_observer.h
@@ -17,15 +17,24 @@
   LockObserver() = default;
   virtual ~LockObserver() = default;
 
-  // Invokes when a frame starts or stops holding Web Locks, i.e. when the
-  // number of Web Locks held switches between zero and non-zero. There is no
-  // guarantee that the frame identified by |render_process_id| and
-  // |render_frame_id| still exists when this is called.
+  // Invoked when the number of Web Locks held by a frame switches between zero
+  // and non-zero. There is no guarantee that the frame identified by
+  // |render_process_id| and |render_frame_id| still exists when this is called.
   virtual void OnFrameStartsHoldingWebLocks(int render_process_id,
                                             int render_frame_id) = 0;
   virtual void OnFrameStopsHoldingWebLocks(int render_process_id,
                                            int render_frame_id) = 0;
 
+  // Invoked when the number of IndexedDB connections (pending or active) in a
+  // frame switches between zero and non-zero. There is no guarantee that the
+  // frame identified by |render_process_id| and |render_frame_id| still exists
+  // when this is called.
+  virtual void OnFrameStartsHoldingIndexedDBConnections(
+      int render_process_id,
+      int render_frame_id) = 0;
+  virtual void OnFrameStopsHoldingIndexedDBConnections(int render_process_id,
+                                                       int render_frame_id) = 0;
+
   LockObserver(const LockObserver&) = delete;
   LockObserver& operator=(const LockObserver&) = delete;
 };
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index dd9fcc8..c761ce5 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -25,12 +25,12 @@
 #include "content/public/common/previews_state.h"
 #include "content/public/common/window_container_type.mojom-forward.h"
 #include "third_party/blink/public/common/frame/blocked_navigation_types.h"
+#include "third_party/blink/public/common/fullscreen/fullscreen_options.h"
 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
 #include "third_party/blink/public/mojom/choosers/color_chooser.mojom-forward.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 #include "third_party/blink/public/platform/web_drag_operation.h"
 #include "third_party/blink/public/platform/web_security_style.h"
-#include "third_party/blink/public/web/web_fullscreen_options.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/gfx/geometry/rect_f.h"
@@ -428,7 +428,7 @@
   virtual void EnterFullscreenModeForTab(
       WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) {}
+      const blink::FullScreenOptions& options) {}
 
   // Called when the renderer puts a tab out of fullscreen mode.
   virtual void ExitFullscreenModeForTab(WebContents*) {}
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 11f3786..d0e2b58 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -404,7 +404,7 @@
 // is only useful for tests.
 const char kEnableServiceBinaryLauncher[] = "enable-service-binary-launcher";
 
-// Enables the Skia benchmarking extension
+// Enables the Skia benchmarking extension.
 const char kEnableSkiaBenchmarking[]        = "enable-skia-benchmarking";
 
 // On platforms that support it, enables smooth scroll animation.
@@ -558,9 +558,12 @@
 // Enables experimental Harmony (ECMAScript 6) features.
 const char kJavaScriptHarmony[]             = "javascript-harmony";
 
-// Specifies the flags passed to JS engine
+// Specifies the flags passed to JS engine.
 const char kJavaScriptFlags[]               = "js-flags";
 
+// Flag to launch tests in the browser process.
+const char kLaunchAsBrowser[] = "as-browser";
+
 // Overrides the Lite Page Subresource host.
 const char kLitePagesServerSubresourceHost[] =
     "litepage-server-subresource-host";
@@ -857,6 +860,9 @@
 // kWaitForDebugger flag passed on or not.
 const char kWaitForDebuggerChildren[]       = "wait-for-debugger-children";
 
+// Flag used by WebUI test runners to wait for debugger to be attached.
+const char kWaitForDebuggerWebUI[] = "wait-for-debugger-webui";
+
 // Set the antialiasing method used for webgl. (none, explicit, implicit, or
 // screenspace)
 const char kWebglAntialiasingMode[] = "webgl-antialiasing-mode";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 856f21b..20acdce1 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -167,6 +167,7 @@
 CONTENT_EXPORT extern const char kIsolateOrigins[];
 CONTENT_EXPORT extern const char kJavaScriptFlags[];
 CONTENT_EXPORT extern const char kJavaScriptHarmony[];
+CONTENT_EXPORT extern const char kLaunchAsBrowser[];
 CONTENT_EXPORT extern const char kLitePagesServerSubresourceHost[];
 CONTENT_EXPORT extern const char kLogGpuControlListDecisions[];
 CONTENT_EXPORT extern const char kLoggingLevel[];
@@ -248,6 +249,7 @@
 CONTENT_EXPORT extern const char kEnableWebRtcStunOrigin[];
 CONTENT_EXPORT extern const char kEnforceWebRtcIPPermissionCheck[];
 CONTENT_EXPORT extern const char kForceWebRtcIPHandlingPolicy[];
+CONTENT_EXPORT extern const char kWaitForDebuggerWebUI[];
 extern const char kWebRtcMaxCaptureFramerate[];
 extern const char kWebRtcMaxCpuConsumptionPercentage[];
 CONTENT_EXPORT extern const char kWebRtcStunProbeTrialParameter[];
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index ef4c3e6..0c99317 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -25,6 +25,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/post_task.h"
+#include "base/test/test_switches.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
@@ -1767,8 +1768,8 @@
 
   DOMMessageQueue message_queue;
 
-  bool should_wait_flag =
-      base::CommandLine::ForCurrentProcess()->HasSwitch(kWaitForDebuggerWebUI);
+  bool should_wait_flag = base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kWaitForDebuggerWebUI);
 
   if (should_wait_flag) {
     ExecuteScriptAsync(
diff --git a/content/public/test/test_launcher.cc b/content/public/test/test_launcher.cc
index fa500d1..a164ef3 100644
--- a/content/public/test/test_launcher.cc
+++ b/content/public/test/test_launcher.cc
@@ -208,7 +208,7 @@
   // tests unless this flag was specified to the browser test executable.
   new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests");
   new_cmd_line.AppendSwitchASCII("gtest_filter", test_name);
-  new_cmd_line.AppendSwitch(kSingleProcessTestsFlag);
+  new_cmd_line.AppendSwitch(switches::kSingleProcessTests);
   return new_cmd_line;
 }
 
@@ -243,14 +243,6 @@
 
 }  // namespace
 
-const char kHelpFlag[]   = "help";
-
-const char kLaunchAsBrowser[] = "as-browser";
-
-const char kSingleProcessTestsFlag[]   = "single_process";
-
-const char kWaitForDebuggerWebUI[] = "wait-for-debugger-webui";
-
 void AppendCommandLineSwitches() {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
 
@@ -273,7 +265,7 @@
   const base::CommandLine* command_line =
       base::CommandLine::ForCurrentProcess();
 
-  if (command_line->HasSwitch(kHelpFlag)) {
+  if (command_line->HasSwitch(switches::kHelpFlag)) {
     PrintUsage();
     return 0;
   }
@@ -310,12 +302,12 @@
   // This needs to be before trying to run tests as otherwise utility processes
   // end up being launched as a test, which leads to rerunning the test.
   if (command_line->HasSwitch(switches::kProcessType) ||
-      command_line->HasSwitch(kLaunchAsBrowser)) {
+      command_line->HasSwitch(switches::kLaunchAsBrowser)) {
     return ContentMain(params);
   }
 #endif
 
-  if (command_line->HasSwitch(kSingleProcessTestsFlag) ||
+  if (command_line->HasSwitch(switches::kSingleProcessTests) ||
       (command_line->HasSwitch(switches::kSingleProcess) &&
        command_line->HasSwitch(base::kGTestFilterFlag)) ||
       command_line->HasSwitch(base::kGTestListTestsFlag) ||
@@ -331,11 +323,12 @@
   TestTimeouts::Initialize();
 
   fprintf(stdout,
-      "IMPORTANT DEBUGGING NOTE: each test is run inside its own process.\n"
-      "For debugging a test inside a debugger, use the\n"
-      "--gtest_filter=<your_test_name> flag along with either\n"
-      "--single_process (to run the test in one launcher/browser process) or\n"
-      "--single-process (to do the above, and also run Chrome in single-"
+          "IMPORTANT DEBUGGING NOTE: each test is run inside its own process.\n"
+          "For debugging a test inside a debugger, use the\n"
+          "--gtest_filter=<your_test_name> flag along with either\n"
+          "--single-process-tests (to run the test in one launcher/browser "
+          "process) or\n"
+          "--single-process (to do the above, and also run Chrome in single-"
           "process mode).\n");
 
   base::debug::VerifyDebugger();
diff --git a/content/public/test/test_launcher.h b/content/public/test/test_launcher.h
index 062640c7..bf733bd 100644
--- a/content/public/test/test_launcher.h
+++ b/content/public/test/test_launcher.h
@@ -21,17 +21,6 @@
 class ContentMainDelegate;
 struct ContentMainParams;
 
-extern const char kEmptyTestName[];
-extern const char kHelpFlag[];
-extern const char kLaunchAsBrowser[];
-extern const char kSingleProcessTestsFlag[];
-
-// Flag that causes only the kEmptyTestName test to be run.
-extern const char kWarmupFlag[];
-
-// Flag used by WebUI test runners to wait for debugger to be attached.
-extern const char kWaitForDebuggerWebUI[];
-
 class TestLauncherDelegate {
  public:
   virtual int RunTestSuite(int argc, char** argv) = 0;
@@ -46,13 +35,13 @@
 
   // Called prior to running each test.
   //
-  // NOTE: this is not called if --single_process is supplied.
+  // NOTE: this is not called if --single-process-tests is supplied.
   virtual void PreRunTest() {}
 
   // Called after running each test. Can modify test result.
   //
-  // NOTE: Just like PreRunTest, this is not called when --single_process is
-  // supplied.
+  // NOTE: Just like PreRunTest, this is not called when --single-process-tests
+  // is supplied.
   virtual void PostRunTest(base::TestResult* result) {}
 
   // Allows a TestLauncherDelegate to do work before the launcher shards test
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 8cdda1a..db30b901 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -5697,8 +5697,7 @@
     render_accessibility_->HandleAccessibilityFindInPageTermination();
 }
 
-void RenderFrameImpl::EnterFullscreen(
-    const blink::WebFullscreenOptions& options) {
+void RenderFrameImpl::EnterFullscreen(const blink::FullScreenOptions& options) {
   Send(new FrameHostMsg_EnterFullscreen(routing_id_, options));
 }
 
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index d90d6f6a..7ea2212 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -834,7 +834,7 @@
                                            const blink::WebNode& end_node,
                                            int end_offset) override;
   void HandleAccessibilityFindInPageTermination() override;
-  void EnterFullscreen(const blink::WebFullscreenOptions& options) override;
+  void EnterFullscreen(const blink::FullScreenOptions& options) override;
   void ExitFullscreen() override;
   void FullscreenStateChanged(bool is_fullscreen) override;
   void SuddenTerminationDisablerChanged(
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index 129cea20..91dab8b 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -23,6 +23,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
+#include "base/test/test_switches.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/app/mojo/mojo_init.h"
@@ -227,7 +228,7 @@
 
   void TearDown() override {
     if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-            kSingleProcessTestsFlag)) {
+            switches::kSingleProcessTests)) {
       // In a single-process mode, we need to avoid destructing mock_process_
       // because it will call _exit(0) and kill the process before the browser
       // side is ready to exit.
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc
index 8f11214..fe66634 100644
--- a/content/shell/browser/shell.cc
+++ b/content/shell/browser/shell.cc
@@ -471,10 +471,9 @@
   PlatformSetIsLoading(source->IsLoading());
 }
 
-void Shell::EnterFullscreenModeForTab(
-    WebContents* web_contents,
-    const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+void Shell::EnterFullscreenModeForTab(WebContents* web_contents,
+                                      const GURL& origin,
+                                      const blink::FullScreenOptions& options) {
   ToggleFullscreenModeForTab(web_contents, true);
 }
 
diff --git a/content/shell/browser/shell.h b/content/shell/browser/shell.h
index cbb7b48d..6147191 100644
--- a/content/shell/browser/shell.h
+++ b/content/shell/browser/shell.h
@@ -153,7 +153,7 @@
   void EnterFullscreenModeForTab(
       WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override;
+      const blink::FullScreenOptions& options) override;
   void ExitFullscreenModeForTab(WebContents* web_contents) override;
   bool IsFullscreenForTabOrPending(const WebContents* web_contents) override;
   blink::mojom::DisplayMode GetDisplayMode(
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 115c59cd..724fa98 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -938,6 +938,7 @@
     "../browser/gpu/in_process_gpu_thread_browsertests.cc",
     "../browser/idle/idle_browsertest.cc",
     "../browser/indexed_db/indexed_db_browsertest.cc",
+    "../browser/indexed_db/indexed_db_execution_context_connection_tracker_browsertest.cc",
     "../browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc",
     "../browser/indexed_db/mock_browsertest_indexed_db_class_factory.h",
     "../browser/isolated_origin_browsertest.cc",
@@ -1639,6 +1640,7 @@
     "../browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc",
     "../browser/indexed_db/indexed_db_database_unittest.cc",
     "../browser/indexed_db/indexed_db_dispatcher_host_unittest.cc",
+    "../browser/indexed_db/indexed_db_execution_context_connection_tracker_unittest.cc",
     "../browser/indexed_db/indexed_db_factory_unittest.cc",
     "../browser/indexed_db/indexed_db_fake_backing_store.cc",
     "../browser/indexed_db/indexed_db_fake_backing_store.h",
diff --git a/content/test/content_browser_test_test.cc b/content/test/content_browser_test_test.cc
index d329ef9..4f5abb0 100644
--- a/content/test/content_browser_test_test.cc
+++ b/content/test/content_browser_test_test.cc
@@ -16,6 +16,7 @@
 #include "base/test/launcher/test_launcher.h"
 #include "base/test/launcher/test_launcher_test_utils.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/test_switches.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -82,7 +83,7 @@
   new_test.AppendSwitchASCII(base::kGTestFilterFlag,
                              "ContentBrowserTest.MANUAL_RendererCrash");
   new_test.AppendSwitch(switches::kRunManualTestsFlag);
-  new_test.AppendSwitch(kSingleProcessTestsFlag);
+  new_test.AppendSwitch(switches::kSingleProcessTests);
 
 #if defined(THREAD_SANITIZER)
   // TSan appears to not be able to report intentional crashes from sandboxed
@@ -123,7 +124,7 @@
   new_test.AppendSwitchASCII(base::kGTestFilterFlag,
                              "ContentBrowserTest.MANUAL_BrowserCrash");
   new_test.AppendSwitch(switches::kRunManualTestsFlag);
-  new_test.AppendSwitch(kSingleProcessTestsFlag);
+  new_test.AppendSwitch(switches::kSingleProcessTests);
   std::string output;
   base::GetAppOutputAndError(new_test, &output);
 
@@ -193,11 +194,11 @@
   // will need to change accordingly.
   std::string file_name = "../../content/test/content_browser_test_test.cc";
   EXPECT_TRUE(base::test_launcher_utils::ValidateTestLocation(
-      val, "MockContentBrowserTest.DISABLED_PassTest", file_name, 152));
+      val, "MockContentBrowserTest.DISABLED_PassTest", file_name, 153));
   EXPECT_TRUE(base::test_launcher_utils::ValidateTestLocation(
-      val, "MockContentBrowserTest.DISABLED_FailTest", file_name, 156));
+      val, "MockContentBrowserTest.DISABLED_FailTest", file_name, 157));
   EXPECT_TRUE(base::test_launcher_utils::ValidateTestLocation(
-      val, "MockContentBrowserTest.DISABLED_CrashTest", file_name, 160));
+      val, "MockContentBrowserTest.DISABLED_CrashTest", file_name, 161));
 
   val = root->FindListKey("per_iteration_data");
   ASSERT_TRUE(val);
diff --git a/content/test/data/indexeddb/open_connection/open_connection.html b/content/test/data/indexeddb/open_connection/open_connection.html
new file mode 100644
index 0000000..46c3861
--- /dev/null
+++ b/content/test/data/indexeddb/open_connection/open_connection.html
@@ -0,0 +1,75 @@
+<title>IndexedDB Open Connection</title>
+<script>
+    var connections = {};
+
+    var next_request_id = 1;
+
+    function OpenConnection(name) {
+      return new Promise(resolve => {
+        let request = window.indexedDB.open(name, 1);
+
+        request.onsuccess = e => {
+          connections[name] = e.target.result;
+          resolve(true);
+        };
+        request.onerror = e => {
+          resolve(false);
+        }
+      });
+    }
+
+    function CloseConnection(name) {
+      connections[name].close();
+      connections[name] = undefined;
+    }
+
+    function OpenConnectionFromDedicatedWorker() {
+      return new Promise(resolve => {
+        const worker = new Worker('open_connection_from_dedicated_worker.js');
+        let data = {op: 'open_connection', rqid: next_request_id++};
+        worker.postMessage(data);
+        const listener = event => {
+          if (event.data.rqid !== data.rqid)
+            return;
+          worker.onmessage = undefined;
+          resolve(event.data.result);
+        };
+        worker.onmessage = listener;
+      });
+    }
+
+    function OpenConnectionFromSharedWorker() {
+      return new Promise(resolve => {
+        const worker = new SharedWorker(
+            'open_connection_from_shared_worker.js');
+        let data = {op: 'open_connection', rqid: next_request_id++};
+        worker.port.postMessage(data);
+        const listener = event => {
+          if (event.data.rqid !== data.rqid)
+            return;
+          worker.port.onmessage = undefined;
+          resolve(event.data.result);
+        };
+        worker.port.onmessage = listener;
+      });
+    }
+
+    function OpenConnectionFromServiceWorker() {
+      return new Promise(async resolve => {
+        await navigator.serviceWorker.register(
+            'open_connection_from_service_worker.js');
+        registration = await navigator.serviceWorker.ready;
+
+        var message_channel = new MessageChannel();
+        message_channel.port1.onmessage = event => {
+          if (event.data.rqid !== data.rqid)
+            return;
+          message_channel.port1.onmessage = undefined;
+          resolve(event.data.result);
+        }
+        let data = {op: 'open_connection', rqid: next_request_id++};
+       registration.active.postMessage(
+            data, [message_channel.port2]);
+      });
+    }
+</script>
diff --git a/content/test/data/indexeddb/open_connection/open_connection_from_dedicated_worker.js b/content/test/data/indexeddb/open_connection/open_connection_from_dedicated_worker.js
new file mode 100644
index 0000000..035c0a8
--- /dev/null
+++ b/content/test/data/indexeddb/open_connection/open_connection_from_dedicated_worker.js
@@ -0,0 +1,24 @@
+// 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.
+
+'use strict';
+
+self.onmessage = async function(e) {
+  let connected;
+  let connected_promise = new Promise(r => { connected = r; });
+  let request = indexedDB.open("Foo", 1);
+
+  request.onsuccess = e => {
+    connected(e.target.result);
+  };
+  request.onerror = e => {
+    connected(undefined);
+  }
+
+  let connection = await connected_promise;
+  if (connection)
+    connection.close();
+
+  self.postMessage({rqid: e.data.rqid, result: connection != undefined});
+};
diff --git a/content/test/data/indexeddb/open_connection/open_connection_from_service_worker.js b/content/test/data/indexeddb/open_connection/open_connection_from_service_worker.js
new file mode 100644
index 0000000..53f3098
--- /dev/null
+++ b/content/test/data/indexeddb/open_connection/open_connection_from_service_worker.js
@@ -0,0 +1,24 @@
+// 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.
+
+'use strict';
+
+self.onmessage = async function(e) {
+  let connected;
+  let connected_promise = new Promise(r => { connected = r; });
+  let request = indexedDB.open("Foo", 1);
+
+  request.onsuccess = e => {
+    connected(e.target.result);
+  };
+  request.onerror = e => {
+    connected(undefined);
+  }
+
+  let connection = await connected_promise;
+  if (connection)
+    connection.close();
+
+  e.ports[0].postMessage({rqid: e.data.rqid, result: connection != undefined});
+};
diff --git a/content/test/data/indexeddb/open_connection/open_connection_from_shared_worker.js b/content/test/data/indexeddb/open_connection/open_connection_from_shared_worker.js
new file mode 100644
index 0000000..d1e76304
--- /dev/null
+++ b/content/test/data/indexeddb/open_connection/open_connection_from_shared_worker.js
@@ -0,0 +1,29 @@
+// 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.
+
+'use strict';
+
+onconnect = function(e) {
+  var port = e.ports[0];
+
+  port.onmessage = async function(e) {
+    let connected;
+    let connected_promise = new Promise(r => { connected = r; });
+    let request = indexedDB.open("Foo", 1);
+
+    request.onsuccess = e => {
+      connected(e.target.result);
+    };
+    request.onerror = e => {
+      connected(undefined);
+    }
+
+    let connection = await connected_promise;
+    if (connection)
+      connection.close();
+
+    port.postMessage({rqid: e.data.rqid, result: connection != undefined});
+  }
+
+}
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index cdf7a9a..6a4b7c5 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -53,9 +53,6 @@
 
 crbug.com/949249 [ passthrough ] conformance2/extensions/ovr_multiview2.html [ Failure ]
 
-# Marking a test as failing on all platforms.
-crbug.com/985032 conformance2/glsl3/sampler-array-indexing.html [ Failure ]
-
 # Failing new test
 crbug.com/874620 [ linux nvidia ] conformance2/glsl3/const-struct-from-array-as-function-parameter.html [ Failure ]
 crbug.com/874620 [ opengl win nvidia ] conformance2/glsl3/const-struct-from-array-as-function-parameter.html [ Failure ]
diff --git a/docs/linux_debugging.md b/docs/linux_debugging.md
index 36e35da..430778e 100644
--- a/docs/linux_debugging.md
+++ b/docs/linux_debugging.md
@@ -332,10 +332,10 @@
 browser side of a single test, use a command like
 
 ```
-gdb --args out/Debug/browser_tests --single_process --gtest_filter=MyTestName
+gdb --args out/Debug/browser_tests --single-process-tests --gtest_filter=MyTestName
 ```
 
-**note the underscore in `single_process`** -- this makes the test harness and
+**note the use of `single-process-tests`** -- this makes the test harness and
 browser process share the outermost process.
 
 
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher.cc b/extensions/browser/api/declarative_net_request/composite_matcher.cc
index d1aabd6..dce8132 100644
--- a/extensions/browser/api/declarative_net_request/composite_matcher.cc
+++ b/extensions/browser/api/declarative_net_request/composite_matcher.cc
@@ -10,13 +10,14 @@
 
 #include "base/metrics/histogram_macros.h"
 #include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
+#include "extensions/browser/api/declarative_net_request/request_action.h"
 #include "extensions/browser/api/declarative_net_request/utils.h"
 
 namespace extensions {
 namespace declarative_net_request {
 namespace flat_rule = url_pattern_index::flat;
 using PageAccess = PermissionsData::PageAccess;
-using RedirectAction = CompositeMatcher::RedirectAction;
+using RedirectActionInfo = CompositeMatcher::RedirectActionInfo;
 
 namespace {
 
@@ -50,45 +51,21 @@
   return params.allow_rule_cache[matcher];
 }
 
-// Upgrades the url's scheme to HTTPS.
-GURL GetUpgradedUrl(const GURL& url) {
-  DCHECK(url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kFtpScheme));
-
-  GURL::Replacements replacements;
-  replacements.SetSchemeStr(url::kHttpsScheme);
-  return url.ReplaceComponents(replacements);
-}
-
-// Compares |redirect_rule| and |upgrade_rule| and determines the redirect URL
-// based on the rule with the higher priority.
-GURL GetUrlByRulePriority(const flat_rule::UrlRule* redirect_rule,
-                          const flat_rule::UrlRule* upgrade_rule,
-                          const GURL& request_url,
-                          GURL redirect_rule_url) {
-  DCHECK(upgrade_rule || redirect_rule);
-
-  if (!upgrade_rule)
-    return redirect_rule_url;
-
-  if (!redirect_rule)
-    return GetUpgradedUrl(request_url);
-
-  return upgrade_rule->priority() > redirect_rule->priority()
-             ? GetUpgradedUrl(request_url)
-             : redirect_rule_url;
-}
-
 }  // namespace
 
-RedirectAction::RedirectAction(base::Optional<GURL> redirect_url,
-                               bool notify_request_withheld)
-    : redirect_url(std::move(redirect_url)),
-      notify_request_withheld(notify_request_withheld) {}
+RedirectActionInfo::RedirectActionInfo(base::Optional<RequestAction> action,
+                                       bool notify_request_withheld)
+    : action(std::move(action)),
+      notify_request_withheld(notify_request_withheld) {
+  if (action)
+    DCHECK_EQ(RequestAction::Type::REDIRECT, action->type);
+}
 
-RedirectAction::~RedirectAction() = default;
+RedirectActionInfo::~RedirectActionInfo() = default;
 
-RedirectAction::RedirectAction(RedirectAction&&) = default;
-RedirectAction& RedirectAction::operator=(RedirectAction&& other) = default;
+RedirectActionInfo::RedirectActionInfo(RedirectActionInfo&&) = default;
+RedirectActionInfo& RedirectActionInfo::operator=(RedirectActionInfo&& other) =
+    default;
 
 CompositeMatcher::CompositeMatcher(MatcherList matchers)
     : matchers_(std::move(matchers)) {
@@ -123,7 +100,8 @@
   has_any_extra_headers_matcher_.reset();
 }
 
-bool CompositeMatcher::ShouldBlockRequest(const RequestParams& params) const {
+base::Optional<RequestAction> CompositeMatcher::GetBlockOrCollapseAction(
+    const RequestParams& params) const {
   // TODO(karandeepb): change this to report time in micro-seconds.
   SCOPED_UMA_HISTOGRAM_TIMER(
       "Extensions.DeclarativeNetRequest.ShouldBlockRequestTime."
@@ -131,15 +109,18 @@
 
   for (const auto& matcher : matchers_) {
     if (HasMatchingAllowRule(matcher.get(), params))
-      return false;
-    if (matcher->HasMatchingBlockRule(params))
-      return true;
+      return base::nullopt;
+
+    base::Optional<RequestAction> action =
+        matcher->GetBlockOrCollapseAction(params);
+    if (action)
+      return action;
   }
 
-  return false;
+  return base::nullopt;
 }
 
-RedirectAction CompositeMatcher::ShouldRedirectRequest(
+RedirectActionInfo CompositeMatcher::GetRedirectAction(
     const RequestParams& params,
     PageAccess page_access) const {
   // TODO(karandeepb): change this to report time in micro-seconds.
@@ -150,42 +131,35 @@
   bool notify_request_withheld = false;
   for (const auto& matcher : matchers_) {
     if (HasMatchingAllowRule(matcher.get(), params)) {
-      return RedirectAction(base::nullopt /* redirect_url */,
-                            false /* notify_request_withheld */);
+      return RedirectActionInfo(base::nullopt /* action */,
+                                false /* notify_request_withheld */);
     }
 
     if (page_access == PageAccess::kAllowed) {
-      GURL redirect_rule_url;
-
-      const flat_rule::UrlRule* redirect_rule =
-          matcher->GetRedirectRule(params, &redirect_rule_url);
-      const flat_rule::UrlRule* upgrade_rule = matcher->GetUpgradeRule(params);
-
-      if (!upgrade_rule && !redirect_rule)
+      base::Optional<RequestAction> action =
+          matcher->GetRedirectOrUpgradeActionByPriority(params);
+      if (!action)
         continue;
 
-      GURL redirect_url =
-          GetUrlByRulePriority(redirect_rule, upgrade_rule, *params.url,
-                               std::move(redirect_rule_url));
-      return RedirectAction(std::move(redirect_url),
-                            false /* notify_request_withheld */);
+      return RedirectActionInfo(std::move(action),
+                                false /* notify_request_withheld */);
     }
 
     // If the extension has no host permissions for the request, it can still
     // upgrade the request.
-    if (matcher->GetUpgradeRule(params)) {
-      return RedirectAction(GetUpgradedUrl(*params.url),
-                            false /* notify_request_withheld */);
+    base::Optional<RequestAction> upgrade_action =
+        matcher->GetUpgradeAction(params);
+    if (upgrade_action) {
+      return RedirectActionInfo(std::move(upgrade_action),
+                                false /* notify_request_withheld */);
     }
 
-    GURL redirect_url;
-    notify_request_withheld |=
-        (page_access == PageAccess::kWithheld &&
-         matcher->GetRedirectRule(params, &redirect_url));
+    notify_request_withheld |= (page_access == PageAccess::kWithheld &&
+                                matcher->GetRedirectAction(params));
   }
 
-  return RedirectAction(base::nullopt /* redirect_url */,
-                        notify_request_withheld);
+  return RedirectActionInfo(base::nullopt /* action */,
+                            notify_request_withheld);
 }
 
 uint8_t CompositeMatcher::GetRemoveHeadersMask(const RequestParams& params,
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher.h b/extensions/browser/api/declarative_net_request/composite_matcher.h
index b4cf781..873d1c9 100644
--- a/extensions/browser/api/declarative_net_request/composite_matcher.h
+++ b/extensions/browser/api/declarative_net_request/composite_matcher.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "base/optional.h"
+#include "extensions/browser/api/declarative_net_request/request_action.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
 #include "extensions/common/permissions/permissions_data.h"
 
@@ -21,22 +22,22 @@
 // while respecting their priorities.
 class CompositeMatcher {
  public:
-  struct RedirectAction {
-    RedirectAction(base::Optional<GURL> redirect_url, bool notify);
-    ~RedirectAction();
-    RedirectAction(RedirectAction&& other);
-    RedirectAction& operator=(RedirectAction&& other);
+  struct RedirectActionInfo {
+    RedirectActionInfo(base::Optional<RequestAction> action, bool notify);
+    ~RedirectActionInfo();
+    RedirectActionInfo(RedirectActionInfo&& other);
+    RedirectActionInfo& operator=(RedirectActionInfo&& other);
 
-    // The URL the request will be redirected to. The request should not be
-    // redirected if this is not specified.
-    base::Optional<GURL> redirect_url;
+    // The action to be taken for this request. If specified, the action type
+    // must be |REDIRECT|.
+    base::Optional<RequestAction> action;
 
     // Whether the extension should be notified that the request was unable to
     // be redirected as the extension lacks the appropriate host permission for
     // the request.
     bool notify_request_withheld = false;
 
-    DISALLOW_COPY_AND_ASSIGN(RedirectAction);
+    DISALLOW_COPY_AND_ASSIGN(RedirectActionInfo);
   };
 
   using MatcherList = std::vector<std::unique_ptr<RulesetMatcher>>;
@@ -49,14 +50,15 @@
   // corresponding ID is already present, updates the matcher.
   void AddOrUpdateRuleset(std::unique_ptr<RulesetMatcher> new_matcher);
 
-  // Returns whether the network request as specified by |params| should be
-  // blocked.
-  bool ShouldBlockRequest(const RequestParams& params) const;
+  // Returns a RequestAction if the network request specified by |params| should
+  // be blocked.
+  base::Optional<RequestAction> GetBlockOrCollapseAction(
+      const RequestParams& params) const;
 
-  // Returns a RedirectAction struct containing a redirect URL if the request
-  // is to be redirected, and whether the extension should be notified if its
-  // access to the request is withheld.
-  RedirectAction ShouldRedirectRequest(
+  // Returns a RedirectActionInfo struct containing a RequestAction if the
+  // request is to be redirected, and whether the extension should be notified
+  // if its access to the request is withheld.
+  RedirectActionInfo GetRedirectAction(
       const RequestParams& params,
       PermissionsData::PageAccess page_access) const;
 
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc b/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
index 215911b..30d2bf5 100644
--- a/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
@@ -24,7 +24,7 @@
 namespace declarative_net_request {
 
 using PageAccess = PermissionsData::PageAccess;
-using RedirectAction = CompositeMatcher::RedirectAction;
+using RedirectActionInfo = CompositeMatcher::RedirectActionInfo;
 
 class CompositeMatcherTest : public ::testing::Test {
  public:
@@ -86,7 +86,8 @@
   google_params.is_third_party = false;
 
   // The second ruleset should get more priority.
-  EXPECT_FALSE(composite_matcher->ShouldBlockRequest(google_params));
+  EXPECT_FALSE(
+      composite_matcher->GetBlockOrCollapseAction(google_params).has_value());
 
   GURL example_url = GURL("http://example.com");
   RequestParams example_params;
@@ -95,10 +96,11 @@
       url_pattern_index::flat::ElementType_SUBDOCUMENT;
   example_params.is_third_party = false;
 
-  RedirectAction action = composite_matcher->ShouldRedirectRequest(
+  RedirectActionInfo action_info = composite_matcher->GetRedirectAction(
       example_params, PageAccess::kAllowed);
-  EXPECT_EQ(GURL("http://ruleset2.com"), action.redirect_url);
-  EXPECT_FALSE(action.notify_request_withheld);
+  ASSERT_TRUE(action_info.action);
+  EXPECT_EQ(GURL("http://ruleset2.com"), action_info.action->redirect_url);
+  EXPECT_FALSE(action_info.notify_request_withheld);
 
   // Now switch the priority of the two rulesets. This requires re-constructing
   // the two ruleset matchers.
@@ -120,12 +122,14 @@
   example_params.allow_rule_cache.clear();
 
   // The first ruleset should get more priority.
-  EXPECT_TRUE(composite_matcher->ShouldBlockRequest(google_params));
+  EXPECT_TRUE(
+      composite_matcher->GetBlockOrCollapseAction(google_params).has_value());
 
-  action = composite_matcher->ShouldRedirectRequest(example_params,
-                                                    PageAccess::kAllowed);
-  EXPECT_EQ(GURL("http://ruleset1.com"), action.redirect_url);
-  EXPECT_FALSE(action.notify_request_withheld);
+  action_info = composite_matcher->GetRedirectAction(example_params,
+                                                     PageAccess::kAllowed);
+  ASSERT_TRUE(action_info.action);
+  EXPECT_EQ(GURL("http://ruleset1.com"), action_info.action->redirect_url);
+  EXPECT_FALSE(action_info.notify_request_withheld);
 }
 
 // Ensure allow rules in a higher priority matcher override redirect
@@ -188,10 +192,11 @@
   google_params.is_third_party = false;
 
   // The second ruleset should get more priority.
-  RedirectAction action = composite_matcher->ShouldRedirectRequest(
-      google_params, PageAccess::kAllowed);
-  EXPECT_EQ(GURL("http://ruleset2.com"), action.redirect_url);
-  EXPECT_FALSE(action.notify_request_withheld);
+  RedirectActionInfo action_info =
+      composite_matcher->GetRedirectAction(google_params, PageAccess::kAllowed);
+  ASSERT_TRUE(action_info.action);
+  EXPECT_EQ(GURL("http://ruleset2.com"), action_info.action->redirect_url);
+  EXPECT_FALSE(action_info.notify_request_withheld);
 
   // Send a request to example.com with headers, expect the allow rule to be
   // matched and the headers to remain.
@@ -226,10 +231,10 @@
 
   // The first ruleset should get more priority and so the request to google.com
   // should not be redirected.
-  action = composite_matcher->ShouldRedirectRequest(google_params,
-                                                    PageAccess::kAllowed);
-  EXPECT_FALSE(action.redirect_url);
-  EXPECT_FALSE(action.notify_request_withheld);
+  action_info =
+      composite_matcher->GetRedirectAction(google_params, PageAccess::kAllowed);
+  EXPECT_FALSE(action_info.action.has_value());
+  EXPECT_FALSE(action_info.notify_request_withheld);
 
   // The request to example.com should now have its headers removed.
   example_params.allow_rule_cache.clear();
@@ -310,11 +315,11 @@
     params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
     params.is_third_party = false;
 
-    RedirectAction redirect_action =
-        composite_matcher->ShouldRedirectRequest(params, test_case.access);
+    RedirectActionInfo redirect_action_info =
+        composite_matcher->GetRedirectAction(params, test_case.access);
 
     EXPECT_EQ(test_case.should_notify_withheld,
-              redirect_action.notify_request_withheld);
+              redirect_action_info.notify_request_withheld);
   }
 }
 
@@ -387,16 +392,18 @@
     params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
     params.is_third_party = false;
 
-    RedirectAction redirect_action =
-        composite_matcher->ShouldRedirectRequest(params, PageAccess::kAllowed);
+    RedirectActionInfo redirect_action_info =
+        composite_matcher->GetRedirectAction(params, PageAccess::kAllowed);
 
     if (test_case.expected_final_url) {
-      EXPECT_EQ(test_case.expected_final_url->spec(),
-                redirect_action.redirect_url->spec());
-    } else
-      EXPECT_FALSE(redirect_action.redirect_url);
+      ASSERT_TRUE(redirect_action_info.action);
+      EXPECT_EQ(test_case.expected_final_url,
+                redirect_action_info.action->redirect_url);
+    } else {
+      EXPECT_FALSE(redirect_action_info.action.has_value());
+    }
 
-    EXPECT_FALSE(redirect_action.notify_request_withheld);
+    EXPECT_FALSE(redirect_action_info.notify_request_withheld);
   }
 }
 
diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.cc b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
index 897dd5f..76a7622 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_manager.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
@@ -162,13 +162,6 @@
          allowed_pages.MatchesURL(*request.frame_data.pending_main_frame_url);
 }
 
-bool ShouldCollapseResourceType(flat_rule::ElementType type) {
-  // TODO(crbug.com/848842): Add support for other element types like
-  // OBJECT.
-  return type == flat_rule::ElementType_IMAGE ||
-         type == flat_rule::ElementType_SUBDOCUMENT;
-}
-
 void NotifyRequestWithheld(const ExtensionId& extension_id,
                            const WebRequestInfo& request) {
   DCHECK(ExtensionsAPIClient::Get());
@@ -404,13 +397,10 @@
     const std::vector<const ExtensionRulesetData*>& rulesets,
     const RequestParams& params) const {
   for (const ExtensionRulesetData* ruleset : rulesets) {
-    if (ruleset->matcher->ShouldBlockRequest(params)) {
-      RequestAction action = ShouldCollapseResourceType(params.element_type)
-                                 ? RequestAction(RequestAction::Type::COLLAPSE)
-                                 : RequestAction(RequestAction::Type::BLOCK);
-      action.extension_id = ruleset->extension_id;
+    base::Optional<RequestAction> action =
+        ruleset->matcher->GetBlockOrCollapseAction(params);
+    if (action)
       return action;
-    }
   }
   return base::nullopt;
 }
@@ -439,23 +429,20 @@
         WebRequestPermissions::REQUIRE_HOST_PERMISSION_FOR_URL_AND_INITIATOR,
         request.initiator, request.type);
 
-    CompositeMatcher::RedirectAction redirect_action =
-        ruleset->matcher->ShouldRedirectRequest(params, page_access);
+    CompositeMatcher::RedirectActionInfo redirect_action_info =
+        ruleset->matcher->GetRedirectAction(params, page_access);
 
-    DCHECK(!(redirect_action.redirect_url &&
-             redirect_action.notify_request_withheld));
-    if (redirect_action.notify_request_withheld) {
+    DCHECK(!(redirect_action_info.action &&
+             redirect_action_info.notify_request_withheld));
+    if (redirect_action_info.notify_request_withheld) {
       NotifyRequestWithheld(ruleset->extension_id, request);
       continue;
     }
 
-    if (!redirect_action.redirect_url)
+    if (!redirect_action_info.action)
       continue;
 
-    RequestAction action(RequestAction::Type::REDIRECT);
-    action.redirect_url = std::move(redirect_action.redirect_url);
-    action.extension_id = ruleset->extension_id;
-    return action;
+    return std::move(redirect_action_info.action);
   }
 
   return base::nullopt;
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
index b146e0b..a99a92d 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
@@ -297,6 +297,22 @@
   return params.url->ReplaceComponents(replacements);
 }
 
+bool ShouldCollapseResourceType(flat_rule::ElementType type) {
+  // TODO(crbug.com/848842): Add support for other element types like
+  // OBJECT.
+  return type == flat_rule::ElementType_IMAGE ||
+         type == flat_rule::ElementType_SUBDOCUMENT;
+}
+
+// Upgrades the url's scheme to HTTPS.
+GURL GetUpgradedUrl(const GURL& url) {
+  DCHECK(url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kFtpScheme));
+
+  GURL::Replacements replacements;
+  replacements.SetSchemeStr(url::kHttpsScheme);
+  return url.ReplaceComponents(replacements);
+}
+
 }  // namespace
 
 RequestParams::RequestParams(const WebRequestInfo& info)
@@ -343,13 +359,88 @@
 
   // Using WrapUnique instead of make_unique since this class has a private
   // constructor.
-  *matcher = base::WrapUnique(new RulesetMatcher(
-      std::move(ruleset_data), source.id(), source.priority()));
+  *matcher = base::WrapUnique(new RulesetMatcher(std::move(ruleset_data),
+                                                 source.id(), source.priority(),
+                                                 source.extension_id()));
   return kLoadSuccess;
 }
 
 RulesetMatcher::~RulesetMatcher() = default;
 
+base::Optional<RequestAction> RulesetMatcher::GetBlockOrCollapseAction(
+    const RequestParams& params) const {
+  const flat_rule::UrlRule* rule =
+      GetMatchingRule(params, flat::ActionIndex_block);
+  if (!rule)
+    return base::nullopt;
+
+  RequestAction action = ShouldCollapseResourceType(params.element_type)
+                             ? RequestAction(RequestAction::Type::COLLAPSE)
+                             : RequestAction(RequestAction::Type::BLOCK);
+
+  action.extension_id = extension_id_;
+  return action;
+}
+
+base::Optional<RequestAction> RulesetMatcher::GetRedirectAction(
+    const RequestParams& params) const {
+  GURL redirect_rule_url;
+  const flat_rule::UrlRule* redirect_rule =
+      GetRedirectRule(params, &redirect_rule_url);
+
+  if (!redirect_rule)
+    return base::nullopt;
+
+  RequestAction redirect_action(RequestAction::Type::REDIRECT);
+  redirect_action.extension_id = extension_id_;
+  redirect_action.redirect_url = std::move(redirect_rule_url);
+
+  return redirect_action;
+}
+
+base::Optional<RequestAction> RulesetMatcher::GetUpgradeAction(
+    const RequestParams& params) const {
+  const flat_rule::UrlRule* upgrade_rule = GetUpgradeRule(params);
+
+  if (!upgrade_rule)
+    return base::nullopt;
+
+  RequestAction upgrade_action(RequestAction::Type::REDIRECT);
+  upgrade_action.extension_id = extension_id_;
+  upgrade_action.redirect_url = GetUpgradedUrl(*params.url);
+
+  return upgrade_action;
+}
+
+base::Optional<RequestAction>
+RulesetMatcher::GetRedirectOrUpgradeActionByPriority(
+    const RequestParams& params) const {
+  GURL redirect_rule_url;
+  const flat_rule::UrlRule* redirect_rule =
+      GetRedirectRule(params, &redirect_rule_url);
+  const flat_rule::UrlRule* upgrade_rule = GetUpgradeRule(params);
+
+  if (!redirect_rule && !upgrade_rule)
+    return base::nullopt;
+
+  GURL highest_priority_url;
+  if (!upgrade_rule) {
+    highest_priority_url = std::move(redirect_rule_url);
+  } else if (!redirect_rule) {
+    highest_priority_url = GetUpgradedUrl(*params.url);
+  } else {
+    highest_priority_url = upgrade_rule->priority() > redirect_rule->priority()
+                               ? GetUpgradedUrl(*params.url)
+                               : std::move(redirect_rule_url);
+  }
+
+  RequestAction action(RequestAction::Type::REDIRECT);
+  action.extension_id = extension_id_;
+  action.redirect_url = std::move(highest_priority_url);
+
+  return action;
+}
+
 uint8_t RulesetMatcher::GetRemoveHeadersMask(const RequestParams& params,
                                              uint8_t ignored_mask) const {
   uint8_t mask = 0;
@@ -391,6 +482,19 @@
   return mask;
 }
 
+RulesetMatcher::RulesetMatcher(std::string ruleset_data,
+                               size_t id,
+                               size_t priority,
+                               const ExtensionId& extension_id)
+    : ruleset_data_(std::move(ruleset_data)),
+      root_(flat::GetExtensionIndexedRuleset(ruleset_data_.data())),
+      matchers_(GetMatchers(root_)),
+      metadata_list_(root_->extension_metadata()),
+      id_(id),
+      priority_(priority),
+      extension_id_(extension_id),
+      is_extra_headers_matcher_(IsExtraHeadersMatcherInternal(*root_)) {}
+
 const flat_rule::UrlRule* RulesetMatcher::GetRedirectRule(
     const RequestParams& params,
     GURL* redirect_url) const {
@@ -438,17 +542,6 @@
              : nullptr;
 }
 
-RulesetMatcher::RulesetMatcher(std::string ruleset_data,
-                               size_t id,
-                               size_t priority)
-    : ruleset_data_(std::move(ruleset_data)),
-      root_(flat::GetExtensionIndexedRuleset(ruleset_data_.data())),
-      matchers_(GetMatchers(root_)),
-      metadata_list_(root_->extension_metadata()),
-      id_(id),
-      priority_(priority),
-      is_extra_headers_matcher_(IsExtraHeadersMatcherInternal(*root_)) {}
-
 const flat_rule::UrlRule* RulesetMatcher::GetMatchingRule(
     const RequestParams& params,
     flat::ActionIndex index,
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.h b/extensions/browser/api/declarative_net_request/ruleset_matcher.h
index 3535d9f..8a12290 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher.h
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.h
@@ -11,8 +11,10 @@
 #include <vector>
 
 #include "base/containers/flat_map.h"
+#include "base/optional.h"
 #include "components/url_pattern_index/url_pattern_index.h"
 #include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
+#include "extensions/common/extension_id.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -20,6 +22,7 @@
 struct WebRequestInfo;
 
 namespace declarative_net_request {
+struct RequestAction;
 class RulesetSource;
 
 namespace flat {
@@ -93,34 +96,39 @@
 
   ~RulesetMatcher();
 
-  // Returns whether the ruleset has a matching blocking rule.
-  bool HasMatchingBlockRule(const RequestParams& params) const {
-    return GetMatchingRule(params, flat::ActionIndex_block);
-  }
+  // Returns the ruleset's matching RequestAction with type |BLOCK| or
+  // |COLLAPSE|, or base::nullopt if the ruleset has no matching blocking rule.
+  base::Optional<RequestAction> GetBlockOrCollapseAction(
+      const RequestParams& params) const;
 
   // Returns whether the ruleset has a matching allow rule.
   bool HasMatchingAllowRule(const RequestParams& params) const {
     return GetMatchingRule(params, flat::ActionIndex_allow);
   }
 
+  // Returns the ruleset's matching redirect RequestAction if there is a
+  // matching redirect rule, otherwise returns base::nullopt.
+  base::Optional<RequestAction> GetRedirectAction(
+      const RequestParams& params) const;
+
+  // Returns the ruleset's matching RequestAction with |params.url| upgraded to
+  // HTTPS as the redirect url, or base::nullopt if no matching rule is found or
+  // if the request's scheme is not upgradeable.
+  base::Optional<RequestAction> GetUpgradeAction(
+      const RequestParams& params) const;
+
+  // Returns a RedirectAction constructed from the matching redirect or upgrade
+  // rule with the highest priority, or base::nullopt if no matching redirect or
+  // upgrade rules are found for this request.
+  base::Optional<RequestAction> GetRedirectOrUpgradeActionByPriority(
+      const RequestParams& params) const;
+
   // Returns the bitmask of headers to remove from the request. The bitmask
   // corresponds to RemoveHeadersMask type. |ignored_mask| denotes the mask of
   // headers to be skipped for evaluation and is excluded in the return value.
   uint8_t GetRemoveHeadersMask(const RequestParams& params,
                                uint8_t ignored_mask) const;
 
-  // Returns the ruleset's matching redirect rule and populates
-  // |redirect_url| if there is a matching redirect rule, otherwise returns
-  // nullptr.
-  const url_pattern_index::flat::UrlRule* GetRedirectRule(
-      const RequestParams& params,
-      GURL* redirect_url) const;
-
-  // Returns the ruleset's matching upgrade scheme rule or nullptr if no
-  // matching rule is found or if the request's scheme is not upgradeable.
-  const url_pattern_index::flat::UrlRule* GetUpgradeRule(
-      const RequestParams& params) const;
-
   // Returns whether this modifies "extraHeaders".
   bool IsExtraHeadersMatcher() const { return is_extra_headers_matcher_; }
 
@@ -137,7 +145,22 @@
   using ExtensionMetadataList =
       flatbuffers::Vector<flatbuffers::Offset<flat::UrlRuleMetadata>>;
 
-  explicit RulesetMatcher(std::string ruleset_data, size_t id, size_t priority);
+  explicit RulesetMatcher(std::string ruleset_data,
+                          size_t id,
+                          size_t priority,
+                          const ExtensionId& extension_id);
+
+  // Returns the ruleset's matching redirect rule and populates
+  // |redirect_url| if there is a matching redirect rule, otherwise returns
+  // nullptr.
+  const url_pattern_index::flat::UrlRule* GetRedirectRule(
+      const RequestParams& params,
+      GURL* redirect_url) const;
+
+  // Returns the ruleset's matching upgrade scheme rule or nullptr if no
+  // matching rule is found or if the request's scheme is not upgradeable.
+  const url_pattern_index::flat::UrlRule* GetUpgradeRule(
+      const RequestParams& params) const;
 
   const url_pattern_index::flat::UrlRule* GetMatchingRule(
       const RequestParams& params,
@@ -154,8 +177,11 @@
 
   const ExtensionMetadataList* const metadata_list_;
 
-  size_t id_;
-  size_t priority_;
+  const size_t id_;
+  const size_t priority_;
+
+  // The ID of the extension from which this matcher's ruleset originates from.
+  const ExtensionId extension_id_;
 
   const bool is_extra_headers_matcher_;
 
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
index 54cfa1f..9323ba56 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
@@ -14,6 +14,7 @@
 #include "components/url_pattern_index/flat/url_pattern_index_generated.h"
 #include "components/version_info/version_info.h"
 #include "extensions/browser/api/declarative_net_request/constants.h"
+#include "extensions/browser/api/declarative_net_request/request_action.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_source.h"
 #include "extensions/browser/api/declarative_net_request/test_utils.h"
 #include "extensions/browser/api/declarative_net_request/utils.h"
@@ -49,7 +50,7 @@
 
   auto should_block_request = [&matcher](const RequestParams& params) {
     return !matcher->HasMatchingAllowRule(params) &&
-           matcher->HasMatchingBlockRule(params);
+           matcher->GetBlockOrCollapseAction(params).has_value();
   };
 
   GURL google_url("http://google.com");
@@ -77,11 +78,6 @@
   std::unique_ptr<RulesetMatcher> matcher;
   ASSERT_TRUE(CreateVerifiedMatcher({rule}, CreateTemporarySource(), &matcher));
 
-  auto should_redirect_request = [&matcher](const RequestParams& params,
-                                            GURL* redirect_url) {
-    return matcher->GetRedirectRule(params, redirect_url) != nullptr;
-  };
-
   GURL google_url("http://google.com");
   GURL yahoo_url("http://yahoo.com");
 
@@ -90,12 +86,13 @@
   params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
   params.is_third_party = true;
 
-  GURL redirect_url;
-  EXPECT_TRUE(should_redirect_request(params, &redirect_url));
-  EXPECT_EQ(yahoo_url, redirect_url);
+  base::Optional<RequestAction> redirect_action =
+      matcher->GetRedirectAction(params);
+  ASSERT_TRUE(redirect_action);
+  EXPECT_EQ(yahoo_url, redirect_action->redirect_url);
 
   params.url = &yahoo_url;
-  EXPECT_FALSE(should_redirect_request(params, &redirect_url));
+  EXPECT_FALSE(matcher->GetRedirectAction(params));
 }
 
 // Test that a URL cannot redirect to itself, as filed in crbug.com/954646.
@@ -116,8 +113,7 @@
   params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
   params.is_third_party = true;
 
-  GURL redirect_url;
-  EXPECT_FALSE(matcher->GetRedirectRule(params, &redirect_url));
+  EXPECT_FALSE(matcher->GetRedirectAction(params));
 }
 
 // Tests a simple upgrade scheme rule.
@@ -131,7 +127,7 @@
   ASSERT_TRUE(CreateVerifiedMatcher({rule}, CreateTemporarySource(), &matcher));
 
   auto should_upgrade_request = [&matcher](const RequestParams& params) {
-    return matcher->GetUpgradeRule(params) != nullptr;
+    return matcher->GetUpgradeAction(params).has_value();
   };
 
   GURL google_url("http://google.com");
@@ -232,21 +228,21 @@
   const size_t kId = 1;
   const size_t kPriority = 1;
   const size_t kRuleCountLimit = 10;
-  const ExtensionId extension_id = "extension_id";
   ASSERT_TRUE(CreateVerifiedMatcher(
-      {rule},
-      CreateTemporarySource(kId, kPriority, kRuleCountLimit, extension_id),
+      {rule}, CreateTemporarySource(kId, kPriority, kRuleCountLimit),
       &matcher));
 
   GURL example_url("http://example.com");
   RequestParams params;
   params.url = &example_url;
 
-  GURL redirect_url;
-  EXPECT_TRUE(matcher->GetRedirectRule(params, &redirect_url));
+  base::Optional<RequestAction> redirect_action =
+      matcher->GetRedirectAction(params);
+
+  ASSERT_TRUE(redirect_action.has_value());
   GURL expected_redirect_url(
-      "chrome-extension://extension_id/path/newfile.js?query#fragment");
-  EXPECT_EQ(expected_redirect_url, redirect_url);
+      "chrome-extension://extensionid/path/newfile.js?query#fragment");
+  EXPECT_EQ(expected_redirect_url, redirect_action->redirect_url);
 }
 
 // Tests a rule to redirect to a static url.
@@ -265,10 +261,12 @@
   RequestParams params;
   params.url = &example_url;
 
-  GURL redirect_url;
+  base::Optional<RequestAction> redirect_action =
+      matcher->GetRedirectAction(params);
+
+  ASSERT_TRUE(redirect_action.has_value());
   GURL expected_redirect_url("https://google.com");
-  EXPECT_TRUE(matcher->GetRedirectRule(params, &redirect_url));
-  EXPECT_EQ(expected_redirect_url, redirect_url);
+  EXPECT_EQ(expected_redirect_url, redirect_action->redirect_url);
 }
 
 // Tests url transformation rules.
@@ -396,17 +394,20 @@
     RequestParams params;
     params.url = &url;
 
-    GURL redirect_url;
+    base::Optional<RequestAction> redirect_action =
+        matcher->GetRedirectAction(params);
+
     if (!test_case.expected_redirect_url) {
-      EXPECT_FALSE(matcher->GetRedirectRule(params, &redirect_url))
-          << redirect_url.spec();
+      EXPECT_FALSE(redirect_action) << redirect_action->redirect_url->spec();
       continue;
     }
 
     ASSERT_TRUE(GURL(*test_case.expected_redirect_url).is_valid())
         << *test_case.expected_redirect_url;
-    EXPECT_TRUE(matcher->GetRedirectRule(params, &redirect_url));
-    EXPECT_EQ(*test_case.expected_redirect_url, redirect_url.spec());
+
+    ASSERT_TRUE(redirect_action.has_value());
+    EXPECT_EQ(GURL(*test_case.expected_redirect_url),
+              redirect_action->redirect_url);
   }
 }
 
diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc
index 0d4efd05..0de22ee 100644
--- a/extensions/browser/app_window/app_window.cc
+++ b/extensions/browser/app_window/app_window.cc
@@ -913,7 +913,7 @@
 void AppWindow::EnterFullscreenModeForTab(
     content::WebContents* source,
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   ToggleFullscreenModeForTab(source, true);
 }
 
diff --git a/extensions/browser/app_window/app_window.h b/extensions/browser/app_window/app_window.h
index b3454693..f885247 100644
--- a/extensions/browser/app_window/app_window.h
+++ b/extensions/browser/app_window/app_window.h
@@ -410,7 +410,7 @@
   void EnterFullscreenModeForTab(
       content::WebContents* source,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override;
+      const blink::FullScreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents* source) override;
   bool IsFullscreenForTabOrPending(const content::WebContents* source) override;
   blink::mojom::DisplayMode GetDisplayMode(
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
index 86dcfed5..e06ec97 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
@@ -369,7 +369,7 @@
 void MimeHandlerViewGuest::EnterFullscreenModeForTab(
     content::WebContents*,
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   if (SetFullscreenState(true)) {
     auto* delegate = embedder_web_contents()->GetDelegate();
     if (delegate) {
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
index 908d183..038b21c 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
@@ -146,7 +146,7 @@
   void EnterFullscreenModeForTab(
       content::WebContents* web_contents,
       const GURL& origin,
-      const blink::WebFullscreenOptions& options) override;
+      const blink::FullScreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents*) override;
   bool IsFullscreenForTabOrPending(
       const content::WebContents* web_contents) override;
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index 3e73eef..913077e 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -1406,7 +1406,7 @@
 void WebViewGuest::EnterFullscreenModeForTab(
     WebContents* web_contents,
     const GURL& origin,
-    const blink::WebFullscreenOptions& options) {
+    const blink::FullScreenOptions& options) {
   // Ask the embedder for permission.
   base::DictionaryValue request_info;
   request_info.SetString(webview::kOrigin, origin.spec());
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h
index de9cb23..7b08224 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.h
+++ b/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -256,10 +256,9 @@
                           const std::string& frame_name,
                           const GURL& target_url,
                           content::WebContents* new_contents) final;
-  void EnterFullscreenModeForTab(
-      content::WebContents* web_contents,
-      const GURL& origin,
-      const blink::WebFullscreenOptions& options) final;
+  void EnterFullscreenModeForTab(content::WebContents* web_contents,
+                                 const GURL& origin,
+                                 const blink::FullScreenOptions& options) final;
   void ExitFullscreenModeForTab(content::WebContents* web_contents) final;
   bool IsFullscreenForTabOrPending(
       const content::WebContents* web_contents) final;
diff --git a/fuchsia/fidl/cast/application_config.fidl b/fuchsia/fidl/cast/application_config.fidl
index f3c4685..4ea9729 100644
--- a/fuchsia/fidl/cast/application_config.fidl
+++ b/fuchsia/fidl/cast/application_config.fidl
@@ -4,6 +4,8 @@
 
 library chromium.cast;
 
+using fuchsia.web;
+
 /// Describes the configuration under which a Cast application should run.
 table ApplicationConfig {
   /// Cast application Id.
@@ -21,6 +23,11 @@
   // If true, enable remote debugging for this application.
   // if false or unset, remote debugging is disabled for this application.
   5: bool enable_remote_debugging;
+
+  /// List of directories whose contents are served via `fuchsia-dir://`
+  /// URLs. Networking will be disabled if any directories are set.
+  6: vector<fuchsia.web.ContentDirectoryProvider>
+      content_directories_for_isolated_application;
 };
 
 /// Service interface for working with application configurations.
diff --git a/fuchsia/runners/cast/cast_runner.cc b/fuchsia/runners/cast/cast_runner.cc
index 4dcab1e3..85b00fd 100644
--- a/fuchsia/runners/cast/cast_runner.cc
+++ b/fuchsia/runners/cast/cast_runner.cc
@@ -4,20 +4,72 @@
 
 #include "fuchsia/runners/cast/cast_runner.h"
 
+#include <fuchsia/sys/cpp/fidl.h>
 #include <memory>
 #include <string>
 #include <utility>
 
+#include "base/fuchsia/file_utils.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/logging.h"
 #include "url/gurl.h"
 
+namespace {
+
+bool AreCastComponentParamsValid(
+    const CastComponent::CastComponentParams& params) {
+  if (params.app_config.IsEmpty())
+    return false;
+  if (!params.api_bindings_client->HasBindings())
+    return false;
+  if (!params.rewrite_rules.has_value())
+    return false;
+  return true;
+}
+
+// Creates a CreateContextParams object which can be used as a basis
+// for starting isolated Runners.
+fuchsia::web::CreateContextParams BuildCreateContextParamsForIsolatedRunners(
+    const fuchsia::web::CreateContextParams& create_context_params) {
+  fuchsia::web::CreateContextParams output;
+  if (create_context_params.has_features()) {
+    output.set_features(create_context_params.features());
+  }
+  if (create_context_params.has_user_agent_product()) {
+    output.set_user_agent_product(create_context_params.user_agent_product());
+  }
+  if (create_context_params.has_user_agent_version()) {
+    output.set_user_agent_version(create_context_params.user_agent_version());
+  }
+  if (create_context_params.has_remote_debugging_port()) {
+    output.set_remote_debugging_port(
+        create_context_params.remote_debugging_port());
+  }
+  return output;
+}
+
+}  // namespace
+
 CastRunner::CastRunner(sys::OutgoingDirectory* outgoing_directory,
+                       fuchsia::web::CreateContextParams create_context_params)
+    : WebContentRunner(outgoing_directory,
+                       base::BindOnce(&CastRunner::CreateCastRunnerWebContext,
+                                      base::Unretained(this))),
+      create_context_params_(std::move(create_context_params)),
+      common_create_context_params_(
+          BuildCreateContextParamsForIsolatedRunners(create_context_params_)) {}
+
+CastRunner::CastRunner(OnDestructionCallback on_destruction_callback,
                        fuchsia::web::ContextPtr context)
-    : WebContentRunner(outgoing_directory, std::move(context)) {}
+    : WebContentRunner(std::move(context)),
+      on_destruction_callback_(std::move(on_destruction_callback)) {}
 
 CastRunner::~CastRunner() = default;
 
+fuchsia::web::ContextPtr CastRunner::CreateCastRunnerWebContext() {
+  return WebContentRunner::CreateWebContext(std::move(create_context_params_));
+}
+
 void CastRunner::StartComponent(
     fuchsia::sys::Package package,
     fuchsia::sys::StartupInfo startup_info,
@@ -99,6 +151,16 @@
   pending_components_.emplace(std::move(pending_component));
 }
 
+void CastRunner::DestroyComponent(WebComponent* component) {
+  WebContentRunner::DestroyComponent(component);
+
+  if (on_destruction_callback_) {
+    // |this| may be deleted and should not be used after this line.
+    std::move(on_destruction_callback_).Run(this);
+    return;
+  }
+}
+
 const char CastRunner::kAgentComponentUrl[] =
     "fuchsia-pkg://fuchsia.com/cast_agent#meta/cast_agent.cmx";
 
@@ -121,23 +183,75 @@
 }
 
 void CastRunner::MaybeStartComponent(
-    CastComponent::CastComponentParams* pending_component) {
-  if (pending_component->app_config.IsEmpty())
-    return;
-  if (!pending_component->api_bindings_client->HasBindings())
-    return;
-  if (!pending_component->rewrite_rules.has_value())
+    CastComponent::CastComponentParams* pending_component_params) {
+  if (!AreCastComponentParamsValid(*pending_component_params))
     return;
 
-  // Create a component based on the returned configuration, and pass it the
-  // |pending_component|.
-  GURL cast_app_url(pending_component->app_config.web_url());
-  auto component =
-      std::make_unique<CastComponent>(this, std::move(*pending_component));
-  pending_components_.erase(pending_component);
+  // The runner which will host the newly created CastComponent.
+  CastRunner* component_owner = this;
+  if (pending_component_params->app_config
+          .has_content_directories_for_isolated_application()) {
+    // Create a isolated, isolated CastRunner instance which will own the
+    // CastComponent.
+    component_owner =
+        CreateChildRunnerForIsolatedComponent(pending_component_params);
+  }
 
-  component->StartComponent();
-  component->LoadUrl(std::move(cast_app_url),
-                     std::vector<fuchsia::net::http::Header>());
-  RegisterComponent(std::move(component));
+  component_owner->CreateAndRegisterCastComponent(
+      std::move(*pending_component_params));
+  pending_components_.erase(pending_component_params);
+}
+
+void CastRunner::CreateAndRegisterCastComponent(
+    CastComponent::CastComponentParams params) {
+  GURL app_url = GURL(params.app_config.web_url());
+  auto cast_component =
+      std::make_unique<CastComponent>(this, std::move(params));
+  cast_component->StartComponent();
+  cast_component->LoadUrl(std::move(app_url),
+                          std::vector<fuchsia::net::http::Header>());
+  RegisterComponent(std::move(cast_component));
+}
+
+CastRunner* CastRunner::CreateChildRunnerForIsolatedComponent(
+    CastComponent::CastComponentParams* params) {
+  // Construct the CreateContextParams in order to create a new Context.
+  // Some common parameters must be inherited from
+  // |common_create_context_params_|.
+  fuchsia::web::CreateContextParams isolated_context_params;
+  zx_status_t status =
+      common_create_context_params_.Clone(&isolated_context_params);
+  ZX_CHECK(status == ZX_OK, status) << "clone";
+  isolated_context_params.set_service_directory(base::fuchsia::OpenDirectory(
+      base::FilePath(base::fuchsia::kServiceDirectoryPath)));
+  isolated_context_params.set_content_directories(
+      std::move(*params->app_config
+                     .mutable_content_directories_for_isolated_application()));
+
+  std::unique_ptr<CastRunner> cast_runner(
+      new CastRunner(base::BindOnce(&CastRunner::OnChildRunnerDestroyed,
+                                    base::Unretained(this)),
+                     CreateWebContext(std::move(isolated_context_params))));
+
+  // If test code is listening for Component creation events, then wire up the
+  // isolated CastRunner to signal component creation events.
+  if (web_component_created_callback_for_test()) {
+    cast_runner->SetWebComponentCreatedCallbackForTest(
+        web_component_created_callback_for_test());
+  }
+
+  CastRunner* cast_runner_ptr = cast_runner.get();
+  isolated_runners_.insert(std::move(cast_runner));
+  return cast_runner_ptr;
+}
+
+void CastRunner::OnChildRunnerDestroyed(CastRunner* runner) {
+  auto runner_iterator = isolated_runners_.find(runner);
+  DCHECK(runner_iterator != isolated_runners_.end());
+
+  isolated_runners_.erase(runner_iterator);
+}
+
+size_t CastRunner::GetChildCastRunnerCountForTest() {
+  return isolated_runners_.size();
 }
diff --git a/fuchsia/runners/cast/cast_runner.h b/fuchsia/runners/cast/cast_runner.h
index f2ca037..9752fb28 100644
--- a/fuchsia/runners/cast/cast_runner.h
+++ b/fuchsia/runners/cast/cast_runner.h
@@ -22,11 +22,20 @@
 // sys::Runner which instantiates Cast activities specified via cast/casts URIs.
 class CastRunner : public WebContentRunner {
  public:
+  using OnDestructionCallback = base::OnceCallback<void(CastRunner*)>;
+
+  // |outgoing_directory|: The directory that this CastRunner will publish
+  //     itself to.
+  // |context_feature_flags|: The feature flags to use when creating the
+  //     runner's Context.
   CastRunner(sys::OutgoingDirectory* outgoing_directory,
-             fuchsia::web::ContextPtr context);
+             fuchsia::web::CreateContextParams create_context_params);
 
   ~CastRunner() override;
 
+  // WebContentRunner implementation.
+  void DestroyComponent(WebComponent* component) override;
+
   // fuchsia::sys::Runner implementation.
   void StartComponent(fuchsia::sys::Package package,
                       fuchsia::sys::StartupInfo startup_info,
@@ -36,16 +45,35 @@
   // Used to connect to the CastAgent to access Cast-specific services.
   static const char kAgentComponentUrl[];
 
+  // Returns the number of active CastRunner instances.
+  size_t GetChildCastRunnerCountForTest();
+
  private:
+  // Constructor used for creating CastRunners that run apps in dedicated
+  // Contexts. Child CastRunners may only spawn one Component and will be
+  // destroyed by their parents when their singleton Components are destroyed.
+  // |on_destruction_callback| is invoked when the child component is destroyed.
+  CastRunner(OnDestructionCallback on_destruction_callback,
+             fuchsia::web::ContextPtr context);
+
+  // Starts a component once all configuration data is available.
+  void MaybeStartComponent(
+      CastComponent::CastComponentParams* pending_component_params);
+
+  void CreateAndRegisterCastComponent(
+      CastComponent::CastComponentParams params);
   void GetConfigCallback(CastComponent::CastComponentParams* pending_component,
                          chromium::cast::ApplicationConfig app_config);
   void GetBindingsCallback(
       CastComponent::CastComponentParams* pending_component,
       std::vector<chromium::cast::ApiBinding> bindings);
+  void OnChildRunnerDestroyed(CastRunner* cast_runner);
+  fuchsia::web::ContextPtr CreateCastRunnerWebContext();
 
-  // Starts a component once all configuration data is available.
-  void MaybeStartComponent(
-      CastComponent::CastComponentParams* pending_component);
+  // Creates a CastRunner configured to serve data from content directories in
+  // |params|.
+  CastRunner* CreateChildRunnerForIsolatedComponent(
+      CastComponent::CastComponentParams* params);
 
   // Holds StartComponent() requests while the ApplicationConfig is being
   // fetched from the ApplicationConfigManager.
@@ -53,6 +81,20 @@
                  base::UniquePtrComparator>
       pending_components_;
 
+  // Used for creating the CastRunner's ContextPtr.
+  fuchsia::web::CreateContextParams create_context_params_;
+
+  // Used as a template for creating the ContextPtrs of isolated Runners.
+  fuchsia::web::CreateContextParams common_create_context_params_;
+
+  // Invoked upon destruction of "isolated" runners, used to signal termination
+  // to parents.
+  OnDestructionCallback on_destruction_callback_;
+
+  // Manages isolated CastRunners owned by |this| instance.
+  base::flat_set<std::unique_ptr<CastRunner>, base::UniquePtrComparator>
+      isolated_runners_;
+
   DISALLOW_COPY_AND_ASSIGN(CastRunner);
 };
 
diff --git a/fuchsia/runners/cast/cast_runner_integration_test.cc b/fuchsia/runners/cast/cast_runner_integration_test.cc
index f74cf6e..94bf955 100644
--- a/fuchsia/runners/cast/cast_runner_integration_test.cc
+++ b/fuchsia/runners/cast/cast_runner_integration_test.cc
@@ -7,9 +7,12 @@
 #include <lib/fidl/cpp/binding.h>
 #include <lib/zx/channel.h>
 
+#include "base/base_paths_fuchsia.h"
+#include "base/callback_helpers.h"
 #include "base/fuchsia/file_utils.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/fuchsia/scoped_service_binding.h"
+#include "base/path_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/task_environment.h"
@@ -175,8 +178,7 @@
     const uint16_t kRemoteDebuggingAnyPort = 0;
     create_context_params.set_remote_debugging_port(kRemoteDebuggingAnyPort);
     cast_runner_ = std::make_unique<CastRunner>(
-        &outgoing_directory_,
-        WebContentRunner::CreateWebContext(std::move(create_context_params)));
+        &outgoing_directory_, std::move(create_context_params));
 
     // Connect to the CastRunner's fuchsia.sys.Runner interface.
     fidl::InterfaceHandle<fuchsia::io::Directory> directory;
@@ -319,7 +321,8 @@
     base::RunLoop run_loop;
     cr_fuchsia::ResultReceiver<WebComponent*> web_component(
         run_loop.QuitClosure());
-    cast_runner_->GetWebComponentForTest(web_component.GetReceiveCallback());
+    cast_runner_->SetWebComponentCreatedCallbackForTest(
+        base::AdaptCallbackForRepeating(web_component.GetReceiveCallback()));
     run_loop.Run();
     ASSERT_NE(*web_component, nullptr);
     (*web_component)
@@ -405,7 +408,8 @@
   });
   cr_fuchsia::ResultReceiver<WebComponent*> web_component(
       run_loop.QuitClosure());
-  cast_runner_->GetWebComponentForTest(web_component.GetReceiveCallback());
+  cast_runner_->SetWebComponentCreatedCallbackForTest(
+      AdaptCallbackForRepeating(web_component.GetReceiveCallback()));
   run_loop.Run();
   EXPECT_FALSE(web_component.has_value());
 }
@@ -426,8 +430,8 @@
     base::RunLoop run_loop;
     cr_fuchsia::ResultReceiver<WebComponent*> web_component_receiver(
         run_loop.QuitClosure());
-    cast_runner_->GetWebComponentForTest(
-        web_component_receiver.GetReceiveCallback());
+    cast_runner_->SetWebComponentCreatedCallbackForTest(
+        AdaptCallbackForRepeating(web_component_receiver.GetReceiveCallback()));
     run_loop.Run();
     ASSERT_NE(*web_component_receiver, nullptr);
     web_component = *web_component_receiver;
@@ -534,7 +538,7 @@
     cr_fuchsia::ResultReceiver<
         fuchsia::web::Context_GetRemoteDebuggingPort_Result>
         port_receiver(run_loop.QuitClosure());
-    cast_runner_->context()->GetRemoteDebuggingPort(
+    cast_runner_->GetContext()->GetRemoteDebuggingPort(
         cr_fuchsia::CallbackToFitFunction(port_receiver.GetReceiveCallback()));
     run_loop.Run();
 
@@ -554,4 +558,57 @@
   EXPECT_EQ(devtools_url->GetString(), kBlankAppUrl.spec());
 }
 
+TEST_F(CastRunnerIntegrationTest, IsolatedContext) {
+  const char kBlankAppId[] = "00000000";
+  const GURL kContentDirectoryUrl("fuchsia-dir://testdata/echo.html");
+
+  EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 0u);
+
+  fuchsia::web::ContentDirectoryProvider provider;
+  provider.set_name("testdata");
+  base::FilePath pkg_path;
+  CHECK(base::PathService::Get(base::DIR_ASSETS, &pkg_path));
+  provider.set_directory(base::fuchsia::OpenDirectory(
+      pkg_path.AppendASCII("fuchsia/runners/cast/testdata")));
+  std::vector<fuchsia::web::ContentDirectoryProvider> providers;
+  providers.emplace_back(std::move(provider));
+  app_config_manager_.AddAppMappingWithContentDirectories(
+      kBlankAppId, kContentDirectoryUrl, std::move(providers));
+
+  // Launch the test-app component.
+  fuchsia::sys::ComponentControllerPtr component_controller =
+      StartCastComponent(base::StringPrintf("cast:%s", kBlankAppId));
+  component_controller.set_error_handler(&ComponentErrorHandler);
+
+  // Navigate to the page and verify that we read it.
+  {
+    base::RunLoop run_loop;
+    cr_fuchsia::ResultReceiver<WebComponent*> web_component(
+        run_loop.QuitClosure());
+    cast_runner_->SetWebComponentCreatedCallbackForTest(
+        AdaptCallbackForRepeating(web_component.GetReceiveCallback()));
+    run_loop.Run();
+    ASSERT_NE(*web_component, nullptr);
+
+    EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 1u);
+
+    cr_fuchsia::TestNavigationListener listener;
+    fidl::Binding<fuchsia::web::NavigationEventListener> listener_binding(
+        &listener);
+    (*web_component)
+        ->frame()
+        ->SetNavigationEventListener(listener_binding.NewBinding());
+    listener.RunUntilUrlAndTitleEquals(kContentDirectoryUrl, "echo");
+  }
+
+  // Verify that the component is torn down when |component_controller| is
+  // unbound.
+  base::RunLoop run_loop;
+  component_state_->set_on_delete(run_loop.QuitClosure());
+  component_controller.Unbind();
+  run_loop.Run();
+
+  EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 0u);
+}
+
 }  // namespace castrunner
diff --git a/fuchsia/runners/cast/fake_application_config_manager.cc b/fuchsia/runners/cast/fake_application_config_manager.cc
index 2b380f4..a1e838e5 100644
--- a/fuchsia/runners/cast/fake_application_config_manager.cc
+++ b/fuchsia/runners/cast/fake_application_config_manager.cc
@@ -15,17 +15,14 @@
 
 void FakeApplicationConfigManager::GetConfig(std::string id,
                                              GetConfigCallback callback) {
-  const auto iter = id_to_application_config_.find(id);
-  if (iter == id_to_application_config_.end()) {
+  if (id_to_config_.find(id) == id_to_config_.end()) {
     LOG(ERROR) << "Unknown Cast App ID: " << id;
     callback(chromium::cast::ApplicationConfig());
     return;
   }
 
-  chromium::cast::ApplicationConfig app_config;
-  zx_status_t status = iter->second.Clone(&app_config);
-  DCHECK_EQ(status, ZX_OK);
-  callback(std::move(app_config));
+  callback(std::move(std::move(id_to_config_[id])));
+  id_to_config_.erase(id);
 }
 
 void FakeApplicationConfigManager::AddAppMapping(const std::string& id,
@@ -36,6 +33,21 @@
   app_config.set_display_name("Dummy test app");
   app_config.set_web_url(url.spec());
   app_config.set_enable_remote_debugging(enable_remote_debugging);
+  id_to_config_[id] = std::move(app_config);
+}
 
-  id_to_application_config_[id] = std::move(app_config);
+void FakeApplicationConfigManager::AddAppMappingWithContentDirectories(
+    const std::string& id,
+    const GURL& url,
+    std::vector<fuchsia::web::ContentDirectoryProvider> directories) {
+  chromium::cast::ApplicationConfig app_config;
+  app_config.set_id(id);
+  app_config.set_display_name("Dummy test app");
+  app_config.set_web_url(url.spec());
+  if (!directories.empty()) {
+    app_config.set_content_directories_for_isolated_application(
+        std::move(directories));
+  }
+
+  id_to_config_[id] = std::move(app_config);
 }
diff --git a/fuchsia/runners/cast/fake_application_config_manager.h b/fuchsia/runners/cast/fake_application_config_manager.h
index 0b4e488..b965d87 100644
--- a/fuchsia/runners/cast/fake_application_config_manager.h
+++ b/fuchsia/runners/cast/fake_application_config_manager.h
@@ -7,6 +7,7 @@
 
 #include <map>
 #include <string>
+#include <vector>
 
 #include "base/macros.h"
 #include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
@@ -26,12 +27,18 @@
                      const GURL& url,
                      bool enable_remote_debugging);
 
+  // Associates a Cast application |id| with a url and a set of content
+  // directories, to be served from the EmbeddedTestServer.
+  void AddAppMappingWithContentDirectories(
+      const std::string& id,
+      const GURL& url,
+      std::vector<fuchsia::web::ContentDirectoryProvider> directories);
+
   // chromium::cast::ApplicationConfigManager interface.
   void GetConfig(std::string id, GetConfigCallback config_callback) override;
 
  private:
-  std::map<std::string, chromium::cast::ApplicationConfig>
-      id_to_application_config_;
+  std::map<std::string, chromium::cast::ApplicationConfig> id_to_config_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeApplicationConfigManager);
 };
diff --git a/fuchsia/runners/cast/main.cc b/fuchsia/runners/cast/main.cc
index 0b2740a..eb11ef4 100644
--- a/fuchsia/runners/cast/main.cc
+++ b/fuchsia/runners/cast/main.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <fuchsia/sys/cpp/fidl.h>
 #include <lib/sys/cpp/component_context.h>
 
 #include "base/command_line.h"
@@ -51,7 +50,7 @@
 
   CastRunner runner(
       base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(),
-      WebContentRunner::CreateWebContext(std::move(create_context_params)));
+      std::move(create_context_params));
 
   base::fuchsia::ComponentContextForCurrentProcess()
       ->outgoing()
diff --git a/fuchsia/runners/common/web_component.cc b/fuchsia/runners/common/web_component.cc
index 4f79844..a8a56ce 100644
--- a/fuchsia/runners/common/web_component.cc
+++ b/fuchsia/runners/common/web_component.cc
@@ -65,8 +65,8 @@
   // Create the underlying Frame and get its NavigationController.
   fuchsia::web::CreateFrameParams create_params;
   create_params.set_enable_remote_debugging(enable_remote_debugging_);
-  runner_->context()->CreateFrameWithParams(std::move(create_params),
-                                            frame_.NewRequest());
+  runner_->GetContext()->CreateFrameWithParams(std::move(create_params),
+                                               frame_.NewRequest());
 
   // If the Frame unexpectedly disconnect us then tear-down this Component.
   frame_.set_error_handler([this](zx_status_t status) {
@@ -93,7 +93,6 @@
 void WebComponent::LoadUrl(
     const GURL& url,
     std::vector<fuchsia::net::http::Header> extra_headers) {
-  DCHECK(component_started_);
   DCHECK(url.is_valid());
   fuchsia::web::NavigationControllerPtr navigation_controller;
   frame()->GetNavigationController(navigation_controller.NewRequest());
diff --git a/fuchsia/runners/common/web_content_runner.cc b/fuchsia/runners/common/web_content_runner.cc
index c5649715..d791930 100644
--- a/fuchsia/runners/common/web_content_runner.cc
+++ b/fuchsia/runners/common/web_content_runner.cc
@@ -76,14 +76,29 @@
   return create_params;
 }
 
-WebContentRunner::WebContentRunner(sys::OutgoingDirectory* outgoing_directory,
-                                   fuchsia::web::ContextPtr context)
-    : context_(std::move(context)), service_binding_(outgoing_directory, this) {
-  DCHECK(context_);
+WebContentRunner::WebContentRunner(
+    sys::OutgoingDirectory* outgoing_directory,
+    CreateContextCallback create_context_callback)
+    : create_context_callback_(std::move(create_context_callback)) {
+  DCHECK(create_context_callback_);
+  service_binding_.emplace(outgoing_directory, this);
 }
 
+WebContentRunner::WebContentRunner(fuchsia::web::ContextPtr context)
+    : context_(std::move(context)) {}
+
 WebContentRunner::~WebContentRunner() = default;
 
+fuchsia::web::Context* WebContentRunner::GetContext() {
+  if (!context_) {
+    DCHECK(create_context_callback_);
+    context_ = std::move(create_context_callback_).Run();
+    DCHECK(context_);
+  }
+
+  return context_.get();
+}
+
 void WebContentRunner::StartComponent(
     fuchsia::sys::Package package,
     fuchsia::sys::StartupInfo startup_info,
@@ -104,13 +119,10 @@
   RegisterComponent(std::move(component));
 }
 
-void WebContentRunner::GetWebComponentForTest(
-    base::OnceCallback<void(WebComponent*)> callback) {
-  if (!components_.empty()) {
-    std::move(callback).Run(components_.begin()->get());
-    return;
-  }
-  web_component_test_callback_ = std::move(callback);
+void WebContentRunner::SetWebComponentCreatedCallbackForTest(
+    base::RepeatingCallback<void(WebComponent*)> callback) {
+  DCHECK(components_.empty());
+  web_component_created_callback_for_test_ = std::move(callback);
 }
 
 void WebContentRunner::DestroyComponent(WebComponent* component) {
@@ -119,8 +131,8 @@
 
 void WebContentRunner::RegisterComponent(
     std::unique_ptr<WebComponent> component) {
-  if (web_component_test_callback_) {
-    std::move(web_component_test_callback_).Run(component.get());
-  }
+  if (web_component_created_callback_for_test_)
+    web_component_created_callback_for_test_.Run(component.get());
+
   components_.insert(std::move(component));
 }
diff --git a/fuchsia/runners/common/web_content_runner.h b/fuchsia/runners/common/web_content_runner.h
index c6ff2a5..825e2ff 100644
--- a/fuchsia/runners/common/web_content_runner.h
+++ b/fuchsia/runners/common/web_content_runner.h
@@ -9,17 +9,21 @@
 #include <fuchsia/web/cpp/fidl.h>
 #include <memory>
 #include <set>
+#include <vector>
 
 #include "base/callback.h"
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/fuchsia/scoped_service_binding.h"
 #include "base/macros.h"
+#include "base/optional.h"
 
 class WebComponent;
 
 // sys::Runner that instantiates components hosting standard web content.
 class WebContentRunner : public fuchsia::sys::Runner {
  public:
+  using CreateContextCallback = base::OnceCallback<fuchsia::web::ContextPtr()>;
+
   // Creates and returns a web.Context with a default path and parameters,
   // and with access to the same services as this Runner. The returned binding
   // is configured to exit this process on error.
@@ -42,17 +46,23 @@
   //   published. |on_idle_closure| will be invoked when the final client of the
   //   published service disconnects, even if one or more Components are still
   //   active.
-  // |context|: Context (e.g. persisted profile storage) under which all web
-  //   content launched through this Runner instance will be run.
+  // |create_context_callback|: A callback that, when invoked, connects a
+  //    fuchsia.web.Context under which all web content launched through this
+  //    Runner instance will be run.
   WebContentRunner(sys::OutgoingDirectory* outgoing_directory,
-                   fuchsia::web::ContextPtr context);
+                   CreateContextCallback create_context_callback);
+
+  // Alternative constructor for unpublished Runners.
+  explicit WebContentRunner(fuchsia::web::ContextPtr context);
+
   ~WebContentRunner() override;
 
-  fuchsia::web::Context* context() { return context_.get(); }
+  // Gets a pointer to this runner's Context, creating one if needed.
+  fuchsia::web::Context* GetContext();
 
   // Used by WebComponent instances to signal that the ComponentController
   // channel was dropped, and therefore the component should be destroyed.
-  void DestroyComponent(WebComponent* component);
+  virtual void DestroyComponent(WebComponent* component);
 
   // fuchsia::sys::Runner implementation.
   void StartComponent(fuchsia::sys::Package package,
@@ -61,22 +71,33 @@
                           controller_request) override;
 
   // Used by tests to asynchronously access the first WebComponent.
-  void GetWebComponentForTest(base::OnceCallback<void(WebComponent*)> callback);
+  void SetWebComponentCreatedCallbackForTest(
+      base::RepeatingCallback<void(WebComponent*)> callback);
 
- protected:
   // Registers a WebComponent, or specialization, with this Runner.
   void RegisterComponent(std::unique_ptr<WebComponent> component);
 
+ protected:
+  base::RepeatingCallback<void(WebComponent*)>
+  web_component_created_callback_for_test() const {
+    return web_component_created_callback_for_test_;
+  }
+
  private:
+  // If set, invoked whenever a WebComponent is created.
+  base::RepeatingCallback<void(WebComponent*)>
+      web_component_created_callback_for_test_;
+
+  CreateContextCallback create_context_callback_;
+
   fuchsia::web::ContextPtr context_;
   std::set<std::unique_ptr<WebComponent>, base::UniquePtrComparator>
       components_;
 
   // Publishes this Runner into the service directory specified at construction.
-  base::fuchsia::ScopedServiceBinding<fuchsia::sys::Runner> service_binding_;
-
-  // Test-only callback for GetWebComponentForTest.
-  base::OnceCallback<void(WebComponent*)> web_component_test_callback_;
+  // This is not set for child runner instances.
+  base::Optional<base::fuchsia::ScopedServiceBinding<fuchsia::sys::Runner>>
+      service_binding_;
 
   DISALLOW_COPY_AND_ASSIGN(WebContentRunner);
 };
diff --git a/fuchsia/runners/web/main.cc b/fuchsia/runners/web/main.cc
index 96985abb..0e1e39c 100644
--- a/fuchsia/runners/web/main.cc
+++ b/fuchsia/runners/web/main.cc
@@ -31,7 +31,8 @@
 
   WebContentRunner runner(
       base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(),
-      WebContentRunner::CreateDefaultWebContext(kWebRunnerFeatures));
+      base::BindOnce(&WebContentRunner::CreateDefaultWebContext,
+                     kWebRunnerFeatures));
 
   base::fuchsia::ComponentContextForCurrentProcess()
       ->outgoing()
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg
index 503c61e..391b47d 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -18,18 +18,6 @@
     url: "https://rota-ng.appspot.com/legacy/sheriff_ios.json"
   }
   oncalls {
-    name: "CrOS MTV"
-    url: "https://rota-ng.appspot.com/legacy/sheriff_cros_mtv.json"
-  }
-  oncalls {
-    name: "CrOS non-MTV"
-    url: "https://rota-ng.appspot.com/legacy/sheriff_cros_nonmtv.json"
-  }
-  oncalls {
-    name: "ChromeOS Gardener"
-    url: "https://rota-ng.appspot.com/legacy/sheriff_cr_cros_gardeners.json"
-  }
-  oncalls {
     name: "GPU"
     url: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
   }
@@ -254,75 +242,6 @@
   tree_status_host: "chromium-status.appspot.com"
 }
 
-headers {
-  id: "chromiumos"
-  oncalls {
-    name: "Sheriff"
-    url: "https://rota-ng.appspot.com/legacy/sheriff.json"
-  }
-  oncalls {
-    name: "Sheriff 2"
-    url: "https://rota-ng.appspot.com/legacy/sheriff2.json"
-  }
-  oncalls {
-    name: "Gardeners"
-    url: "https://rota-ng.appspot.com/legacy/sheriff_cr_cros_gardeners.json"
-  }
-  links {
-    name: "Builds"
-    links {
-      text: "status"
-      url: "https://chromiumos-status.appspot.com/"
-      alt: "Chromium OS status page"
-    }
-  }
-  links {
-    name: "ChromiumOS"
-    links {
-      text: "sources"
-      url: "https://chromium.googlesource.com/"
-      alt: "Source code project"
-    }
-    links {
-      text: "reviews"
-      url: "https://chromium-review.googlesource.com"
-      alt: "Chromium code review tool"
-    }
-    links {
-      text: "bugs"
-      url: "https://crbug.com"
-      alt: "Chromium bug tracker"
-    }
-    links {
-      text: "dev"
-      url: "http://dev.chromium.org/chromium-os"
-      alt: "ChromiumOS developer home page"
-    }
-  }
-  links {
-    name: "Navigate"
-    links {
-      text: "about"
-      url: "http://dev.chromium.org/developers/testing/chromium-build-infrastructure/tour-of-the-chromium-buildbot"
-      alt: "Tour of the console"
-    }
-    links {
-      text: "customize"
-      url: "https://chromium.googlesource.com/infra/experimental/+/infra/config/luci-milo-dev.cfg"
-      alt: "Customize this console"
-    }
-  }
-  console_groups {
-    console_ids: "chromium/chromiumos-Closers"
-    console_ids: "chromium/chromiumos-Full"
-    console_ids: "chromium/chromiumos-Incremental"
-    console_ids: "chromium/chromiumos-ASAN"
-    console_ids: "chromium/chromiumos-CommitQueue"
-    console_ids: "chromium/chromiumos.chromium"
-  }
-  tree_status_host: "chromiumos-status.appspot.com"
-}
-
 consoles {
   header_id: "chromium"
   id: "main"
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg
index 503c61e..391b47d 100644
--- a/infra/config/luci-milo.cfg
+++ b/infra/config/luci-milo.cfg
@@ -18,18 +18,6 @@
     url: "https://rota-ng.appspot.com/legacy/sheriff_ios.json"
   }
   oncalls {
-    name: "CrOS MTV"
-    url: "https://rota-ng.appspot.com/legacy/sheriff_cros_mtv.json"
-  }
-  oncalls {
-    name: "CrOS non-MTV"
-    url: "https://rota-ng.appspot.com/legacy/sheriff_cros_nonmtv.json"
-  }
-  oncalls {
-    name: "ChromeOS Gardener"
-    url: "https://rota-ng.appspot.com/legacy/sheriff_cr_cros_gardeners.json"
-  }
-  oncalls {
     name: "GPU"
     url: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
   }
@@ -254,75 +242,6 @@
   tree_status_host: "chromium-status.appspot.com"
 }
 
-headers {
-  id: "chromiumos"
-  oncalls {
-    name: "Sheriff"
-    url: "https://rota-ng.appspot.com/legacy/sheriff.json"
-  }
-  oncalls {
-    name: "Sheriff 2"
-    url: "https://rota-ng.appspot.com/legacy/sheriff2.json"
-  }
-  oncalls {
-    name: "Gardeners"
-    url: "https://rota-ng.appspot.com/legacy/sheriff_cr_cros_gardeners.json"
-  }
-  links {
-    name: "Builds"
-    links {
-      text: "status"
-      url: "https://chromiumos-status.appspot.com/"
-      alt: "Chromium OS status page"
-    }
-  }
-  links {
-    name: "ChromiumOS"
-    links {
-      text: "sources"
-      url: "https://chromium.googlesource.com/"
-      alt: "Source code project"
-    }
-    links {
-      text: "reviews"
-      url: "https://chromium-review.googlesource.com"
-      alt: "Chromium code review tool"
-    }
-    links {
-      text: "bugs"
-      url: "https://crbug.com"
-      alt: "Chromium bug tracker"
-    }
-    links {
-      text: "dev"
-      url: "http://dev.chromium.org/chromium-os"
-      alt: "ChromiumOS developer home page"
-    }
-  }
-  links {
-    name: "Navigate"
-    links {
-      text: "about"
-      url: "http://dev.chromium.org/developers/testing/chromium-build-infrastructure/tour-of-the-chromium-buildbot"
-      alt: "Tour of the console"
-    }
-    links {
-      text: "customize"
-      url: "https://chromium.googlesource.com/infra/experimental/+/infra/config/luci-milo-dev.cfg"
-      alt: "Customize this console"
-    }
-  }
-  console_groups {
-    console_ids: "chromium/chromiumos-Closers"
-    console_ids: "chromium/chromiumos-Full"
-    console_ids: "chromium/chromiumos-Incremental"
-    console_ids: "chromium/chromiumos-ASAN"
-    console_ids: "chromium/chromiumos-CommitQueue"
-    console_ids: "chromium/chromiumos.chromium"
-  }
-  tree_status_host: "chromiumos-status.appspot.com"
-}
-
 consoles {
   header_id: "chromium"
   id: "main"
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
index ece71d4..bb9412a0 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
@@ -11,6 +11,7 @@
 #import "ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator_implementation.h"
 #import "ios/chrome/browser/ui/infobars/infobar_container.h"
 #import "ios/chrome/browser/ui/infobars/modals/infobar_modal_view_controller.h"
+#include "ui/gfx/image/image.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -60,6 +61,9 @@
     self.bannerViewController.buttonText =
         base::SysUTF16ToNSString(self.confirmInfobarDelegate->GetButtonLabel(
             ConfirmInfoBarDelegate::BUTTON_OK));
+    gfx::Image modelIcon = self.confirmInfobarDelegate->GetIcon();
+    if (!modelIcon.IsEmpty())
+      self.bannerViewController.iconImage = modelIcon.ToUIImage();
   }
 }
 
diff --git a/ios/chrome/browser/web_state_list/web_state_list.mm b/ios/chrome/browser/web_state_list/web_state_list.mm
index 5b430cb..06c8828c 100644
--- a/ios/chrome/browser/web_state_list/web_state_list.mm
+++ b/ios/chrome/browser/web_state_list/web_state_list.mm
@@ -333,8 +333,13 @@
 }
 
 void WebStateList::CloseAllWebStates(int close_flags) {
+  const bool user_action = IsClosingFlagSet(close_flags, CLOSE_USER_ACTION);
+  for (auto& observer : observers_)
+    observer.WillCloseAllWebStates(this, user_action);
   while (!empty())
     CloseWebStateAt(count() - 1, close_flags);
+  for (auto& observer : observers_)
+    observer.DidCloseAllWebStates(this, user_action);
 }
 
 void WebStateList::ActivateWebStateAt(int index) {
diff --git a/ios/chrome/browser/web_state_list/web_state_list_observer.h b/ios/chrome/browser/web_state_list/web_state_list_observer.h
index 3b0d3cfb..79320fe7 100644
--- a/ios/chrome/browser/web_state_list/web_state_list_observer.h
+++ b/ios/chrome/browser/web_state_list/web_state_list_observer.h
@@ -85,6 +85,16 @@
                                    int active_index,
                                    int reason);
 
+  // Invoked before all WebStates are closed in the WebStateList. If the
+  // WebState is closed due to user action, |user_action| will be true.
+  virtual void WillCloseAllWebStates(WebStateList* web_state_list,
+                                     bool user_action);
+
+  // Invoked after all WebStates are closed in the WebStateList. If the WebState
+  // is closed due to user action, |user_action| will be true.
+  virtual void DidCloseAllWebStates(WebStateList* web_state_list,
+                                    bool user_action);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(WebStateListObserver);
 };
diff --git a/ios/chrome/browser/web_state_list/web_state_list_observer.mm b/ios/chrome/browser/web_state_list/web_state_list_observer.mm
index d703654..e9ccd1a 100644
--- a/ios/chrome/browser/web_state_list/web_state_list_observer.mm
+++ b/ios/chrome/browser/web_state_list/web_state_list_observer.mm
@@ -45,3 +45,9 @@
                                                web::WebState* new_web_state,
                                                int active_index,
                                                int reason) {}
+
+void WebStateListObserver::WillCloseAllWebStates(WebStateList* web_state_list,
+                                                 bool user_action) {}
+
+void WebStateListObserver::DidCloseAllWebStates(WebStateList* web_state_list,
+                                                bool user_action) {}
diff --git a/ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h b/ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h
index 656f363..6cc2d06d 100644
--- a/ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h
+++ b/ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h
@@ -68,6 +68,16 @@
                     atIndex:(int)atIndex
                      reason:(int)reason;
 
+// Invoked before all the WebStates are closed in the WebStateList. If the
+// WebState is closed due to user action, |userAction| will be true.
+- (void)webStateList:(WebStateList*)webStateList
+    willCloseAllWebStatesUserAction:(BOOL)userAction;
+
+// Invoked after all the WebStates are closed in the WebStateList. If the
+// WebState is closed due to user action, |userAction| will be true.
+- (void)webStateList:(WebStateList*)webStateList
+    didCloseAllWebStatesUserAction:(BOOL)userAction;
+
 @end
 
 // Observer that bridges WebStateList events to an Objective-C observer that
@@ -106,6 +116,10 @@
                            web::WebState* new_web_state,
                            int active_index,
                            int reason) override;
+  void WillCloseAllWebStates(WebStateList* web_state_list,
+                             bool user_action) override;
+  void DidCloseAllWebStates(WebStateList* web_state_list,
+                            bool user_action) override;
 
   __weak id<WebStateListObserving> observer_ = nil;
 
diff --git a/ios/chrome/browser/web_state_list/web_state_list_observer_bridge.mm b/ios/chrome/browser/web_state_list/web_state_list_observer_bridge.mm
index b4554c7..3b290ba 100644
--- a/ios/chrome/browser/web_state_list/web_state_list_observer_bridge.mm
+++ b/ios/chrome/browser/web_state_list/web_state_list_observer_bridge.mm
@@ -120,3 +120,25 @@
                       atIndex:active_index
                        reason:reason];
 }
+
+void WebStateListObserverBridge::WillCloseAllWebStates(
+    WebStateList* web_state_list,
+    bool user_action) {
+  const SEL selector = @selector(webStateList:willCloseAllWebStatesUserAction:);
+  if (![observer_ respondsToSelector:selector])
+    return;
+
+  [observer_ webStateList:web_state_list
+      willCloseAllWebStatesUserAction:(user_action ? YES : NO)];
+}
+
+void WebStateListObserverBridge::DidCloseAllWebStates(
+    WebStateList* web_state_list,
+    bool user_action) {
+  const SEL selector = @selector(webStateList:didCloseAllWebStatesUserAction:);
+  if (![observer_ respondsToSelector:selector])
+    return;
+
+  [observer_ webStateList:web_state_list
+      didCloseAllWebStatesUserAction:(user_action ? YES : NO)];
+}
diff --git a/ios/chrome/browser/web_state_list/web_state_list_unittest.mm b/ios/chrome/browser/web_state_list/web_state_list_unittest.mm
index e194ae7..4444972 100644
--- a/ios/chrome/browser/web_state_list/web_state_list_unittest.mm
+++ b/ios/chrome/browser/web_state_list/web_state_list_unittest.mm
@@ -38,6 +38,8 @@
     web_state_replaced_called_ = false;
     web_state_detached_called_ = false;
     web_state_activated_called_ = false;
+    will_close_all_webstates_called_ = false;
+    did_close_all_webstates_called_ = false;
   }
 
   // Returns whether WebStateInsertedAt was invoked.
@@ -57,6 +59,16 @@
     return web_state_activated_called_;
   }
 
+  // Returns whether WillCloseAllWebStates was invoked.
+  bool will_close_all_webstates_called() const {
+    return will_close_all_webstates_called_;
+  }
+
+  // Returns whether DidCloseAllWebStates was invoked.
+  bool did_close_all_webstates_called() const {
+    return did_close_all_webstates_called_;
+  }
+
   // WebStateListObserver implementation.
   void WebStateInsertedAt(WebStateList* web_state_list,
                           web::WebState* web_state,
@@ -96,12 +108,24 @@
     web_state_activated_called_ = true;
   }
 
+  void WillCloseAllWebStates(WebStateList* web_state_list,
+                             bool user_action) override {
+    will_close_all_webstates_called_ = true;
+  }
+
+  void DidCloseAllWebStates(WebStateList* web_state_list,
+                            bool user_action) override {
+    did_close_all_webstates_called_ = true;
+  }
+
  private:
   bool web_state_inserted_called_ = false;
   bool web_state_moved_called_ = false;
   bool web_state_replaced_called_ = false;
   bool web_state_detached_called_ = false;
   bool web_state_activated_called_ = false;
+  bool will_close_all_webstates_called_ = false;
+  bool did_close_all_webstates_called_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(WebStateListTestObserver);
 };
@@ -693,3 +717,40 @@
             web_state_list_.GetIndexOfLastWebStateOpenedBy(opener, start_index,
                                                            true));
 }
+
+// Test closing all webstates.
+TEST_F(WebStateListTest, CloseAllWebStates) {
+  AppendNewWebState(kURL0);
+  AppendNewWebState(kURL1);
+  AppendNewWebState(kURL2);
+
+  // Sanity check before closing WebStates.
+  EXPECT_EQ(3, web_state_list_.count());
+
+  observer_.ResetStatistics();
+  web_state_list_.CloseAllWebStates(WebStateList::CLOSE_USER_ACTION);
+
+  EXPECT_EQ(0, web_state_list_.count());
+
+  EXPECT_TRUE(observer_.web_state_detached_called());
+  EXPECT_TRUE(observer_.will_close_all_webstates_called());
+  EXPECT_TRUE(observer_.did_close_all_webstates_called());
+}
+
+// Test closing one webstate.
+TEST_F(WebStateListTest, CloseWebState) {
+  AppendNewWebState(kURL0);
+  AppendNewWebState(kURL1);
+  AppendNewWebState(kURL2);
+
+  // Sanity check before closing WebState.
+  EXPECT_EQ(3, web_state_list_.count());
+
+  observer_.ResetStatistics();
+  web_state_list_.CloseWebStateAt(0, WebStateList::CLOSE_USER_ACTION);
+
+  EXPECT_EQ(2, web_state_list_.count());
+  EXPECT_TRUE(observer_.web_state_detached_called());
+  EXPECT_FALSE(observer_.will_close_all_webstates_called());
+  EXPECT_FALSE(observer_.did_close_all_webstates_called());
+}
diff --git a/ios/web/public/test/web_view_interaction_test_util.mm b/ios/web/public/test/web_view_interaction_test_util.mm
index 5c75b91..5ec56cf 100644
--- a/ios/web/public/test/web_view_interaction_test_util.mm
+++ b/ios/web/public/test/web_view_interaction_test_util.mm
@@ -71,6 +71,14 @@
 
 CGRect GetBoundingRectOfElement(web::WebState* web_state,
                                 ElementSelector* selector) {
+#if !TARGET_IPHONE_SIMULATOR
+  // TODO(crbug.com/1013714): Replace delay with improved JavaScript.
+  // As of iOS 13.1, devices need additional time to stabalize the page before
+  // getting the element location. Without this wait, the element's bounding
+  // rect will be incorrect.
+  base::test::ios::SpinRunLoopWithMinDelay(base::TimeDelta::FromSecondsD(0.5));
+#endif
+
   std::string selector_script =
       base::SysNSStringToUTF8(selector.selectorScript);
   std::string selector_description =
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
index f71f441..739b1db 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -344,7 +344,7 @@
   frameHeight_ = height;
   frameRate_ = frameRate;
 
-  FourCharCode best_fourcc = kCVPixelFormatType_422YpCbCr8;
+  FourCharCode best_fourcc = kCMPixelFormat_422YpCbCr8_yuvs;
   const bool prefer_mjpeg =
       width > kMjpegWidthThreshold || height > kMjpegHeightThreshold;
   for (AVCaptureDeviceFormat* format in captureDevice_.formats) {
diff --git a/media/filters/fuchsia/fuchsia_video_decoder.cc b/media/filters/fuchsia/fuchsia_video_decoder.cc
index 29e08cc9..377977d4 100644
--- a/media/filters/fuchsia/fuchsia_video_decoder.cc
+++ b/media/filters/fuchsia/fuchsia_video_decoder.cc
@@ -1032,11 +1032,15 @@
 }
 
 void FuchsiaVideoDecoder::ReleaseInputBuffers() {
-  in_flight_input_packets_.clear();
   input_writer_queue_.ResetBuffers();
   input_buffer_collection_creator_.reset();
   input_buffer_collection_.reset();
   num_input_buffers_ = 0;
+
+  // |in_flight_input_packets_| must be destroyed after
+  // |input_writer_queue_.ResetBuffers()|. Otherwise |input_writer_queue_| may
+  // call SendInputPacket() in response to the packet destruction callbacks.
+  in_flight_input_packets_.clear();
 }
 
 void FuchsiaVideoDecoder::ReleaseOutputBuffers() {
diff --git a/net/BUILD.gn b/net/BUILD.gn
index a879882b..4b346ce 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1610,6 +1610,8 @@
       "third_party/quiche/src/quic/core/quic_interval.h",
       "third_party/quiche/src/quic/core/quic_interval_set.h",
       "third_party/quiche/src/quic/core/quic_lru_cache.h",
+      "third_party/quiche/src/quic/core/quic_mtu_discovery.cc",
+      "third_party/quiche/src/quic/core/quic_mtu_discovery.h",
       "third_party/quiche/src/quic/core/quic_one_block_arena.h",
       "third_party/quiche/src/quic/core/quic_packet_creator.cc",
       "third_party/quiche/src/quic/core/quic_packet_creator.h",
@@ -1726,6 +1728,9 @@
       "third_party/quiche/src/quic/platform/api/quic_uint128.h",
       "third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc",
       "third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h",
+      "third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc",
+      "third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h",
+      "third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h",
       "third_party/quiche/src/spdy/core/fifo_write_scheduler.h",
       "third_party/quiche/src/spdy/core/hpack/hpack_constants.cc",
       "third_party/quiche/src/spdy/core/hpack/hpack_constants.h",
@@ -5628,6 +5633,7 @@
     "third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc",
     "third_party/quiche/src/quic/platform/api/quic_text_utils_test.cc",
     "third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc",
+    "third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc",
     "third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc",
     "third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.cc",
     "third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h",
@@ -6691,6 +6697,17 @@
   ]
 }
 
+fuzzer_test("net_http_content_disposition_fuzzer") {
+  sources = [
+    "http/http_content_disposition_fuzzer.cc",
+  ]
+  dict = "data/fuzzer_dictionaries/net_http_content_disposition_fuzzer.dict"
+  deps = [
+    ":net_fuzzer_test_support",
+    "//net",
+  ]
+}
+
 fuzzer_test("net_http_proxy_client_socket_fuzzer") {
   sources = [
     "http/http_proxy_client_socket_fuzzer.cc",
diff --git a/net/cookies/canonical_cookie_fuzzer.cc b/net/cookies/canonical_cookie_fuzzer.cc
index be13c58..23a84af 100644
--- a/net/cookies/canonical_cookie_fuzzer.cc
+++ b/net/cookies/canonical_cookie_fuzzer.cc
@@ -38,11 +38,27 @@
   const base::Time expiration = getRandomTime(&data_provider);
   const base::Time last_access = getRandomTime(&data_provider);
 
+  const CookieSameSite same_site =
+      data_provider.PickValueInArray<CookieSameSite>({
+          CookieSameSite::UNSPECIFIED,
+          CookieSameSite::NO_RESTRICTION,
+          CookieSameSite::LAX_MODE,
+          CookieSameSite::STRICT_MODE,
+          CookieSameSite::EXTENDED_MODE,
+      });
+
+  const CookiePriority priority =
+      data_provider.PickValueInArray<CookiePriority>({
+          CookiePriority::COOKIE_PRIORITY_LOW,
+          CookiePriority::COOKIE_PRIORITY_MEDIUM,
+          CookiePriority::COOKIE_PRIORITY_HIGH,
+      });
+
   const std::unique_ptr<const CanonicalCookie> sanitized_cookie =
       CanonicalCookie::CreateSanitizedCookie(
           url, name, value, domain, path, creation, expiration, last_access,
-          data_provider.ConsumeBool(), data_provider.ConsumeBool(),
-          CookieSameSite::UNSPECIFIED, CookiePriority::COOKIE_PRIORITY_DEFAULT);
+          data_provider.ConsumeBool(), data_provider.ConsumeBool(), same_site,
+          priority);
 
   if (sanitized_cookie) {
     CHECK(sanitized_cookie->IsCanonical());
diff --git a/net/data/fuzzer_dictionaries/net_http_content_disposition_fuzzer.dict b/net/data/fuzzer_dictionaries/net_http_content_disposition_fuzzer.dict
new file mode 100644
index 0000000..d339b7c
--- /dev/null
+++ b/net/data/fuzzer_dictionaries/net_http_content_disposition_fuzzer.dict
@@ -0,0 +1,25 @@
+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+"inline"
+"attachment"
+"filename"
+"="
+"*="
+";"
+"\""
+"'"
+" "
+","
+"''"
+"\n"
+"?"
+"%"
+"en"
+"EUC-JP"
+"iso-8859-1"
+"utf-8"
+"windows-1253"
+"bogus_charset''foo.html'"
+"\\x"
diff --git a/net/http/http_content_disposition_fuzzer.cc b/net/http/http_content_disposition_fuzzer.cc
new file mode 100644
index 0000000..d6769e3
--- /dev/null
+++ b/net/http/http_content_disposition_fuzzer.cc
@@ -0,0 +1,18 @@
+// 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 <cstddef>
+#include <cstdint>
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "net/http/http_content_disposition.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  FuzzedDataProvider input{data, size};
+  auto charset = input.ConsumeRandomLengthString(100u);
+  auto header = input.ConsumeRemainingBytesAsString();
+  net::HttpContentDisposition content_disposition{header, charset};
+  return 0;
+}
diff --git a/net/http/http_content_disposition_unittest.cc b/net/http/http_content_disposition_unittest.cc
index 36e3994..fd31df3 100644
--- a/net/http/http_content_disposition_unittest.cc
+++ b/net/http/http_content_disposition_unittest.cc
@@ -499,4 +499,15 @@
   }
 }
 
+TEST(HttpContentDispositionTest, ContainsNul) {
+  const char kHeader[] = "filename=ab\0c";
+  const char kExpectedFilename[] = "ab\0c";
+  // Note: both header and expected_filename include the trailing NUL.
+  std::string header{kHeader, sizeof(kHeader)};
+  std::string expected_filename{kExpectedFilename, sizeof(kExpectedFilename)};
+
+  HttpContentDisposition content_disposition(header, "utf-8");
+  EXPECT_EQ(expected_filename, content_disposition.filename());
+}
+
 }  // namespace net
diff --git a/net/http/http_proxy_connect_job_unittest.cc b/net/http/http_proxy_connect_job_unittest.cc
index 3f569c6e..3371b0f 100644
--- a/net/http/http_proxy_connect_job_unittest.cc
+++ b/net/http/http_proxy_connect_job_unittest.cc
@@ -104,28 +104,34 @@
     HttpProxyConnectJob::UpdateFieldTrialParametersForTesting();
   }
 
-  scoped_refptr<TransportSocketParams> CreateHttpProxyParams() const {
+  scoped_refptr<TransportSocketParams> CreateHttpProxyParams(
+      bool disable_secure_dns) const {
     if (GetParam() != HTTP)
       return nullptr;
     return base::MakeRefCounted<TransportSocketParams>(
-        HostPortPair(kHttpProxyHost, 80), OnHostResolutionCallback());
+        HostPortPair(kHttpProxyHost, 80), disable_secure_dns,
+        OnHostResolutionCallback());
   }
 
-  scoped_refptr<SSLSocketParams> CreateHttpsProxyParams() const {
+  scoped_refptr<SSLSocketParams> CreateHttpsProxyParams(
+      bool disable_secure_dns) const {
     if (GetParam() == HTTP)
       return nullptr;
     return base::MakeRefCounted<SSLSocketParams>(
         base::MakeRefCounted<TransportSocketParams>(
-            HostPortPair(kHttpsProxyHost, 443), OnHostResolutionCallback()),
+            HostPortPair(kHttpsProxyHost, 443), disable_secure_dns,
+            OnHostResolutionCallback()),
         nullptr, nullptr, HostPortPair(kHttpsProxyHost, 443), SSLConfig(),
         PRIVACY_MODE_DISABLED, NetworkIsolationKey());
   }
 
   // Returns a correctly constructed HttpProxyParams for the HTTP or HTTPS
   // proxy.
-  scoped_refptr<HttpProxySocketParams> CreateParams(bool tunnel) {
+  scoped_refptr<HttpProxySocketParams> CreateParams(bool tunnel,
+                                                    bool disable_secure_dns) {
     return base::MakeRefCounted<HttpProxySocketParams>(
-        CreateHttpProxyParams(), CreateHttpsProxyParams(), false /* is_quic */,
+        CreateHttpProxyParams(disable_secure_dns),
+        CreateHttpsProxyParams(disable_secure_dns), false /* is_quic */,
         HostPortPair(kEndpointHost, tunnel ? 443 : 80),
         /*is_trusted_proxy=*/false, tunnel, TRAFFIC_ANNOTATION_FOR_TESTS,
         NetworkIsolationKey());
@@ -133,16 +139,19 @@
 
   std::unique_ptr<HttpProxyConnectJob> CreateConnectJobForHttpRequest(
       ConnectJob::Delegate* delegate,
-      RequestPriority priority = DEFAULT_PRIORITY) {
-    return CreateConnectJob(CreateParams(false /* tunnel */), delegate,
-                            priority);
+      RequestPriority priority = DEFAULT_PRIORITY,
+      bool disable_secure_dns = false) {
+    return CreateConnectJob(
+        CreateParams(false /* tunnel */, disable_secure_dns), delegate,
+        priority);
   }
 
   std::unique_ptr<HttpProxyConnectJob> CreateConnectJobForTunnel(
       ConnectJob::Delegate* delegate,
-      RequestPriority priority = DEFAULT_PRIORITY) {
-    return CreateConnectJob(CreateParams(true /* tunnel */), delegate,
-                            priority);
+      RequestPriority priority = DEFAULT_PRIORITY,
+      bool disable_secure_dns = false) {
+    return CreateConnectJob(CreateParams(true /* tunnel */, disable_secure_dns),
+                            delegate, priority);
   }
 
   std::unique_ptr<HttpProxyConnectJob> CreateConnectJob(
@@ -220,7 +229,8 @@
     // since tunnels need an extra round trip.
     base::TimeDelta alternate_connection_timeout =
         HttpProxyConnectJob::AlternateNestedConnectionTimeout(
-            *CreateParams(true /* tunnel */), network_quality_estimator_.get());
+            *CreateParams(true /* tunnel */, false /* disable_secure_dns */),
+            network_quality_estimator_.get());
 
     // If there's an alternate connection timeout, and it's less than the
     // standard TCP+SSL timeout (Which is also applied by the nested connect
@@ -833,6 +843,24 @@
   }
 }
 
+TEST_P(HttpProxyConnectJobTest, DisableSecureDns) {
+  for (bool disable_secure_dns : {false, true}) {
+    TestConnectJobDelegate test_delegate;
+    std::unique_ptr<ConnectJob> connect_job = CreateConnectJobForHttpRequest(
+        &test_delegate, DEFAULT_PRIORITY, disable_secure_dns);
+
+    EXPECT_THAT(connect_job->Connect(), test::IsError(ERR_IO_PENDING));
+    EXPECT_EQ(disable_secure_dns,
+              session_deps_.host_resolver->last_secure_dns_mode_override()
+                  .has_value());
+    if (disable_secure_dns) {
+      EXPECT_EQ(
+          net::DnsConfig::SecureDnsMode::OFF,
+          session_deps_.host_resolver->last_secure_dns_mode_override().value());
+    }
+  }
+}
+
 // Make sure that HttpProxyConnectJob does not pass on its priority to its
 // SPDY session's socket request on Init, or on SetPriority.
 TEST_P(HttpProxyConnectJobTest, SetSpdySessionSocketRequestPriority) {
@@ -1516,7 +1544,7 @@
   // since tunnels need an extra round trip.
   base::TimeDelta alternate_connection_timeout =
       HttpProxyConnectJob::AlternateNestedConnectionTimeout(
-          *CreateParams(true /* tunnel */),
+          *CreateParams(true /* tunnel */, false /* disable_secure_dns */),
           nullptr /* network_quality_estimator */);
 
 #if defined(OS_ANDROID) || defined(OS_IOS)
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 8b270bf2..32b3f7f 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -2440,7 +2440,6 @@
     { "name": "axka.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "bitcoin.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blablacar.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "blablacar.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blablacar.com.tr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blablacar.com.ua", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blablacar.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -4121,7 +4120,6 @@
     { "name": "edpubs.gov", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "eeqj.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "elitefishtank.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "endofnet.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "englerts.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "eugenekay.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "evasovova.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -4927,7 +4925,6 @@
     { "name": "isondo.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jacobphono.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jamesrains.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "jayharris.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jcraft.us", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jennythebaker.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jonaskjodt.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -6614,7 +6611,6 @@
     { "name": "dewalch.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dfranke.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "diddens.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "digitalriver.tk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "directme.ga", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dittvertshus.no", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dizorg.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -7669,7 +7665,6 @@
     { "name": "liquidcomm.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "loadingdeck.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "locomotive.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "loony.info", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "lovemomiji.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "lpak.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "lynkos.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -9464,7 +9459,6 @@
     { "name": "mrnonz.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "mrpopat.in", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "mtg-esport.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "mtn.cc", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "mumei.space", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "murfy.nz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "murodese.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -10738,7 +10732,6 @@
     { "name": "drew.red", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dollarstore24.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "docbox.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "dossplumbing.co.za", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "doubleavineyards.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "duelysthub.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dreamlinehost.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -10867,7 +10860,6 @@
     { "name": "happygastro.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "gold24.in", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hdrboundless.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "hausarzt-stader-str.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hatcherlawgroupnm.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hepteract.us", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hartlep.email", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -15535,7 +15527,6 @@
     { "name": "vlogge.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "vitsoft.by", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "vician.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "warehost.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "whatwebcando.today", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "wowjs.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "web-vision.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -24801,7 +24792,6 @@
     { "name": "mikro-inwestycje.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "mikropixel.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "milesapart.dating", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "militarycarlot.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "milkingit.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "min-sky.no", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "minakov.pro", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -25206,7 +25196,6 @@
     { "name": "plustech.id", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "pluta.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "pocketmemories.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "pocobelli.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "podcast.style", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "podiumsdiskussion.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "poe.digital", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -27297,7 +27286,6 @@
     { "name": "ebop.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "eworksmedia.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "exeintel.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "evolutionpets.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "example.wf", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "evilarmy.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "epistas.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -28240,7 +28228,6 @@
     { "name": "mohanmekap.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "miguel.pw", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "mobil-bei-uns.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "misrv.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "lookart.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "millionairessecrets.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "meu-solutions.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -28261,7 +28248,6 @@
     { "name": "monteurzimmerfrei.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "moneytoday.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "moonrhythm.info", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "moonrhythm.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "mojoco.co.za", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "moppeleinhorn.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "mojefilmy.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -29906,7 +29892,6 @@
     { "name": "bevnut.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "belpbleibtbelp.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "beetgroup.id", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "beverlyinternational.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "beingmad.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "anwaltsindex.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "belfasttechservices.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -30250,7 +30235,6 @@
     { "name": "drlangsdon.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "edeca.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "eklepka.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "drfrey.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "elias-nicolas.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "elhossari.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "ecoterramedia.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -30682,7 +30666,6 @@
     { "name": "kremalicious.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kabashop.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "keycenter.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "ken-electric.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kitchen-profi.by", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kobofarm.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kostecki.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -31521,7 +31504,6 @@
     { "name": "swisswebhelp.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tjl.rocks", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "titanlab.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "theroks.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "thomasetsophie.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tomticket.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "timbishopartist.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -33767,7 +33749,6 @@
     { "name": "inforisposte.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "infoworm.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "inge-r.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "innerform.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "innovation-workshop.ro", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "instawi.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "instelikes.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -34753,7 +34734,6 @@
     { "name": "akazakov.info", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "akijo.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "akritikos.info", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "alviano.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "americafamilylawcenter.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "andrew.fi", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "andrewprokos.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -35819,8 +35799,6 @@
     { "name": "derbybouncycastles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "derdewereldrommelmarkt.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "derehamcastles.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "derekseaman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "derekseaman.studio", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "detalyedesigngroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "detroitzoo.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dev-brandywineglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -37280,7 +37258,6 @@
     { "name": "martijn.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mashandco.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mashandco.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "mathias.re", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "maxwellmoore.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mdiv.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "media-credit.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -38395,7 +38372,6 @@
     { "name": "labcoat.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "landinfo.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lascana.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lebarbatruc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ledeguisement.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lemonop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lenguajedeprogramacion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -39171,7 +39147,6 @@
     { "name": "esb16888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "esb17888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "esb222.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "esb555.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "esb555.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "esb556.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "esb5889.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -39285,7 +39260,6 @@
     { "name": "frejasdal.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "frugal-millennial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fs-community.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "fullhost.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "futurehack.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fwest98.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gaff-rig.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -39710,7 +39684,6 @@
     { "name": "mycareersfuture.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "myessaygeek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mygreatlakes.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "mymarketingcourses.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mypaperdone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "myref.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mysexydate24.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -40303,7 +40276,6 @@
     { "name": "yacineboumaza.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yannick.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yenibilgi.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "yetishirt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yocchan1513.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yoga-alliance-teacher-training.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yongbin.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -40591,7 +40563,6 @@
     { "name": "dunamiscommunity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dushu.cat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "e-tonery.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "eastmidlandsstargazers.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "easyoutdoor.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "easyroad.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ecocreativity.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -43926,7 +43897,6 @@
     { "name": "l.me.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lacantine.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ladadate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "laharilais.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lamclam.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lame1337.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "laperfumista.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -46351,7 +46321,6 @@
     { "name": "aprikaner.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aproposcomputing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "arise19.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "arnsmedia.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "arswb.men", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "arts.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "asianbet77.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -48192,7 +48161,6 @@
     { "name": "elektrotechnik-kaetzel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elhorizontal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elie.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "elstopstelten.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "eltrox.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "enderszone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "envoyworld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -48493,7 +48461,6 @@
     { "name": "norbertschneider-music.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ntcoss.org.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nubeslayer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "nzws.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oakparkexteriorlighting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oakparklandscapelighting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oakparklighting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -48657,7 +48624,6 @@
     { "name": "somersetwellbeing.nhs.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sonavankova.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "songsmp3.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "sportbetuwe.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sporttown.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "spritsail.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ssconn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -48700,7 +48666,6 @@
     { "name": "thousandoaksoutdoorlighting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thpay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tiim.technology", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tomarns.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tonnycat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "topservercccam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "topservercccam.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -50055,7 +50020,6 @@
     { "name": "aoaprograms.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "autoschadeschreuder.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "axtudo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "banes.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "behindthethrills.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "benjaminkopelke.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "benz-hikaku.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -50231,7 +50195,6 @@
     { "name": "nextcloud.nerdpol.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nhgteam.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ninverse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "noofficewalls.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nootronerd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nosqlzoo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nutpanda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -50953,7 +50916,6 @@
     { "name": "jej.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jej.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jelmoli-shop.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "jeroensangers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jerryweb.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jf-fotos.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jitlab.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -50989,7 +50951,6 @@
     { "name": "komenamanda.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kotobox.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kucukayvaz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "labspack.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lanahallen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "landlordy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "landscape-photography.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -51238,7 +51199,6 @@
     { "name": "promo-brille.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "propertyinside.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "protech.ge", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "protectr.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "prowise.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "psici.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "psicologajanainapresotto.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -51461,7 +51421,6 @@
     { "name": "thehoryzon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thelatedcult.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thepoplarswines.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "thepurem.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thereisnocloud.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "theworldexchange.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "theworldexchange.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -53951,7 +53910,6 @@
     { "name": "eveonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "evtasima.name.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "examedge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "exnovin.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "exordiumconcepts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "experise.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "expertofficefitouts.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -57291,7 +57249,6 @@
     { "name": "hearinghelpexpress.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hebamme-cranio.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hellerarko.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "hellerup.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hemtest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hennies.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "heromuster.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -58027,7 +57984,6 @@
     { "name": "sproutways.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "spt.re", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sqsd.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "srichan.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ssl24.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "stadtkapelle-oehringen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "stainternational.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -58326,7 +58282,6 @@
     { "name": "233now.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "3dgep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "52hentai.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "adventuredrives.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "affarsnatverk.nu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "afterdwi.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "agenceactiv.immo", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -58795,7 +58750,6 @@
     { "name": "bestdoc.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "besti.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bestpractice.domains", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "bet.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "betonmarkets.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bgp.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bibica.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -59108,7 +59062,6 @@
     { "name": "lampsh.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lancelhoff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lancemanion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "larotayogaming.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "latinmusicrecords.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "leaf-consulting.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lehmitz-weinstuben.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -60831,7 +60784,6 @@
     { "name": "whocalledme.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wikilivres.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "winfographics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "withdewhua.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wmcns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wolfcrow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "woshiluo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -63136,7 +63088,6 @@
     { "name": "wangqr.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wanmen.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wardslager.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "weblegion.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "webmaster-infographiste-lyon.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "websa.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "weidehelp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -63892,7 +63843,6 @@
     { "name": "ql.tc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "qoacher.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "qqiao.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "qualitylogoproducts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "raeder-test.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "razvodguru.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "reactivelambda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -64064,7 +64014,6 @@
     { "name": "deconsolas.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "deltaservers.blog.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "devinite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "dewolden.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "die-besten-bewertungen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "digaxtest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "digitec.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -64117,7 +64066,6 @@
     { "name": "heraldik-wiki.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hiczp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "highkick.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "hoogeveen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "host97.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "houseandgarden.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "htmanager.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -64301,7 +64249,6 @@
     { "name": "vuldb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vvild.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wasteman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "wettbonus.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "whitevpn.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wigmore-hall.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wijwillendit.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -65519,7 +65466,6 @@
     { "name": "elitsa.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ell888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "emigratieplanner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "emiliobonelli.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "enderle.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "energy-healings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "enterclaim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -65852,7 +65798,6 @@
     { "name": "neuropatia-periferica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nextcloud.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nextcloud.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "nguyenhongson.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nhakhoangocanh.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nicogrosser.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nicolas-simond.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -66371,7 +66316,6 @@
     { "name": "youdamom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yourcleaningcompany.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yoyoost.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "z8022.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zbib.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zenidees.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zhaostephen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -69942,7 +69886,6 @@
     { "name": "shelbymunsch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "shibbydex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "siikaflix.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "sjamaan.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "skolnilogin.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "skolniweby.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sldlcdn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -70243,7 +70186,6 @@
     { "name": "dd6957.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "deal30.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "debierhandel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "dedoho.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "deeplink-medical.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "defibrillateur.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "delpark.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -70358,7 +70300,6 @@
     { "name": "kiumie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "knoxvilleimplants.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "koffie-enzo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "kukoon.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kulpakko.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kunstkieken.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lasabina.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -71249,7 +71190,6 @@
     { "name": "jaja.wtf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "janome.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "javaweb.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "jcsdevelopment.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jellysquid.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jenniferlucia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jordanhamilton.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73363,7 +73303,6 @@
     { "name": "elementarewatson.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elitedangerous.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "emergesydney.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "encd.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ep-cortex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "epilepsiyle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "es-tools.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73439,7 +73378,6 @@
     { "name": "ishimen.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "j3349.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jackingsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "jarv.is", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "javiscoffee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jerome.to", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jewelers.expert", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73709,7 +73647,6 @@
     { "name": "z8109.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "z8132.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "z8182.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "z8233.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "z8851.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "z8922.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zaffke.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -75395,17 +75332,6 @@
     { "name": "ezik-ido.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "f30365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "f51365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9850.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9851.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9852.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9854.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9855.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9880.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9881.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9882.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9883.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9884.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "f9885.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "factslider.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fairyth.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fake-show.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -76618,24 +76544,9 @@
     { "name": "test-school.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "testthis.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "textpages.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo0000.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo0088.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo1111.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo2222.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tgo3333.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tgo4444.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo456.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tgo5555.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo58.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo6688.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo7777.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo7788.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo789.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo8899.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgo9988.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgoaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgoall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tgoasia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thaiboystory.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thaihotmodels.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thaiportal.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -77054,7 +76965,6 @@
     { "name": "xpjai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xucha.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xx6396.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "y09a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "y30365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "y3650.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "y36500.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -77276,7 +77186,6 @@
     { "name": "365securitymg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "365yapan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "369028.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "369038.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "3963dd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "5017501.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "5017502.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -77302,7 +77211,6 @@
     { "name": "6810app.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "6830521.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "690918.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "690928.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "700wns.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "7g31.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "7win.am", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -77481,7 +77389,6 @@
     { "name": "areacinquentaeum.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "arquitet.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "artcenter.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "as398.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "asabacortoscaseros.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "asana.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "asdchieti.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -77969,7 +77876,6 @@
     { "name": "kamildrozd.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kapelya.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kareltrans.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "karhoo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "karimsaadati.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kariyam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kateysagal.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -79691,7 +79597,6 @@
     { "name": "queryquinton.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "quhyu.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ramsaver.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "raphaelschmid.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "realgogo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "rebelbranding.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "renyiyou.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -79932,10 +79837,7 @@
     { "name": "cyberforensics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d81818.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d88.cn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d8855.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d8877.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d88agent.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88f.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "damifph.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "danielkeppler.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "decologisticsgh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80163,7 +80065,6 @@
     { "name": "pepperandpartner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "petwatchersnj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pierreau.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "piloten.digital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pisf.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "playmytime.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "podcrto.si", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80427,8 +80328,6 @@
     { "name": "creamyfox.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ctes.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d8814.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d8899.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88h.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "daily-exps.herokuapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "daimafengzi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "danielkanchev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80452,7 +80351,6 @@
     { "name": "dyneco.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "earthsgoldmine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "easyeditcms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "echtgeld-casino.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "electricfenceboksburg.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "electricfenceroodepoort.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "elo-rocket.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -80799,10 +80697,6 @@
     { "name": "creativeideasagency.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cryptex.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ctf-albstadt.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88a.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88b.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88e.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88g.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "daunatotala.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "de-kramers.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "deckersheaven.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -81188,7 +81082,6 @@
     { "name": "bog8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bombayfashionclub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "boschsplit.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "bread.red", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "buyplore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cambiemosjuegos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "camshowhive.to", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -81211,7 +81104,6 @@
     { "name": "crossformer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cubsbestteaminbaseball.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cvtshop.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88c.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dapperdom.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "davidschubert.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dbw678.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -81938,7 +81830,6 @@
     { "name": "primglaz.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "proweb.solutions", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pugetsoundspas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "punematka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "qosmoschools.edu.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "quiz4math.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ra3y.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -81966,7 +81857,6 @@
     { "name": "sand66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sanjosecolorectal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sarjakuvakauppa.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "sattamatkamobi.mobi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sattaresult.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "secapp.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sedesignxtra.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -82321,7 +82211,6 @@
     { "name": "jeansdiscounter.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "junglevet.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "justin-p.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "kalyanmatka.guru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kb0404.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kb0505.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kb096.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -82977,7 +82866,6 @@
     { "name": "my-web.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "myphamthemis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nan.cm", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "nashikmatka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "natmal.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "noahenco.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nocloud.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83111,7 +82999,6 @@
     { "name": "wuz.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xn--5kv19nxn6b.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xn--birkenblttertee-7kb.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xtremeperformance.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xuwei.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xxxbunker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xzibits.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83370,7 +83257,6 @@
     { "name": "992z6.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "993z6.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "995z6.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "996z6.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "997z6.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "998z6.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "9kopb.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83483,12 +83369,9 @@
     { "name": "d88322.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d88333.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d88522.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88787.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d888.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d888.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d888.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88871.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "d88969.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d88998.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dark.fail", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dayman.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83673,7 +83556,6 @@
     { "name": "lisasworkshop.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "listyourinfo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lockr.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "long139.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lowcarbmaven.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lrs.lt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ltprtz.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83890,7 +83772,6 @@
     { "name": "ybdh88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ycwt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yuanbaohd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "yuppi.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yy6.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yy8.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "z1.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -84566,7 +84447,6 @@
     { "name": "lc861.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc862.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc863.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lc865.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "le-cameleon.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "leemankuiper.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lelux.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -84748,7 +84628,6 @@
     { "name": "u00228.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ucngame.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "uddin.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "unionconsulting.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "uwe-r.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "uwe.training", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v5017.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -84824,10 +84703,6 @@
     { "name": "xinpujing200.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xinpujing518.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xinpujing918.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xn--80aacilurl7aclgj2aw2e.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xn--80accdc8alelmbe9n.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xn--80aeczhjbkbcw0bk0h.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xn--80akcnmdfaffwoxl7h.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xs00228.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "y68aa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "y68cc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -85084,7 +84959,6 @@
     { "name": "elvendrim.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "emoxie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "endbox.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "enghost.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "erichoekstra.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "erichoekstra.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "erkiss.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -85451,6 +85325,633 @@
     { "name": "zalure.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zdenekpasek.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zenassociates.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "040552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "041552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "042552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "046552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "049552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "04d.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "051552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "054552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "068552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "071552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "084552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "09000113.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "0x7.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "12l.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "131k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "132k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "136k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "136k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "137k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "137k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "138k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "139k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "142552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "146552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "151k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "151k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "152k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "152k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "154552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "155k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "155k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "156k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "157k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "158k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "159k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "159k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1stcarpetcleaning.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033002.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033003.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033004.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033005.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033006.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033007.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033008.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033009.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033010.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2033011.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22245j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22256j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "241552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "242552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "24hourelectricalservices.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "266k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "347552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651143.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651145.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651146.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651147.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3651149.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533c.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533e.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533f.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533g.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533h.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533i.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533l.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533m.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533n.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533o.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533p.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533r.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533s.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533u.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "36533v.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q01.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q02.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q03.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q04.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q05.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q06.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q07.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q08.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q10.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q11.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q12.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q14.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365q15.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "366k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "4151365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "420screen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "427552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "457552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "487552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "497552.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "566k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "5k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "60062b.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "60062h.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "60062i.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "611121.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "611125.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "662k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6666365q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "66689j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "666k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "66k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6k662.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6k663.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6k666.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6k666.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6k669.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "755204.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "755245.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "755246.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "755249.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "755274.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "755284.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "755294.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "766k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "7777365q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "77zxdy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "7878365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "7k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "7k66.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8225.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "866k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "886k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "887k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8881234j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8882345j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "888234j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8883456j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "888345j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8884567j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "888456j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "888567j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8886789j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8888365q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "888k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "889vip5.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "8k66.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "966k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "99123j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "99456j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "99789j.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "998k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "9999365q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "999k66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aaainfosystems.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abrikos.group", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "accs.org.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ackis.duckdns.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adminrezo.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agences-cegee.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aimiastestseries.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aland.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alice-of-alice.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alkemi-si.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allisonchapleau.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ammrio.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amperaa.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aotearoafreepress.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "apod.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "apollo-auto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aqua-ferra.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arnove.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arteerotiko.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "artofhappyliving.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aspireuniversal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aspirevc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aussiemilfs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "background-checks-systems.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "background-checks.asia", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "background-checks.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "background-checks.mobi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "backgroundchecks.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bairuo.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bandolino-bewind.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bandolino.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "barnflix.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "baypromoteam.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beautyandfashionadvice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bernmail.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestbuyzone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestprint.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bettercleaningcompany.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beverhof.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biotera.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biz-architect.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bluehillhosting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bluesoap.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bobstenancycleaning.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bocawa.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boomkins.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boxt.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brindisi.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brucherlaw.lu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buddyme.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buri.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bvgt.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bytynazizkove.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "c36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cadep2019.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "canada.ind.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "canttboardpachmarhi.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "car-spaw-rac.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "careertransformed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carium.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carwashdruten.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cdf.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cdnya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ceiba.com.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cgp.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chadlenz.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chianti2002.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chineserecipes.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chloes.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chpwmedicare.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ciagutek.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cineworld.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "citsc.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "claumarservice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coinclickz.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courses-nlp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "craterx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crazymarvin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyber-travel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "d36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dandan101.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "datacommissioner.gov.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "de8468.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "defendtheweb.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dekel.co.il", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "delhitalkie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deltafinanceiro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deltaloja.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "devicom.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "devlinjurister.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dhit.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dianadrive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dipietro.id.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "discarica.napoli.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "discounto.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "divjak.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dmarcian.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doadaybook.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doanhnhankhanhhoa.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doinaruscior.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "draireneborro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drradin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dspropertyservicesltd.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "e36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "easycosmetic.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ecriminalrecords.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "edtech.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "edukador.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eion.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eisen-biomed.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elektrownie-tanio.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emeliemai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emmiwelentain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "employment-applicant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emptybox.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "epicsoft.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "equabanking.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "erty.stream", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esfahanahan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esoteric.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "f36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "f8908.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "familiearchivaris.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "familytreesbyjackie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "faretrotter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "farodeluz.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "felixklenner.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ffg.berlin", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fietsvierdaagsen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flassetlocators.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "forensicsoftware.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freedygist.org.ng", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "friendlycleaners.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frovi.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fullmoviez.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fxstrategics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "g36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "galaxyscientific.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gamewinninggoal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gearwise.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "genealogiewerkbalk.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gentlent.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "girl.science", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "glidestep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "globemusic.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gnaucke.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gogs.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goover.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gospicers.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gratefullane.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greekplots.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greiner-it.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greinerj.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "groupescr.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "grupoalpi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gryinx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "h36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hakkasan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hardfloorcleaninglondon.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heathersmithcommercial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hermiu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heyapakabar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hifly.com.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "himalayanyogashram.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hobby-freizeit.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "holtslander.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "holundersberg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homeportal.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hydroponicglobal.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "i36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "icecutethings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "illange.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inspiresurgery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "intrixgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "intrixlifestyle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inyr.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ipinfo.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "irenkuhn.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "isaob.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ispfontela.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "it-market.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ivetazivot.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iwashealthy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "j36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jan.gl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jkvov.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jmlogistica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joanjensen.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joyofhaskell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jrt.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "juliuseskola.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jumpingdeliege-vip.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jwtv2.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k66.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k663.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k663.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k665.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k6666.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k66666.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k6668.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k667.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k668.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k668.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k6688.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k669.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaibo.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kanpian369.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaputtzich.duckdns.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kartashev.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "keoliz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kernkompas.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kkcinemas.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kochbar.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kojy.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kranjnakolo.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kubanitoscali.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kzmhk.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "l36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "langleyporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laurajeandesigns.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ld66999.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ld6999.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leathersofacleaning.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lelux.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lewiatan.opole.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lidl-shop.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lidl-sklep.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lidlonline.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "liebt.schule", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lightningwirelabs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lincore.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "liveint.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "loveluna.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lxx4380.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lyonslawlink.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "m36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mademoe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnes.priv.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnesy-neodymowe.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnesy-neodymowe.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnesy-tanio.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnesy.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnesy.net.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnesy.priv.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "manicminers.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "markxpdesign.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "martinelias.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mateuszmajewski.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matt.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matts.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matts.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maxuniverse.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mcjars.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mediasst.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "medsourcelabs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "memorind.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mercadosex.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meridanas.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mgae.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mia.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mijngeldcoach.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mimolo.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mist79.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mittwoch-nacht.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mkm.szczecin.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mmxblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mo-mochizuki.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moca-2080.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moneyfortitude.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "montrain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moteksystems.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mott.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "move-out-cleaning.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mservers.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mt-tech.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mtasts.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "musicinsiderdigest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myofficeconnect.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myoptimalbrain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mypt3.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "n36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nepozitkova.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netolink.co.il", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netolink.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "niklasstinkt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nixnet.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nrvc.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nzelaweb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "o36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oberhof-hotel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oceanlogisticgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "octopuslab.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ocupat.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "odegua.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oegd.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ololmke.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "omega-marijuana.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "omshivalab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onlinestoresite.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "opsre.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "optigear.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "optimalrehab.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "optimumterapia.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orphee-beaute.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ostylelimo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "otus.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "overspeed.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "p36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paramountelectronics.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "patchyvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "planovivofibra.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "poolmans.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "postari.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "preparetheword.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pressplayandrelax.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prexxorvita.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "primelogistics.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "producentbalustrad.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "projectborealisgitlab.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prolinq.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proshow.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "protocol.co.il", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prove-uru.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "providentins.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prvcy.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pure-host.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qr70.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "r36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rcjescrow.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redpen.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redsequence.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reflectiondentallasvegas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "restaurant-fujiyama.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "revworld.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rezendemultimarcas.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rhubarb.land", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ricomp.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rmdscreen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rtd.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rugcleaninglondon.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rusdigisolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rutracker.appspot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "s-socks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "s36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sakenohana.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "samindgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "santi-club.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scanwords.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scenariossecuritygroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seandawson.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seccast.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "serverhost.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sggame990.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shepherdsfriendly.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shymeck.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "simplemining.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sinargasht.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sinhnhatbaby.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sittogether.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skydiverapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slan.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slidesvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slyvon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smoothiecriminals.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smtenants.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sofacleanerslondon.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "softweb-dev.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soko.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soterdev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soupbuahtaza.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sphericalvision.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spmax.design", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spmax.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sprossenwand.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ssrr.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stagemaster.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stamboomforum.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "statuswatch.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stevenselectricllc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stonearm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stormboost.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "strelnicesmirice.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sunsetdentalhenderson.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "supercharged.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swapfin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swmlink.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "systemdynamics.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "szkolajazdykaleta.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taffe-elec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taxisaeropuertomadrid.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tcgpraktijk.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "telhabrasil.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theartistjournal.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theindiantrip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thelittlepeartree.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thomasbnt.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totalemaiildelivery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totalemaiilldelivery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totalemaildeliivery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totalemaildellivery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totalemailldeliivery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totalemailldelivery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totallemaiildelivery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totallemaildelivery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trabajaenvitamina.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "traiteur-laporte.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "turbomag.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "txtfile.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "typeclasses.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "u36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ubicaciones-vitamina.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "umcpc.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unblocked.ltda", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unidrogas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "universoscuola.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "upbtrbt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "upbtrbt.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "upbtrbt.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "upbtrbt.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "upbtrbt.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "us-10.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "usapublicrecords.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "usmiddleclass.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ustaywell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "utiars.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uxp-it.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "v0v.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "v36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vegetalvalley.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vicenez.agency", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "videodrome.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "viewbykrian.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "visualmarketingdeals.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "visvolunteers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vitavista.health", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vocationnetwork.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vponline.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "w36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "watchesonwrist.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "watchmoviesgallery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "watzijnmijnkerntalenten.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "weadvize.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wealthadvisorsmf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webceo.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webservertalk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webzoly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wkz.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wowprezi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "www-8225.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "x36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xinxin.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xlink.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xmag.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xxgalgame.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xyz.blue", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "y36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yauatcha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yogamexico.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yogshrihealing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "youber.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yourcareerhost.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yzblack.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "z36533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zaixsp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zambranopublicidadvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zlol.lg.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zuim.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zurlin.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     // END OF 1-YEAR BULK HSTS ENTRIES
 
     // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/quic/platform/impl/quic_flag_utils_impl.h b/net/quic/platform/impl/quic_flag_utils_impl.h
index b50e3e0..974893bc 100644
--- a/net/quic/platform/impl/quic_flag_utils_impl.h
+++ b/net/quic/platform/impl/quic_flag_utils_impl.h
@@ -6,6 +6,7 @@
 #define NET_QUIC_PLATFORM_IMPL_QUIC_FLAG_UTILS_IMPL_H_
 
 #include "base/logging.h"
+#include "net/quic/platform/impl/quic_flags_impl.h"
 
 #define QUIC_RELOADABLE_FLAG_COUNT_IMPL(flag) \
   DVLOG(3) << "FLAG_" #flag ": " << FLAGS_quic_reloadable_flag_##flag
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h
index af73f745..4e3046e 100644
--- a/net/quic/quic_flags_list.h
+++ b/net/quic/quic_flags_list.h
@@ -405,3 +405,6 @@
 
 // If true, enable QUIC version 50.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_50, false)
+
+// If true, enable QUIC MTU discovery version 2.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_mtu_discovery_v2, false)
diff --git a/net/socket/client_socket_pool.cc b/net/socket/client_socket_pool.cc
index 4dcc7df0..b614c75 100644
--- a/net/socket/client_socket_pool.cc
+++ b/net/socket/client_socket_pool.cc
@@ -71,7 +71,8 @@
 ClientSocketPool::GroupId::GroupId(const HostPortPair& destination,
                                    SocketType socket_type,
                                    PrivacyMode privacy_mode,
-                                   NetworkIsolationKey network_isolation_key)
+                                   NetworkIsolationKey network_isolation_key,
+                                   bool disable_secure_dns)
     : destination_(destination),
       socket_type_(socket_type),
       privacy_mode_(privacy_mode),
@@ -79,7 +80,8 @@
           base::FeatureList::IsEnabled(
               features::kPartitionConnectionsByNetworkIsolationKey)
               ? network_isolation_key
-              : NetworkIsolationKey()) {}
+              : NetworkIsolationKey()),
+      disable_secure_dns_(disable_secure_dns) {}
 
 ClientSocketPool::GroupId::GroupId(const GroupId& group_id) = default;
 
@@ -111,6 +113,9 @@
     result += ">";
   }
 
+  if (disable_secure_dns_)
+    result = "dsd/" + result;
+
   return result;
 }
 
@@ -183,8 +188,8 @@
       socket_params->ssl_config_for_origin(),
       socket_params->ssl_config_for_proxy(), is_for_websockets,
       group_id.privacy_mode(), resolution_callback, request_priority,
-      socket_tag, group_id.network_isolation_key(), common_connect_job_params,
-      delegate);
+      socket_tag, group_id.network_isolation_key(),
+      group_id.disable_secure_dns(), common_connect_job_params, delegate);
 }
 
 }  // namespace net
diff --git a/net/socket/client_socket_pool.h b/net/socket/client_socket_pool.h
index 48502ec..0790c8f 100644
--- a/net/socket/client_socket_pool.h
+++ b/net/socket/client_socket_pool.h
@@ -114,7 +114,8 @@
     GroupId(const HostPortPair& destination,
             SocketType socket_type,
             PrivacyMode privacy_mode,
-            NetworkIsolationKey network_isolation_key = NetworkIsolationKey());
+            NetworkIsolationKey network_isolation_key = NetworkIsolationKey(),
+            bool disable_secure_dns = false);
     GroupId(const GroupId& group_id);
 
     ~GroupId();
@@ -132,21 +133,25 @@
       return network_isolation_key_;
     }
 
+    bool disable_secure_dns() const { return disable_secure_dns_; }
+
     // Returns the group ID as a string, for logging.
     std::string ToString() const;
 
     bool operator==(const GroupId& other) const {
       return std::tie(destination_, socket_type_, privacy_mode_,
-                      network_isolation_key_) ==
+                      network_isolation_key_, disable_secure_dns_) ==
              std::tie(other.destination_, other.socket_type_,
-                      other.privacy_mode_, other.network_isolation_key_);
+                      other.privacy_mode_, other.network_isolation_key_,
+                      other.disable_secure_dns_);
     }
 
     bool operator<(const GroupId& other) const {
       return std::tie(destination_, socket_type_, privacy_mode_,
-                      network_isolation_key_) <
+                      network_isolation_key_, disable_secure_dns_) <
              std::tie(other.destination_, other.socket_type_,
-                      other.privacy_mode_, other.network_isolation_key_);
+                      other.privacy_mode_, other.network_isolation_key_,
+                      other.disable_secure_dns_);
     }
 
    private:
@@ -160,6 +165,9 @@
 
     // Used to separate requests made in different contexts.
     NetworkIsolationKey network_isolation_key_;
+
+    // If host resolutions for this request may not use secure DNS.
+    bool disable_secure_dns_;
   };
 
   // Parameters that, in combination with GroupId, proxy, websocket information,
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 9260e5e..eebd2c4 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -82,8 +82,10 @@
         ClientSocketPool::SocketType::kHttp,
     PrivacyMode privacy_mode = PrivacyMode::PRIVACY_MODE_DISABLED,
     NetworkIsolationKey network_isolation_key = NetworkIsolationKey()) {
+  bool disable_secure_dns = false;
   return ClientSocketPool::GroupId(HostPortPair(host, port), socket_type,
-                                   privacy_mode, network_isolation_key);
+                                   privacy_mode, network_isolation_key,
+                                   disable_secure_dns);
 }
 
 // Make sure |handle| sets load times correctly when it has been assigned a
@@ -813,6 +815,8 @@
       NetworkIsolationKey(kOriginB, kOriginB),
   };
 
+  const bool kDisableSecureDnsValues[] = {false, true};
+
   int total_idle_sockets = 0;
 
   // Walk through each GroupId, making sure that requesting a socket for one
@@ -825,55 +829,59 @@
         SCOPED_TRACE(privacy_mode);
         for (const auto& network_isolation_key : kNetworkIsolationKeys) {
           SCOPED_TRACE(network_isolation_key.ToString());
+          for (const auto& disable_secure_dns : kDisableSecureDnsValues) {
+            SCOPED_TRACE(disable_secure_dns);
 
-          connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
+            connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
 
-          ClientSocketPool::GroupId group_id(
-              host_port_pair, socket_type, privacy_mode, network_isolation_key);
+            ClientSocketPool::GroupId group_id(
+                host_port_pair, socket_type, privacy_mode,
+                network_isolation_key, disable_secure_dns);
 
-          EXPECT_FALSE(pool_->HasGroupForTesting(group_id));
+            EXPECT_FALSE(pool_->HasGroupForTesting(group_id));
 
-          TestCompletionCallback callback;
-          ClientSocketHandle handle;
+            TestCompletionCallback callback;
+            ClientSocketHandle handle;
 
-          // Since the group is empty, requesting a socket should not complete
-          // synchronously.
-          EXPECT_THAT(
-              handle.Init(group_id, params_, base::nullopt, DEFAULT_PRIORITY,
-                          SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
-                          callback.callback(),
-                          ClientSocketPool::ProxyAuthCallback(), pool_.get(),
-                          NetLogWithSource()),
-              IsError(ERR_IO_PENDING));
-          EXPECT_TRUE(pool_->HasGroupForTesting(group_id));
-          EXPECT_EQ(total_idle_sockets, pool_->IdleSocketCount());
+            // Since the group is empty, requesting a socket should not complete
+            // synchronously.
+            EXPECT_THAT(handle.Init(group_id, params_, base::nullopt,
+                                    DEFAULT_PRIORITY, SocketTag(),
+                                    ClientSocketPool::RespectLimits::ENABLED,
+                                    callback.callback(),
+                                    ClientSocketPool::ProxyAuthCallback(),
+                                    pool_.get(), NetLogWithSource()),
+                        IsError(ERR_IO_PENDING));
+            EXPECT_TRUE(pool_->HasGroupForTesting(group_id));
+            EXPECT_EQ(total_idle_sockets, pool_->IdleSocketCount());
 
-          EXPECT_THAT(callback.WaitForResult(), IsOk());
-          EXPECT_TRUE(handle.socket());
-          EXPECT_TRUE(pool_->HasGroupForTesting(group_id));
-          EXPECT_EQ(total_idle_sockets, pool_->IdleSocketCount());
+            EXPECT_THAT(callback.WaitForResult(), IsOk());
+            EXPECT_TRUE(handle.socket());
+            EXPECT_TRUE(pool_->HasGroupForTesting(group_id));
+            EXPECT_EQ(total_idle_sockets, pool_->IdleSocketCount());
 
-          // Return socket to pool.
-          handle.Reset();
-          EXPECT_EQ(total_idle_sockets + 1, pool_->IdleSocketCount());
+            // Return socket to pool.
+            handle.Reset();
+            EXPECT_EQ(total_idle_sockets + 1, pool_->IdleSocketCount());
 
-          // Requesting a socket again should return the same socket as before,
-          // so should complete synchronously.
-          EXPECT_THAT(
-              handle.Init(group_id, params_, base::nullopt, DEFAULT_PRIORITY,
-                          SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
-                          callback.callback(),
-                          ClientSocketPool::ProxyAuthCallback(), pool_.get(),
-                          NetLogWithSource()),
-              IsOk());
-          EXPECT_TRUE(handle.socket());
-          EXPECT_EQ(total_idle_sockets, pool_->IdleSocketCount());
+            // Requesting a socket again should return the same socket as
+            // before, so should complete synchronously.
+            EXPECT_THAT(handle.Init(group_id, params_, base::nullopt,
+                                    DEFAULT_PRIORITY, SocketTag(),
+                                    ClientSocketPool::RespectLimits::ENABLED,
+                                    callback.callback(),
+                                    ClientSocketPool::ProxyAuthCallback(),
+                                    pool_.get(), NetLogWithSource()),
+                        IsOk());
+            EXPECT_TRUE(handle.socket());
+            EXPECT_EQ(total_idle_sockets, pool_->IdleSocketCount());
 
-          // Return socket to pool again.
-          handle.Reset();
-          EXPECT_EQ(total_idle_sockets + 1, pool_->IdleSocketCount());
+            // Return socket to pool again.
+            handle.Reset();
+            EXPECT_EQ(total_idle_sockets + 1, pool_->IdleSocketCount());
 
-          ++total_idle_sockets;
+            ++total_idle_sockets;
+          }
         }
       }
     }
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index 4db245c..f8df5f5 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -69,7 +69,8 @@
     const HostPortPair& endpoint,
     const ProxyInfo& proxy_info,
     PrivacyMode privacy_mode,
-    const NetworkIsolationKey& network_isolation_key) {
+    const NetworkIsolationKey& network_isolation_key,
+    bool disable_secure_dns) {
   // Build the string used to uniquely identify connections of this type.
   // Determine the host and port to connect to.
   DCHECK(!endpoint.IsEmpty());
@@ -80,7 +81,7 @@
     socket_type = ClientSocketPool::SocketType::kSsl;
 
   return ClientSocketPool::GroupId(endpoint, socket_type, privacy_mode,
-                                   network_isolation_key);
+                                   network_isolation_key, disable_secure_dns);
 }
 
 // TODO(https://crbug.com/921369) In order to resolve longstanding issues
@@ -129,7 +130,7 @@
 
   ClientSocketPool::GroupId connection_group =
       CreateGroupId(group_type, origin_host_port, proxy_info, privacy_mode,
-                    network_isolation_key);
+                    network_isolation_key, false /* disable_secure_dns */);
   scoped_refptr<ClientSocketPool::SocketParams> socket_params =
       CreateSocketParams(connection_group, proxy_info.proxy_server(),
                          ssl_config_for_origin, ssl_config_for_proxy);
diff --git a/net/socket/client_socket_pool_unittest.cc b/net/socket/client_socket_pool_unittest.cc
index 1ec12ff7..d243745e 100644
--- a/net/socket/client_socket_pool_unittest.cc
+++ b/net/socket/client_socket_pool_unittest.cc
@@ -53,6 +53,8 @@
       NetworkIsolationKey(kOriginB, kOriginB),
   };
 
+  const bool kDisableSecureDnsValues[] = {false, true};
+
   // All previously created |group_ids|. They should all be less than the
   // current group under consideration.
   std::vector<ClientSocketPool::GroupId> group_ids;
@@ -64,26 +66,27 @@
       SCOPED_TRACE(static_cast<int>(socket_type));
       for (const auto& privacy_mode : kPrivacyModes) {
         SCOPED_TRACE(privacy_mode);
-
         for (const auto& network_isolation_key : kNetworkIsolationKeys) {
           SCOPED_TRACE(network_isolation_key.ToString());
+          for (const auto& disable_secure_dns : kDisableSecureDnsValues) {
+            ClientSocketPool::GroupId group_id(
+                host_port_pair, socket_type, privacy_mode,
+                network_isolation_key, disable_secure_dns);
+            for (const auto& lower_group_id : group_ids) {
+              EXPECT_FALSE(lower_group_id == group_id);
+              EXPECT_TRUE(lower_group_id < group_id);
+              EXPECT_FALSE(group_id < lower_group_id);
+            }
 
-          ClientSocketPool::GroupId group_id(
-              host_port_pair, socket_type, privacy_mode, network_isolation_key);
-          for (const auto& lower_group_id : group_ids) {
-            EXPECT_FALSE(lower_group_id == group_id);
-            EXPECT_TRUE(lower_group_id < group_id);
-            EXPECT_FALSE(group_id < lower_group_id);
+            group_ids.push_back(group_id);
+
+            // Compare |group_id| to itself. Use two different copies of
+            // |group_id|'s value, since to protect against bugs where an object
+            // only equals itself.
+            EXPECT_TRUE(group_ids.back() == group_id);
+            EXPECT_FALSE(group_ids.back() < group_id);
+            EXPECT_FALSE(group_id < group_ids.back());
           }
-
-          group_ids.push_back(group_id);
-
-          // Compare |group_id| to itself. Use two different copies of
-          // |group_id|'s value, since to protect against bugs where an object
-          // only equals itself.
-          EXPECT_TRUE(group_ids.back() == group_id);
-          EXPECT_FALSE(group_ids.back() < group_id);
-          EXPECT_FALSE(group_id < group_ids.back());
         }
       }
     }
@@ -98,33 +101,39 @@
   EXPECT_EQ("foo:80 <null>",
             ClientSocketPool::GroupId(
                 HostPortPair("foo", 80), ClientSocketPool::SocketType::kHttp,
-                PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey())
+                PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+                false /* disable_secure_dns */)
                 .ToString());
   EXPECT_EQ("bar:443 <null>",
             ClientSocketPool::GroupId(
                 HostPortPair("bar", 443), ClientSocketPool::SocketType::kHttp,
-                PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey())
+                PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+                false /* disable_secure_dns */)
                 .ToString());
   EXPECT_EQ("pm/bar:80 <null>",
             ClientSocketPool::GroupId(
                 HostPortPair("bar", 80), ClientSocketPool::SocketType::kHttp,
-                PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey())
+                PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey(),
+                false /* disable_secure_dns */)
                 .ToString());
 
   EXPECT_EQ("ssl/foo:80 <null>",
             ClientSocketPool::GroupId(
                 HostPortPair("foo", 80), ClientSocketPool::SocketType::kSsl,
-                PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey())
+                PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+                false /* disable_secure_dns */)
                 .ToString());
   EXPECT_EQ("ssl/bar:443 <null>",
             ClientSocketPool::GroupId(
                 HostPortPair("bar", 443), ClientSocketPool::SocketType::kSsl,
-                PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey())
+                PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+                false /* disable_secure_dns */)
                 .ToString());
   EXPECT_EQ("pm/ssl/bar:80 <null>",
             ClientSocketPool::GroupId(
                 HostPortPair("bar", 80), ClientSocketPool::SocketType::kSsl,
-                PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey())
+                PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey(),
+                false /* disable_secure_dns */)
                 .ToString());
 
   EXPECT_EQ(
@@ -133,8 +142,16 @@
           HostPortPair("foo", 443), ClientSocketPool::SocketType::kSsl,
           PrivacyMode::PRIVACY_MODE_DISABLED,
           NetworkIsolationKey(url::Origin::Create(GURL("https://foo.com")),
-                              url::Origin::Create(GURL("https://foo.com"))))
+                              url::Origin::Create(GURL("https://foo.com"))),
+          false /* disable_secure_dns */)
           .ToString());
+
+  EXPECT_EQ("dsd/pm/ssl/bar:80 <null>",
+            ClientSocketPool::GroupId(
+                HostPortPair("bar", 80), ClientSocketPool::SocketType::kSsl,
+                PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey(),
+                true /* disable_secure_dns */)
+                .ToString());
 }
 
 TEST(ClientSocketPool, PartitionConnectionsByNetworkIsolationKeyDisabled) {
diff --git a/net/socket/connect_job.cc b/net/socket/connect_job.cc
index daea92c..7aad80e89 100644
--- a/net/socket/connect_job.cc
+++ b/net/socket/connect_job.cc
@@ -108,6 +108,7 @@
     RequestPriority request_priority,
     SocketTag socket_tag,
     const NetworkIsolationKey& network_isolation_key,
+    bool disable_secure_dns,
     const CommonConnectJobParams* common_connect_job_params,
     ConnectJob::Delegate* delegate) {
   scoped_refptr<HttpProxySocketParams> http_proxy_params;
@@ -115,7 +116,7 @@
 
   if (!proxy_server.is_direct()) {
     auto proxy_tcp_params = base::MakeRefCounted<TransportSocketParams>(
-        proxy_server.host_port_pair(), resolution_callback);
+        proxy_server.host_port_pair(), disable_secure_dns, resolution_callback);
 
     if (proxy_server.is_http() || proxy_server.is_https() ||
         proxy_server.is_quic()) {
@@ -150,7 +151,7 @@
     scoped_refptr<TransportSocketParams> ssl_tcp_params;
     if (proxy_server.is_direct()) {
       ssl_tcp_params = base::MakeRefCounted<TransportSocketParams>(
-          endpoint, resolution_callback);
+          endpoint, disable_secure_dns, resolution_callback);
     }
     auto ssl_params = base::MakeRefCounted<SSLSocketParams>(
         std::move(ssl_tcp_params), std::move(socks_params),
@@ -175,7 +176,7 @@
 
   DCHECK(proxy_server.is_direct());
   auto tcp_params = base::MakeRefCounted<TransportSocketParams>(
-      endpoint, resolution_callback);
+      endpoint, disable_secure_dns, resolution_callback);
   return TransportConnectJob::CreateTransportConnectJob(
       std::move(tcp_params), request_priority, socket_tag,
       common_connect_job_params, delegate, nullptr /* net_log */);
diff --git a/net/socket/connect_job.h b/net/socket/connect_job.h
index 69274c1..a74b7e9 100644
--- a/net/socket/connect_job.h
+++ b/net/socket/connect_job.h
@@ -188,6 +188,7 @@
       RequestPriority request_priority,
       SocketTag socket_tag,
       const NetworkIsolationKey& network_isolation_key,
+      bool disable_secure_dns,
       const CommonConnectJobParams* common_connect_job_params,
       ConnectJob::Delegate* delegate);
 
diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc
index 45cf5a0..d849eea 100644
--- a/net/socket/socks_client_socket.cc
+++ b/net/socket/socks_client_socket.cc
@@ -64,6 +64,7 @@
     const HostPortPair& destination,
     RequestPriority priority,
     HostResolver* host_resolver,
+    bool disable_secure_dns,
     const NetworkTrafficAnnotationTag& traffic_annotation)
     : transport_socket_(std::move(transport_socket)),
       next_state_(STATE_NONE),
@@ -72,6 +73,7 @@
       bytes_received_(0),
       was_ever_used_(false),
       host_resolver_(host_resolver),
+      disable_secure_dns_(disable_secure_dns),
       destination_(destination),
       priority_(priority),
       net_log_(transport_socket_->NetLog()),
@@ -305,6 +307,8 @@
   HostResolver::ResolveHostParameters parameters;
   parameters.dns_query_type = DnsQueryType::A;
   parameters.initial_priority = priority_;
+  if (disable_secure_dns_)
+    parameters.secure_dns_mode_override = DnsConfig::SecureDnsMode::OFF;
   resolve_host_request_ =
       host_resolver_->CreateRequest(destination_, net_log_, parameters);
 
diff --git a/net/socket/socks_client_socket.h b/net/socket/socks_client_socket.h
index 6f66b57..20339fd 100644
--- a/net/socket/socks_client_socket.h
+++ b/net/socket/socks_client_socket.h
@@ -35,6 +35,7 @@
                     const HostPortPair& destination,
                     RequestPriority priority,
                     HostResolver* host_resolver,
+                    bool disable_secure_dns,
                     const NetworkTrafficAnnotationTag& traffic_annotation);
 
   // On destruction Disconnect() is called.
@@ -136,6 +137,7 @@
 
   // Used to resolve the hostname to which the SOCKS proxy will connect.
   HostResolver* host_resolver_;
+  bool disable_secure_dns_;
   std::unique_ptr<HostResolver::ResolveHostRequest> resolve_host_request_;
   const HostPortPair destination_;
   RequestPriority priority_;
diff --git a/net/socket/socks_client_socket_fuzzer.cc b/net/socket/socks_client_socket_fuzzer.cc
index 63c03bc..9a99935 100644
--- a/net/socket/socks_client_socket_fuzzer.cc
+++ b/net/socket/socks_client_socket_fuzzer.cc
@@ -56,7 +56,8 @@
 
   net::SOCKSClientSocket socket(
       std::move(fuzzed_socket), net::HostPortPair("foo", 80),
-      net::DEFAULT_PRIORITY, &mock_host_resolver, TRAFFIC_ANNOTATION_FOR_TESTS);
+      net::DEFAULT_PRIORITY, &mock_host_resolver,
+      false /* disable_secure_dns */, TRAFFIC_ANNOTATION_FOR_TESTS);
   int result = socket.Connect(callback.callback());
   callback.GetResult(result);
   return 0;
diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc
index 5f26258d..f02c23a 100644
--- a/net/socket/socks_client_socket_unittest.cc
+++ b/net/socket/socks_client_socket_unittest.cc
@@ -95,7 +95,8 @@
   tcp_sock_ = socket.get();
   return std::make_unique<SOCKSClientSocket>(
       std::move(socket), HostPortPair(hostname, port), DEFAULT_PRIORITY,
-      host_resolver, TRAFFIC_ANNOTATION_FOR_TESTS);
+      host_resolver, false /* disable_secure_dns */,
+      TRAFFIC_ANNOTATION_FOR_TESTS);
 }
 
 // Tests a complete handshake and the disconnection.
@@ -435,7 +436,8 @@
   MockHostResolver host_resolver;
   SOCKSClientSocket socket(std::unique_ptr<StreamSocket>(tagging_sock),
                            HostPortPair("localhost", 80), DEFAULT_PRIORITY,
-                           &host_resolver, TRAFFIC_ANNOTATION_FOR_TESTS);
+                           &host_resolver, false /* disable_secure_dns */,
+                           TRAFFIC_ANNOTATION_FOR_TESTS);
 
   EXPECT_EQ(tagging_sock->tag(), SocketTag());
 #if defined(OS_ANDROID)
@@ -445,4 +447,24 @@
 #endif  // OS_ANDROID
 }
 
+TEST_F(SOCKSClientSocketTest, SetDisableSecureDns) {
+  for (bool disable_secure_dns : {false, true}) {
+    StaticSocketDataProvider data;
+    TestNetLog log;
+    MockHostResolver host_resolver;
+    SOCKSClientSocket socket(
+        std::make_unique<MockTCPClientSocket>(address_list_, &log, &data),
+        HostPortPair("localhost", 80), DEFAULT_PRIORITY, &host_resolver,
+        disable_secure_dns, TRAFFIC_ANNOTATION_FOR_TESTS);
+
+    EXPECT_EQ(ERR_IO_PENDING, socket.Connect(callback_.callback()));
+    EXPECT_EQ(disable_secure_dns,
+              host_resolver.last_secure_dns_mode_override().has_value());
+    if (disable_secure_dns) {
+      EXPECT_EQ(net::DnsConfig::SecureDnsMode::OFF,
+                host_resolver.last_secure_dns_mode_override().value());
+    }
+  }
+}
+
 }  // namespace net
diff --git a/net/socket/socks_connect_job.cc b/net/socket/socks_connect_job.cc
index 76ebde8..cb2e542e 100644
--- a/net/socket/socks_connect_job.cc
+++ b/net/socket/socks_connect_job.cc
@@ -165,7 +165,9 @@
   } else {
     socket_.reset(new SOCKSClientSocket(
         transport_connect_job_->PassSocket(), socks_params_->destination(),
-        priority(), host_resolver(), socks_params_->traffic_annotation()));
+        priority(), host_resolver(),
+        socks_params_->transport_params()->disable_secure_dns(),
+        socks_params_->traffic_annotation()));
   }
   transport_connect_job_.reset();
   return socket_->Connect(
diff --git a/net/socket/socks_connect_job_unittest.cc b/net/socket/socks_connect_job_unittest.cc
index 53ca3ba..7ad2fc2 100644
--- a/net/socket/socks_connect_job_unittest.cc
+++ b/net/socket/socks_connect_job_unittest.cc
@@ -65,10 +65,11 @@
   ~SOCKSConnectJobTest() override {}
 
   static scoped_refptr<SOCKSSocketParams> CreateSOCKSParams(
-      SOCKSVersion socks_version) {
+      SOCKSVersion socks_version,
+      bool disable_secure_dns = false) {
     return base::MakeRefCounted<SOCKSSocketParams>(
         base::MakeRefCounted<TransportSocketParams>(
-            HostPortPair(kProxyHostName, kProxyPort),
+            HostPortPair(kProxyHostName, kProxyPort), disable_secure_dns,
             OnHostResolutionCallback()),
         socks_version == SOCKSVersion::V5,
         socks_version == SOCKSVersion::V4
@@ -346,6 +347,23 @@
   }
 }
 
+TEST_F(SOCKSConnectJobTest, DisableSecureDns) {
+  for (bool disable_secure_dns : {false, true}) {
+    TestConnectJobDelegate test_delegate;
+    SOCKSConnectJob socks_connect_job(
+        DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_,
+        CreateSOCKSParams(SOCKSVersion::V4, disable_secure_dns), &test_delegate,
+        nullptr /* net_log */);
+    ASSERT_THAT(socks_connect_job.Connect(), test::IsError(ERR_IO_PENDING));
+    EXPECT_EQ(disable_secure_dns,
+              host_resolver_.last_secure_dns_mode_override().has_value());
+    if (disable_secure_dns) {
+      EXPECT_EQ(net::DnsConfig::SecureDnsMode::OFF,
+                host_resolver_.last_secure_dns_mode_override().value());
+    }
+  }
+}
+
 TEST_F(SOCKSConnectJobTest, ConnectTiming) {
   host_resolver_.set_ondemand_mode(true);
 
diff --git a/net/socket/ssl_connect_job_unittest.cc b/net/socket/ssl_connect_job_unittest.cc
index 3fc596b..a1d33ed4 100644
--- a/net/socket/ssl_connect_job_unittest.cc
+++ b/net/socket/ssl_connect_job_unittest.cc
@@ -83,9 +83,11 @@
         session_(CreateNetworkSession()),
         direct_transport_socket_params_(
             new TransportSocketParams(HostPortPair("host", 443),
+                                      false /* disable_secure_dns */,
                                       OnHostResolutionCallback())),
         proxy_transport_socket_params_(
             new TransportSocketParams(HostPortPair("proxy", 443),
+                                      false /* disable_secure_dns */,
                                       OnHostResolutionCallback())),
         socks_socket_params_(
             new SOCKSSocketParams(proxy_transport_socket_params_,
@@ -409,6 +411,30 @@
   }
 }
 
+TEST_F(SSLConnectJobTest, DisableSecureDns) {
+  for (bool disable_secure_dns : {false, true}) {
+    TestConnectJobDelegate test_delegate;
+    direct_transport_socket_params_ =
+        base::MakeRefCounted<TransportSocketParams>(HostPortPair("host", 443),
+                                                    disable_secure_dns,
+                                                    OnHostResolutionCallback());
+    auto common_connect_job_params = session_->CreateCommonConnectJobParams();
+    std::unique_ptr<ConnectJob> ssl_connect_job =
+        std::make_unique<SSLConnectJob>(DEFAULT_PRIORITY, SocketTag(),
+                                        &common_connect_job_params,
+                                        SSLParams(ProxyServer::SCHEME_DIRECT),
+                                        &test_delegate, nullptr /* net_log */);
+
+    EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
+    EXPECT_EQ(disable_secure_dns,
+              host_resolver_.last_secure_dns_mode_override().has_value());
+    if (disable_secure_dns) {
+      EXPECT_EQ(net::DnsConfig::SecureDnsMode::OFF,
+                host_resolver_.last_secure_dns_mode_override().value());
+    }
+  }
+}
+
 TEST_F(SSLConnectJobTest, DirectCertError) {
   StaticSocketDataProvider data;
   socket_factory_.AddSocketDataProvider(&data);
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc
index 1a51470..065ab22 100644
--- a/net/socket/transport_client_socket_pool_unittest.cc
+++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -250,6 +250,31 @@
   }
 }
 
+TEST_F(TransportClientSocketPoolTest, SetDisableSecureDns) {
+  for (bool disable_secure_dns : {false, true}) {
+    TestCompletionCallback callback;
+    ClientSocketHandle handle;
+    ClientSocketPool::GroupId group_id(
+        HostPortPair("www.google.com", 80), ClientSocketPool::SocketType::kHttp,
+        PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+        disable_secure_dns);
+    EXPECT_EQ(
+        ERR_IO_PENDING,
+        handle.Init(group_id, params_, base::nullopt /* proxy_annotation_tag */,
+                    LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+                    callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource()));
+    EXPECT_EQ(disable_secure_dns,
+              session_deps_.host_resolver->last_secure_dns_mode_override()
+                  .has_value());
+    if (disable_secure_dns) {
+      EXPECT_EQ(
+          net::DnsConfig::SecureDnsMode::OFF,
+          session_deps_.host_resolver->last_secure_dns_mode_override().value());
+    }
+  }
+}
+
 TEST_F(TransportClientSocketPoolTest, ReprioritizeRequests) {
   session_deps_.host_resolver->set_ondemand_mode(true);
 
diff --git a/net/socket/transport_connect_job.cc b/net/socket/transport_connect_job.cc
index dafaeca..4a734a799 100644
--- a/net/socket/transport_connect_job.cc
+++ b/net/socket/transport_connect_job.cc
@@ -47,8 +47,10 @@
 
 TransportSocketParams::TransportSocketParams(
     const HostPortPair& host_port_pair,
+    bool disable_secure_dns,
     const OnHostResolutionCallback& host_resolution_callback)
     : destination_(host_port_pair),
+      disable_secure_dns_(disable_secure_dns),
       host_resolution_callback_(host_resolution_callback) {}
 
 TransportSocketParams::~TransportSocketParams() = default;
@@ -259,6 +261,8 @@
 
   HostResolver::ResolveHostParameters parameters;
   parameters.initial_priority = priority();
+  if (params_->disable_secure_dns())
+    parameters.secure_dns_mode_override = DnsConfig::SecureDnsMode::OFF;
   request_ = host_resolver()->CreateRequest(params_->destination(), net_log(),
                                             parameters);
 
diff --git a/net/socket/transport_connect_job.h b/net/socket/transport_connect_job.h
index 69b763d..0d02929 100644
--- a/net/socket/transport_connect_job.h
+++ b/net/socket/transport_connect_job.h
@@ -34,9 +34,11 @@
   // connection will be aborted with that value.
   TransportSocketParams(
       const HostPortPair& host_port_pair,
+      bool disable_secure_dns,
       const OnHostResolutionCallback& host_resolution_callback);
 
   const HostPortPair& destination() const { return destination_; }
+  bool disable_secure_dns() const { return disable_secure_dns_; }
   const OnHostResolutionCallback& host_resolution_callback() const {
     return host_resolution_callback_;
   }
@@ -46,6 +48,7 @@
   ~TransportSocketParams();
 
   const HostPortPair destination_;
+  const bool disable_secure_dns_;
   const OnHostResolutionCallback host_resolution_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(TransportSocketParams);
diff --git a/net/socket/transport_connect_job_unittest.cc b/net/socket/transport_connect_job_unittest.cc
index c691d8f..59a90e8 100644
--- a/net/socket/transport_connect_job_unittest.cc
+++ b/net/socket/transport_connect_job_unittest.cc
@@ -56,7 +56,8 @@
 
   static scoped_refptr<TransportSocketParams> DefaultParams() {
     return base::MakeRefCounted<TransportSocketParams>(
-        HostPortPair(kHostName, 80), OnHostResolutionCallback());
+        HostPortPair(kHostName, 80), false /* disable_secure_dns */,
+        OnHostResolutionCallback());
   }
 
  protected:
@@ -256,6 +257,26 @@
   }
 }
 
+TEST_F(TransportConnectJobTest, DisableSecureDns) {
+  for (bool disable_secure_dns : {false, true}) {
+    TestConnectJobDelegate test_delegate;
+    TransportConnectJob transport_connect_job(
+        DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_,
+        base::MakeRefCounted<TransportSocketParams>(HostPortPair(kHostName, 80),
+                                                    disable_secure_dns,
+                                                    OnHostResolutionCallback()),
+        &test_delegate, nullptr /* net_log */);
+    test_delegate.StartJobExpectingResult(&transport_connect_job, OK,
+                                          false /* expect_sync_result */);
+    EXPECT_EQ(disable_secure_dns,
+              host_resolver_.last_secure_dns_mode_override().has_value());
+    if (disable_secure_dns) {
+      EXPECT_EQ(net::DnsConfig::SecureDnsMode::OFF,
+                host_resolver_.last_secure_dns_mode_override().value());
+    }
+  }
+}
+
 // Test the case of the IPv6 address stalling, and falling back to the IPv4
 // socket which finishes first.
 TEST_F(TransportConnectJobTest, IPv6FallbackSocketIPv4FinishesFirst) {
diff --git a/net/socket/websocket_transport_connect_job.cc b/net/socket/websocket_transport_connect_job.cc
index 36b5b72..926cf67 100644
--- a/net/socket/websocket_transport_connect_job.cc
+++ b/net/socket/websocket_transport_connect_job.cc
@@ -109,6 +109,7 @@
 
   HostResolver::ResolveHostParameters parameters;
   parameters.initial_priority = priority();
+  DCHECK(!params_->disable_secure_dns());
   request_ = host_resolver()->CreateRequest(params_->destination(), net_log(),
                                             parameters);
 
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc
index 2039289..a2e75a6 100644
--- a/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -93,7 +93,8 @@
       NetLogWithSource()));
 
   auto transport_params = base::MakeRefCounted<TransportSocketParams>(
-      key.host_port_pair(), OnHostResolutionCallback());
+      key.host_port_pair(), false /* disable_secure_dns */,
+      OnHostResolutionCallback());
 
   SSLConfig ssl_config;
   auto ssl_params = base::MakeRefCounted<SSLSocketParams>(
diff --git a/printing/print_job_constants.cc b/printing/print_job_constants.cc
index 8476582..440950e 100644
--- a/printing/print_job_constants.cc
+++ b/printing/print_job_constants.cc
@@ -60,14 +60,6 @@
 // Print job duplex mode. Value is an int from DuplexMode enum.
 const char kSettingDuplexMode[] = "duplex";
 
-// Option to fit source page contents to printer paper size: true if
-// selected else false.
-const char kSettingFitToPageEnabled[] = "fitToPageEnabled";
-
-// Option to fit source page contents to paper size: true if
-// selected else false.
-const char kSettingFitToPaperEnabled[] = "fitToPaperEnabled";
-
 // Option to print headers and Footers: true if selected, false if not.
 const char kSettingHeaderFooterEnabled[] = "headerFooterEnabled";
 
@@ -177,6 +169,9 @@
 // Scaling factor
 const char kSettingScaleFactor[] = "scaleFactor";
 
+// Scaling type
+const char kSettingScalingType[] = "scalingType";
+
 // Number of pages per sheet.
 const char kSettingPagesPerSheet[] = "pagesPerSheet";
 
diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h
index 273b76a..7bbd53676 100644
--- a/printing/print_job_constants.h
+++ b/printing/print_job_constants.h
@@ -26,9 +26,7 @@
 PRINTING_EXPORT extern const char kSettingDpiHorizontal[];
 PRINTING_EXPORT extern const char kSettingDpiVertical[];
 PRINTING_EXPORT extern const char kSettingDuplexMode[];
-PRINTING_EXPORT extern const char kSettingFitToPageEnabled[];
 PRINTING_EXPORT extern const char kSettingFitToPageScaling[];
-PRINTING_EXPORT extern const char kSettingFitToPaperEnabled[];
 PRINTING_EXPORT extern const char kSettingHeaderFooterEnabled[];
 PRINTING_EXPORT extern const float kSettingHeaderFooterInterstice;
 PRINTING_EXPORT extern const char kSettingHeaderFooterDate[];
@@ -68,6 +66,7 @@
 PRINTING_EXPORT extern const char kSettingPrinterType[];
 PRINTING_EXPORT extern const char kSettingRasterizePdf[];
 PRINTING_EXPORT extern const char kSettingScaleFactor[];
+PRINTING_EXPORT extern const char kSettingScalingType[];
 PRINTING_EXPORT extern const char kSettingTicket[];
 PRINTING_EXPORT extern const char kSettingSendUserInfo[];
 PRINTING_EXPORT extern const char kSettingShouldPrintBackgrounds[];
@@ -153,6 +152,16 @@
   MARGIN_TYPE_LAST = CUSTOM_MARGINS
 };
 
+// Must match print_preview.ScalingType in
+// chrome/browser/resources/print_preview/data/scaling.js
+enum ScalingType {
+  DEFAULT,
+  FIT_TO_PAGE,
+  FIT_TO_PAPER,
+  CUSTOM,
+  SCALING_TYPE_LAST = CUSTOM
+};
+
 // Must match print_preview.PrinterType in
 // chrome/browser/resources/print_preview/data/destination_match.js
 enum PrinterType {
diff --git a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
index 73c26c4b..313511f 100644
--- a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
+++ b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
@@ -51,8 +51,9 @@
 
 #elif defined(__aarch64__)
 
+#include <asm-generic/unistd.h>
 #define MIN_SYSCALL 0u
-#define MAX_PUBLIC_SYSCALL 279u
+#define MAX_PUBLIC_SYSCALL __NR_syscalls
 #define MAX_SYSCALL MAX_PUBLIC_SYSCALL
 
 #else
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android_unittest.cc
index e119a46..bc0db81 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android_unittest.cc
@@ -33,5 +33,10 @@
   BPF_ASSERT_NE(-1, open("/proc/cpuinfo", O_RDONLY));
 }
 
+BPF_TEST_C(BaselinePolicyAndroid, Membarrier, BaselinePolicyAndroid) {
+  // Should not crash.
+  syscall(__NR_membarrier, 32 /* cmd */, 0 /* flags */);
+}
+
 }  // namespace
 }  // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
index f1160ff..fdd954c 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
@@ -248,15 +248,9 @@
   getrusage(RUSAGE_CHILDREN, &usage);
 }
 
-// ptace() Tests ///////////////////////////////////////////////////////////////
-
-// Tests for ptrace involve a slightly complex setup in order to properly test
-// ptrace and the variety of ways it is access-checked. The BPF_TEST macro,
-// the body of which already runs in its own process, spawns another process
-// called the "tracee". The "tracee" then spawns another process called the
-// "tracer". The child then traces the parent and performs the test operations.
-// The tracee must be careful to un-stop the tracer if the tracee expects to
-// die.
+// The following ptrace() tests do not actually set up a tracer/tracee
+// relationship, so allowed operations return ESRCH errors. Blocked operations
+// are tested with death tests.
 
 class RestrictPtracePolicy : public bpf_dsl::Policy {
  public:
@@ -273,208 +267,48 @@
   }
 };
 
-constexpr char kExitPtraceChildClean = '!';
-
-class PtraceTestHarness {
- public:
-  using PtraceChildTracerFunc = void (*)(pid_t tracee);
-
-  PtraceTestHarness(PtraceChildTracerFunc tracer_func, bool expect_death)
-      : tracer_func_(tracer_func), expect_death_(expect_death) {}
-  ~PtraceTestHarness() = default;
-
-  void Run() {
-    // Fork the tracee process that will be traced by its child.
-    pid_t pid = fork();
-    BPF_ASSERT_GE(pid, 0);
-
-    if (pid == 0) {
-      RunTracee();
-    } else {
-      // The tracee should always exit cleanly.
-      int status = 0;
-      int rv = waitpid(pid, &status, 0);
-      BPF_ASSERT_EQ(pid, rv);
-      BPF_ASSERT_EQ(0, WEXITSTATUS(status));
-    }
-  }
-
- private:
-  void RunTracee() {
-    // Create a communications pipe between tracer and tracee.
-    int rv = pipe2(pipes_, O_NONBLOCK);
-    BPF_ASSERT_EQ(0, rv);
-
-    // Pipes for redirecting output.
-    int output_pipes[2];
-    BPF_ASSERT_EQ(0, pipe(output_pipes));
-
-    // Create the tracer process.
-    pid_t pid = fork();
-    BPF_ASSERT_GE(pid, 0);
-
-    if (pid == 0) {
-      // Close the pipe read ends and redirect output.
-      close(pipes_[0]);
-      close(output_pipes[0]);
-
-      close(STDOUT_FILENO);
-      dup2(output_pipes[1], STDOUT_FILENO);
-
-      close(STDERR_FILENO);
-      dup2(output_pipes[1], STDERR_FILENO);
-
-      RunTracer();
-
-      close(output_pipes[1]);
-    } else {
-      close(pipes_[1]);
-      close(output_pipes[1]);
-
-      // Ensure the tracer can trace the tracee. This may fail on systems
-      // without YAMA, so the result is not checked.
-      prctl(PR_SET_PTRACER, pid);
-
-      char c = 0;
-      while (c != kExitPtraceChildClean) {
-        // Read from the control channel in a non-blocking fashion.
-        // If no data are present, loop.
-        ignore_result(read(pipes_[0], &c, 1));
-
-        // Poll the exit status of the child.
-        int status = 0;
-        rv = waitpid(pid, &status, WNOHANG);
-        if (rv != 0) {
-          BPF_ASSERT_EQ(pid, rv);
-          CheckTracerStatus(status, output_pipes[0]);
-          _exit(0);
-        }
-      }
-
-      _exit(0);
-    }
-  }
-
-  void RunTracer() {
-    pid_t ppid = getppid();
-    BPF_ASSERT_NE(0, ppid);
-
-    // Attach to the tracee and then call out to the test function.
-    BPF_ASSERT_EQ(0, ptrace(PTRACE_ATTACH, ppid, nullptr, nullptr));
-
-    tracer_func_(ppid);
-
-    BPF_ASSERT_EQ(1, HANDLE_EINTR(write(pipes_[1], &kExitPtraceChildClean, 1)));
-    close(pipes_[1]);
-
-    _exit(0);
-  }
-
-  void CheckTracerStatus(int status, int output_pipe) {
-    // The child has exited. Test that it did so in the way we were
-    // expecting.
-    if (expect_death_) {
-      // This duplicates a bit of what //sandbox/linux/tests/unit_tests.cc does
-      // but that code is not shareable here.
-      std::string output;
-      const size_t kBufferSize = 1024;
-      size_t total_bytes_read = 0;
-      ssize_t read_this_pass = 0;
-      do {
-        output.resize(output.size() + kBufferSize);
-        read_this_pass = HANDLE_EINTR(
-            read(output_pipe, &output[total_bytes_read], kBufferSize));
-        if (read_this_pass >= 0) {
-          total_bytes_read += read_this_pass;
-          output.resize(total_bytes_read);
-        }
-      } while (read_this_pass > 0);
-
-#if !defined(SANDBOX_USES_BASE_TEST_SUITE)
-      const bool subprocess_got_sigsegv =
-          WIFSIGNALED(status) && (SIGSEGV == WTERMSIG(status));
-#else
-      // This hack is required when a signal handler is installed
-      // for SEGV that will _exit(1).
-      const bool subprocess_got_sigsegv =
-          WIFEXITED(status) && (1 == WEXITSTATUS(status));
-#endif
-      BPF_ASSERT(subprocess_got_sigsegv);
-      BPF_ASSERT_NE(output.find(GetPtraceErrorMessageContentForTests()),
-                    std::string::npos);
-    } else {
-      BPF_ASSERT(WIFEXITED(status));
-      BPF_ASSERT_EQ(0, WEXITSTATUS(status));
-    }
-  }
-
-  PtraceChildTracerFunc tracer_func_;
-  bool expect_death_;
-  int pipes_[2];
-
-  DISALLOW_COPY_AND_ASSIGN(PtraceTestHarness);
-};
-
-// Fails on Android L and M.
-// See https://crbug.com/934930
 BPF_TEST_C(ParameterRestrictions,
-           DISABLED_ptrace_getregs_allowed,
+           ptrace_getregs_allowed,
            RestrictPtracePolicy) {
-  auto tracer = [](pid_t pid) {
 #if defined(__arm__)
-    user_regs regs;
+  user_regs regs;
 #else
-    user_regs_struct regs;
+  user_regs_struct regs;
 #endif
-    iovec iov;
-    iov.iov_base = &regs;
-    iov.iov_len = sizeof(regs);
-    BPF_ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid,
-                            reinterpret_cast<void*>(NT_PRSTATUS), &iov));
-
-    BPF_ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, nullptr, nullptr));
-  };
-  PtraceTestHarness(tracer, false).Run();
+  iovec iov;
+  iov.iov_base = &regs;
+  iov.iov_len = sizeof(regs);
+  errno = 0;
+  int rv = ptrace(PTRACE_GETREGSET, getpid(),
+                  reinterpret_cast<void*>(NT_PRSTATUS), &iov);
+  BPF_ASSERT_EQ(-1, rv);
+  BPF_ASSERT_EQ(ESRCH, errno);
 }
 
-// Fails on Android L and M.
-// See https://crbug.com/934930
-BPF_TEST_C(ParameterRestrictions,
-           DISABLED_ptrace_syscall_blocked,
-           RestrictPtracePolicy) {
-  auto tracer = [](pid_t pid) {
-    // The tracer is about to die. Make sure the tracee is not stopped so it
-    // can reap it and inspect its death signal.
-    kill(pid, SIGCONT);
-
-    BPF_ASSERT_NE(0, ptrace(PTRACE_SYSCALL, 0, nullptr, nullptr));
-  };
-  PtraceTestHarness(tracer, true).Run();
+BPF_DEATH_TEST_C(
+    ParameterRestrictions,
+    ptrace_syscall_blocked,
+    DEATH_SEGV_MESSAGE(sandbox::GetPtraceErrorMessageContentForTests()),
+    RestrictPtracePolicy) {
+  ptrace(PTRACE_SYSCALL, getpid(), nullptr, nullptr);
 }
 
-BPF_TEST_C(ParameterRestrictions,
-           DISABLED_ptrace_setregs_blocked,
-           RestrictPtracePolicy) {
-  auto tracer = [](pid_t pid) {
+BPF_DEATH_TEST_C(
+    ParameterRestrictions,
+    ptrace_setregs_blocked,
+    DEATH_SEGV_MESSAGE(sandbox::GetPtraceErrorMessageContentForTests()),
+    RestrictPtracePolicy) {
 #if defined(__arm__)
-    user_regs regs;
+  user_regs regs{};
 #else
-    user_regs_struct regs;
+  user_regs_struct regs{};
 #endif
-    iovec iov;
-    iov.iov_base = &regs;
-    iov.iov_len = sizeof(regs);
-    BPF_ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid,
-                            reinterpret_cast<void*>(NT_PRSTATUS), &iov));
-
-    // The tracer is about to die. Make sure the tracee is not stopped so it
-    // can reap it and inspect its death signal.
-    kill(pid, SIGCONT);
-
-    BPF_ASSERT_NE(0, ptrace(PTRACE_SETREGSET, pid,
-                            reinterpret_cast<void*>(NT_PRSTATUS), &iov));
-  };
-  PtraceTestHarness(tracer, true).Run();
+  iovec iov;
+  iov.iov_base = &regs;
+  iov.iov_len = sizeof(regs);
+  errno = 0;
+  ptrace(PTRACE_SETREGSET, getpid(), reinterpret_cast<void*>(NT_PRSTATUS),
+         &iov);
 }
 
 }  // namespace
diff --git a/services/network/proxy_resolving_client_socket.cc b/services/network/proxy_resolving_client_socket.cc
index 169b046..270ea99b 100644
--- a/services/network/proxy_resolving_client_socket.cc
+++ b/services/network/proxy_resolving_client_socket.cc
@@ -293,7 +293,7 @@
       proxy_annotation_tag, &ssl_config, &ssl_config, true /* force_tunnel */,
       net::PRIVACY_MODE_DISABLED, net::OnHostResolutionCallback(),
       net::MAXIMUM_PRIORITY, net::SocketTag(), net::NetworkIsolationKey(),
-      common_connect_job_params_, this);
+      false /* disable_secure_dns */, common_connect_job_params_, this);
   return connect_job_->Connect();
 }
 
diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTest.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTest.java
index dfb23e3..683b20fc 100644
--- a/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTest.java
+++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTest.java
@@ -20,8 +20,8 @@
     // Set the command line flags to be passed to the C++ main() method. Each
     // browser tests Activity should ensure these are included.
     public static final String BROWSER_TESTS_FLAGS[] = {
-            // content::kSingleProcessTestsFlag
-            "--single_process",
+            // switches::kSingleProcessTests
+            "--single-process-tests",
 
             // switches::kUseFakeDeviceForMediaStream
             "--use-fake-device-for-media-stream"};
diff --git a/testing/buildbot/filters/bfcache.browser_tests.filter b/testing/buildbot/filters/bfcache.browser_tests.filter
index 4fa7cc4..b9afc26 100644
--- a/testing/buildbot/filters/bfcache.browser_tests.filter
+++ b/testing/buildbot/filters/bfcache.browser_tests.filter
@@ -18,3 +18,9 @@
 
 # Flaky on the bots, need to be investigated, see https://crbug.com/1010870.
 -BookmarksCommandManagerTest.All
+
+# Time out since the removal of bfcache timed eviction. Probably waiting on the
+# RenderFrameHost deletion.
+-CredentialManagerBrowserTest.StoreInUnloadHandler_CrossSite_OnDemandMojoPipe
+-CredentialManagerBrowserTest.StoreInUnloadHandler_CrossSite_PreestablishedPipe
+
diff --git a/testing/buildbot/filters/e2e.sync_integration_tests.filter b/testing/buildbot/filters/e2e.sync_integration_tests.filter
index 95303be..8d2e296 100644
--- a/testing/buildbot/filters/e2e.sync_integration_tests.filter
+++ b/testing/buildbot/filters/e2e.sync_integration_tests.filter
@@ -24,3 +24,6 @@
 -TwoClientTypedUrlsSyncTest.AddThenDelete_E2ETest

 -TwoClientTypedUrlsSyncTest.DisableEnableSync_E2ETest

 -TwoClientAutofillProfileSyncTest.DISABLED_E2ETest_TwoClientsAddAutofillProfiles

+# Flaky on bots. Can't log in to GCM.

+-TwoClientDictionarySyncTest.Sanity_E2ETest

+-USS/TwoClientBookmarksSyncTestIncludingUssTests.E2ETest_TwoClientsAddBookmarks/0
\ No newline at end of file
diff --git a/third_party/blink/manual_tests/compositing/resources/composited-subframe.html b/third_party/blink/manual_tests/compositing/resources/composited-subframe.html
index 92b3b7f..1e15908 100644
--- a/third_party/blink/manual_tests/compositing/resources/composited-subframe.html
+++ b/third_party/blink/manual_tests/compositing/resources/composited-subframe.html
@@ -4,15 +4,15 @@
 <head>
   <style type="text/css" media="screen">
     body { background-color:silver }
-    
+
     .box {
         height: 200px;
         width: 200px;
         margin: 10px;
         padding: 5px;
         background-color: blue;
-        transform: translateZ(0);
-        overflow:hidden;
+        will-change: transform;
+        overflow: hidden;
     }
     .box:hover {
         transform: none;
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index cc13265..36b95844 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -71,6 +71,7 @@
     "frame/user_activation_state.h",
     "frame/user_activation_update_source.h",
     "frame/user_activation_update_type.h",
+    "fullscreen/fullscreen_options.h",
     "http/structured_header.h",
     "indexeddb/indexed_db_default_mojom_traits.h",
     "indexeddb/indexeddb_key.h",
diff --git a/third_party/blink/public/web/web_fullscreen_options.h b/third_party/blink/public/common/fullscreen/fullscreen_options.h
similarity index 61%
rename from third_party/blink/public/web/web_fullscreen_options.h
rename to third_party/blink/public/common/fullscreen/fullscreen_options.h
index ae7648b..c877d7b7 100644
--- a/third_party/blink/public/web/web_fullscreen_options.h
+++ b/third_party/blink/public/common/fullscreen/fullscreen_options.h
@@ -2,22 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_FULLSCREEN_OPTIONS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_FULLSCREEN_OPTIONS_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_FULLSCREEN_FULLSCREEN_OPTIONS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_FULLSCREEN_FULLSCREEN_OPTIONS_H_
 
 namespace blink {
 
 // Options used when requesting fullscreen.
-struct WebFullscreenOptions {
+struct FullScreenOptions {
   // Prefer that the bottom navigation bar be shown when in fullscreen
   // mode on devices with overlay navigation bars.
   bool prefers_navigation_bar = false;
 
-  bool operator==(const WebFullscreenOptions& rhs) {
+  bool operator==(const FullScreenOptions& rhs) {
     return prefers_navigation_bar == rhs.prefers_navigation_bar;
   }
 };
 
 }  // namespace blink
 
-#endif
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_FULLSCREEN_FULLSCREEN_OPTIONS_H_
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 03eef09..7d0ebf5 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -119,7 +119,7 @@
 struct FramePolicy;
 struct WebConsoleMessage;
 struct WebContextMenuData;
-struct WebFullscreenOptions;
+struct FullScreenOptions;
 struct WebPluginParams;
 struct WebPopupMenuInfo;
 struct WebRect;
@@ -778,7 +778,7 @@
   // After calling enterFullscreen or exitFullscreen,
   // WebWidget::didEnterFullscreen or WebWidget::didExitFullscreen
   // respectively will be called once the fullscreen mode has changed.
-  virtual void EnterFullscreen(const blink::WebFullscreenOptions& options) {}
+  virtual void EnterFullscreen(const blink::FullScreenOptions& options) {}
   virtual void ExitFullscreen() {}
 
   // Called when this frame changes fullscreen state.
diff --git a/third_party/blink/renderer/bindings/modules/BUILD.gn b/third_party/blink/renderer/bindings/modules/BUILD.gn
index 0f17d1f..3e85261 100644
--- a/third_party/blink/renderer/bindings/modules/BUILD.gn
+++ b/third_party/blink/renderer/bindings/modules/BUILD.gn
@@ -69,6 +69,7 @@
     "//third_party/blink/renderer/modules/speech/speech_synthesis_event.idl",
     "//third_party/blink/renderer/modules/storage/storage_event.idl",
     "//third_party/blink/renderer/modules/vr/vr_display_event.idl",
+    "//third_party/blink/renderer/modules/wake_lock/wake_lock_event.idl",
     "//third_party/blink/renderer/modules/webaudio/audio_processing_event.idl",
     "//third_party/blink/renderer/modules/webaudio/offline_audio_completion_event.idl",
     "//third_party/blink/renderer/modules/webgl/webgl_context_event.idl",
diff --git a/third_party/blink/renderer/bindings/modules/v8/BUILD.gn b/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
index 4adf793e2..7f20ac3 100644
--- a/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
+++ b/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
@@ -128,13 +128,6 @@
     "//third_party/blink/renderer/modules/mediarecorder:buildflags",
     "//third_party/dawn/src/dawn:dawn_headers",
   ]
-
-  if (!is_component_build && is_win) {
-    # This target as a static library (for non-component builds) is >4GB on
-    # Windows, this causes linking to fail. As a workaround, split it into
-    # multiple shards.
-    split_count = 5
-  }
 }
 
 action("generate_v8_context_snapshot_external_references") {
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index c1b944e..8a318a55 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1017,7 +1017,15 @@
 }
 
 # Compiles the code generated by the targets above.
-target("jumbo_" + core_link_small_target_type, "core_generated") {
+if (is_component_build) {
+  # To get exported symbols correct in component builds, the files must be in
+  # source sets.
+  core_generated_target_type = "source_set"
+} else {
+  core_generated_target_type = "static_library"
+}
+
+target("jumbo_" + core_generated_target_type, "core_generated") {
   sources = bindings_core_v8_files
 
   # Add all sources generated by the targets above.
diff --git a/third_party/blink/renderer/core/animation/BUILD.gn b/third_party/blink/renderer/core/animation/BUILD.gn
index 8e01888..9ac8273 100644
--- a/third_party/blink/renderer/core/animation/BUILD.gn
+++ b/third_party/blink/renderer/core/animation/BUILD.gn
@@ -19,7 +19,6 @@
 }
 
 blink_core_sources("animation") {
-  split_count = 5
   sources = [
     "animatable.cc",
     "animatable.h",
diff --git a/third_party/blink/renderer/core/core.gni b/third_party/blink/renderer/core/core.gni
index 97f02c4..b7df7c9 100644
--- a/third_party/blink/renderer/core/core.gni
+++ b/third_party/blink/renderer/core/core.gni
@@ -4,7 +4,6 @@
 
 import("//build/config/chrome_build.gni")
 import("//build/config/jumbo.gni")
-import("//build/split_static_library.gni")
 import("//third_party/blink/renderer/config.gni")
 
 blink_core_output_dir = "$root_gen_dir/third_party/blink/renderer/core"
@@ -33,22 +32,9 @@
 core_config_remove += [ "//build/config/compiler:default_symbols" ]
 core_config_add += blink_symbols_config
 
-# Use this target type to link core targets.
-if (is_component_build) {
-  # To get exported symbols correct in component builds, the files must be in
-  # source sets.
-  core_link_large_target_type = "source_set"
-  core_link_small_target_type = "source_set"
-} else {
-  # In static builds some of the libraries can get >2GB on Windows so we need
-  # to split the targets for the larger ones.
-  core_link_large_target_type = "split_static_library"
-  core_link_small_target_type = "static_library"
-}
-
 # Use this to generate a static library or source set that gets linked into
-# "core". This will either be a source_set (component build), a static library
-# (split_count undefined) or a split static library (split_count defined).
+# "core". This will either be a source_set (component build), or a static
+# library.
 #
 # Special values (all unlisted values are forwarded to the underlying library):
 #
@@ -59,12 +45,6 @@
 #      into account: just modify the configs as normal for target-specific
 #      overrides (or don't touch it).
 #
-#   split_count
-#      If defined, non-component builds will generate this number of static
-#      libraries by splitting the sources. This is for use on Windows where the
-#      maximum static library size is 2GB, and 64-bit builds with full symbols
-#      can exceed this if there are many sources.
-#
 #   deps
 #      Normal meaning but "core:prerequisites" target is always added. Callers
 #      shouldn't list prerequisites as a dependency.
@@ -74,23 +54,14 @@
 template("blink_core_sources") {
   if (is_component_build) {
     target_type = "jumbo_source_set"
-
-    # This assert avoids an unused variable warning.
-    assert(!defined(invoker.split_count) || invoker.split_count != 0)
-  } else if (!defined(invoker.split_count)) {
-    target_type = "jumbo_static_library"
   } else {
-    target_type = "jumbo_split_static_library"
+    target_type = "jumbo_static_library"
   }
   target(target_type, target_name) {
     # The visibility will get overridden by forward_variables_from below if the
     # invoker defined it.
     visibility = [ "//third_party/blink/renderer/core/*" ]
 
-    if (target_type == "jumbo_split_static_library") {
-      split_count = invoker.split_count
-    }
-
     deps = [
       "//third_party/blink/renderer/core:prerequisites",
     ]
@@ -111,7 +82,6 @@
                            [
                              "deps",
                              "public_deps",
-                             "split_count",
                            ])
   }
 }
diff --git a/third_party/blink/renderer/core/css/BUILD.gn b/third_party/blink/renderer/core/css/BUILD.gn
index b041c6c..6da3c4c 100644
--- a/third_party/blink/renderer/core/css/BUILD.gn
+++ b/third_party/blink/renderer/core/css/BUILD.gn
@@ -5,7 +5,6 @@
 import("//third_party/blink/renderer/core/core.gni")
 
 blink_core_sources("css") {
-  split_count = 10
   sources = [
     "abstract_property_set_css_style_declaration.cc",
     "abstract_property_set_css_style_declaration.h",
diff --git a/third_party/blink/renderer/core/dom/BUILD.gn b/third_party/blink/renderer/core/dom/BUILD.gn
index 394115b..76061e82 100644
--- a/third_party/blink/renderer/core/dom/BUILD.gn
+++ b/third_party/blink/renderer/core/dom/BUILD.gn
@@ -5,8 +5,6 @@
 import("//third_party/blink/renderer/core/core.gni")
 
 blink_core_sources("dom") {
-  split_count = 5
-
   sources = [
     "abort_controller.cc",
     "abort_controller.h",
diff --git a/third_party/blink/renderer/core/editing/BUILD.gn b/third_party/blink/renderer/core/editing/BUILD.gn
index 97d40a82..0e738f2 100644
--- a/third_party/blink/renderer/core/editing/BUILD.gn
+++ b/third_party/blink/renderer/core/editing/BUILD.gn
@@ -5,7 +5,6 @@
 import("//third_party/blink/renderer/core/core.gni")
 
 blink_core_sources("editing") {
-  split_count = 5
   sources = [
     "caret_display_item_client.cc",
     "caret_display_item_client.h",
diff --git a/third_party/blink/renderer/core/events/event_type_names.json5 b/third_party/blink/renderer/core/events/event_type_names.json5
index 4ac3f41..9d61388 100644
--- a/third_party/blink/renderer/core/events/event_type_names.json5
+++ b/third_party/blink/renderer/core/events/event_type_names.json5
@@ -229,6 +229,7 @@
     "reading",
     "readystatechange",
     "rejectionhandled",
+    "release",
     "removesourcebuffer",
     "removestream",
     "removetrack",
diff --git a/third_party/blink/renderer/core/frame/fullscreen_controller.cc b/third_party/blink/renderer/core/frame/fullscreen_controller.cc
index 13d190ce..9df3f10 100644
--- a/third_party/blink/renderer/core/frame/fullscreen_controller.cc
+++ b/third_party/blink/renderer/core/frame/fullscreen_controller.cc
@@ -31,7 +31,7 @@
 #include "third_party/blink/renderer/core/frame/fullscreen_controller.h"
 
 #include "base/memory/ptr_util.h"
-#include "third_party/blink/public/web/web_fullscreen_options.h"
+#include "third_party/blink/public/common/fullscreen/fullscreen_options.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
@@ -168,7 +168,7 @@
     return;
 
   DCHECK(state_ == State::kInitial);
-  blink::WebFullscreenOptions blink_options;
+  blink::FullScreenOptions blink_options;
   // Only clone options if the feature is enabled.
   blink_options.prefers_navigation_bar = options->navigationUI() != "hide";
   GetWebFrameClient(frame).EnterFullscreen(blink_options);
diff --git a/third_party/blink/renderer/core/geometry/BUILD.gn b/third_party/blink/renderer/core/geometry/BUILD.gn
index e9970e2..7f26639 100644
--- a/third_party/blink/renderer/core/geometry/BUILD.gn
+++ b/third_party/blink/renderer/core/geometry/BUILD.gn
@@ -5,8 +5,6 @@
 import("//third_party/blink/renderer/core/core.gni")
 
 blink_core_sources("geometry") {
-  split_count = 5
-
   sources = [
     "dom_matrix.cc",
     "dom_matrix.h",
diff --git a/third_party/blink/renderer/core/html/BUILD.gn b/third_party/blink/renderer/core/html/BUILD.gn
index 7e64691..1becb65 100644
--- a/third_party/blink/renderer/core/html/BUILD.gn
+++ b/third_party/blink/renderer/core/html/BUILD.gn
@@ -2,12 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/split_static_library.gni")
 import("//third_party/blink/renderer/core/core.gni")
 
 blink_core_sources("html") {
-  split_count = 4
-
   sources = [
     "anchor_element_metrics.cc",
     "anchor_element_metrics.h",
diff --git a/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc b/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
index 89ee422..d55b0f5 100644
--- a/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
+++ b/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
@@ -31,7 +31,7 @@
     return new EmptyWebMediaPlayer();
   }
 
-  void EnterFullscreen(const blink::WebFullscreenOptions&) final {
+  void EnterFullscreen(const blink::FullScreenOptions&) final {
     Thread::Current()->GetTaskRunner()->PostTask(
         FROM_HERE,
         WTF::Bind(
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn
index be29a9c..18a5174 100644
--- a/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -5,8 +5,6 @@
 import("//third_party/blink/renderer/core/core.gni")
 
 blink_core_sources("layout") {
-  split_count = 5
-
   sources = [
     "api/hit_test_action.h",
     "api/line_layout_api_shim.h",
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
index 13220f6d..d08cd06 100644
--- a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
+++ b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
@@ -131,7 +131,11 @@
   // calculated and set before layout. Copy this to the actual column-span:all
   // object before laying it out, so that it gets paginated correctly, in case
   // we have an enclosing fragmentation context.
-  layout_object_in_flow_thread_->SetLogicalTop(LogicalTop());
+  if (layout_object_in_flow_thread_->LogicalTop() != LogicalTop()) {
+    layout_object_in_flow_thread_->SetLogicalTop(LogicalTop());
+    if (FlowThread()->EnclosingFragmentationContext())
+      layout_object_in_flow_thread_->SetChildNeedsLayout(kMarkOnlyThis);
+  }
 
   // Lay out the actual column-span:all element.
   layout_object_in_flow_thread_->LayoutIfNeeded();
diff --git a/third_party/blink/renderer/core/paint/BUILD.gn b/third_party/blink/renderer/core/paint/BUILD.gn
index 8c07443..335341d4 100644
--- a/third_party/blink/renderer/core/paint/BUILD.gn
+++ b/third_party/blink/renderer/core/paint/BUILD.gn
@@ -5,7 +5,6 @@
 import("//third_party/blink/renderer/core/core.gni")
 
 blink_core_sources("paint") {
-  split_count = 2
   sources = [
     "applied_decoration_painter.cc",
     "applied_decoration_painter.h",
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
index e4946a2..91161e7 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -1296,9 +1296,9 @@
   // This test verifies layers with direct compositing reasons won't have
   // transformed rasterization, i.e. should raster in local space.
   SetBodyInnerHTML(R"HTML(
-    <div id='target1' style='transform:translateZ(0);'>foo</div>
-    <div id='target2' style='will-change:opacity;'>bar</div>
-    <div id='target3' style='backface-visibility:hidden;'>ham</div>
+    <div id='target1' style='will-change: transform;'>foo</div>
+    <div id='target2' style='will-change: opacity;'>bar</div>
+    <div id='target3' style='backface-visibility: hidden;'>ham</div>
   )HTML");
 
   {
@@ -1539,11 +1539,10 @@
     return;
 
   SetHtmlInnerHTML(R"HTML(
-    <div id=scroller style="transform: translateZ(0); overflow: scroll;
-    width: 200px; height: 400px;">
-      <div id=squashing
-          style='width: 200px; height: 200px; position: relative; will-change:
-transform'></div>
+    <div id=scroller style="will-change: transform; overflow: scroll;
+        width: 200px; height: 400px;">
+      <div id=squashing style='width: 200px; height: 200px; position: relative;
+          will-change: transform'></div>
       <div id=squashed style="width: 200px; height: 6000px; top: -100px;
           position: relative;">
       </div>
diff --git a/third_party/blink/renderer/core/script/BUILD.gn b/third_party/blink/renderer/core/script/BUILD.gn
index 80193de..c4d1640 100644
--- a/third_party/blink/renderer/core/script/BUILD.gn
+++ b/third_party/blink/renderer/core/script/BUILD.gn
@@ -5,8 +5,6 @@
 import("//third_party/blink/renderer/core/core.gni")
 
 blink_core_sources("script") {
-  split_count = 5
-
   sources = [
     "classic_pending_script.cc",
     "classic_pending_script.h",
diff --git a/third_party/blink/renderer/core/svg/BUILD.gn b/third_party/blink/renderer/core/svg/BUILD.gn
index 69d9ddc..5e0e345 100644
--- a/third_party/blink/renderer/core/svg/BUILD.gn
+++ b/third_party/blink/renderer/core/svg/BUILD.gn
@@ -5,14 +5,6 @@
 import("//third_party/blink/renderer/core/core.gni")
 
 blink_core_sources("svg") {
-  # Split into multiple static libraries on Windows official builds, where we
-  # run into a 2GB max size limit.
-  if (is_win && is_official_build) {
-    split_count = 5
-  } else {
-    split_count = 1
-  }
-
   sources = [
     "animation/smil_animation_sandwich.cc",
     "animation/smil_animation_sandwich.h",
diff --git a/third_party/blink/renderer/core/testing/data/composited_selection_bounds_split_layer.html b/third_party/blink/renderer/core/testing/data/composited_selection_bounds_split_layer.html
index 105278f..5c1879f 100644
--- a/third_party/blink/renderer/core/testing/data/composited_selection_bounds_split_layer.html
+++ b/third_party/blink/renderer/core/testing/data/composited_selection_bounds_split_layer.html
@@ -9,7 +9,7 @@
     }
 
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 </style>
 <div id="layer1" class="composited">The quick brown fox</div>
diff --git a/third_party/blink/renderer/core/testing/data/rgm_test.html b/third_party/blink/renderer/core/testing/data/rgm_test.html
index 9c0ea9f..1e4e9a2 100644
--- a/third_party/blink/renderer/core/testing/data/rgm_test.html
+++ b/third_party/blink/renderer/core/testing/data/rgm_test.html
@@ -2,7 +2,7 @@
     div {
         border-style:solid;
         border-width:1px;
-        transform:translate3d(0, 0, 0);
+        will-change:transform;
         position:relative;
         padding:5px 0px;
         width:500px;
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index a52ad1f..baa98be 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 import("//build/config/chromecast_build.gni")
-import("//build/split_static_library.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//third_party/blink/renderer/bindings/bindings.gni")
 import("//third_party/blink/renderer/bindings/modules/v8/generated.gni")
@@ -18,16 +17,6 @@
 
 visibility = [ "//third_party/blink/renderer/*" ]
 
-if (!is_component_build && is_win) {
-  # This target as a static library (for non-component builds) is >2GB for
-  # official builds and some goma builds on Windows. This causes linking to
-  # fail. As a workaround, force using a split static library for these
-  # configurations.
-  modules_target_type = "split_static_library"
-} else {
-  modules_target_type = "component"
-}
-
 config("modules_implementation") {
   defines = [ "BLINK_MODULES_IMPLEMENTATION=1" ]
 }
@@ -38,13 +27,9 @@
   deps = []  # Don't use default deps (otherwise it will be circular).
 }
 
-target("jumbo_" + modules_target_type, "modules") {
+jumbo_component("modules") {
   output_name = "blink_modules"
 
-  if (modules_target_type == "split_static_library") {
-    split_count = 5
-  }
-
   visibility = []  # Allow re-assignment of list.
   visibility = [ "//third_party/blink/*" ]
 
@@ -416,8 +401,9 @@
     "service_worker/service_worker_timeout_timer_test.cc",
     "service_worker/thread_safe_script_container_test.cc",
     "service_worker/web_embedded_worker_impl_test.cc",
-    "wake_lock/wake_lock_controller_test.cc",
+    "wake_lock/wake_lock_sentinel_test.cc",
     "wake_lock/wake_lock_state_record_test.cc",
+    "wake_lock/wake_lock_test.cc",
     "wake_lock/wake_lock_test_utils.cc",
     "wake_lock/wake_lock_test_utils.h",
     "webaudio/audio_basic_processor_handler_test.cc",
diff --git a/third_party/blink/renderer/modules/event_target_modules_names.json5 b/third_party/blink/renderer/modules/event_target_modules_names.json5
index 3bb3fe8..3445dc8 100644
--- a/third_party/blink/renderer/modules/event_target_modules_names.json5
+++ b/third_party/blink/renderer/modules/event_target_modules_names.json5
@@ -77,5 +77,6 @@
       ImplementedAs: "DOMWebSocket",
     },
     "USB",
+    "WakeLockSentinel",
   ],
 }
diff --git a/third_party/blink/renderer/modules/modules.gni b/third_party/blink/renderer/modules/modules.gni
index 3d3ee40..30d8be5 100644
--- a/third_party/blink/renderer/modules/modules.gni
+++ b/third_party/blink/renderer/modules/modules.gni
@@ -8,9 +8,7 @@
 # to the huge and slow lists of sources. If sharing is necessary, make a
 # separate .gni.
 import("//build/config/jumbo.gni")
-import("//build/split_static_library.gni")
 import("//third_party/blink/renderer/config.gni")
-
 blink_modules_output_dir = "$root_gen_dir/third_party/blink/renderer/modules"
 
 # Defines a part of blink modules. This is either a source set or a static
@@ -25,11 +23,7 @@
   if (is_component_build) {
     target_type = "source_set"
   } else {
-    if (!defined(invoker.split_count)) {
-      target_type = "static_library"
-    } else {
-      target_type = "split_static_library"
-    }
+    target_type = "static_library"
   }
 
   target("jumbo_" + target_type, target_name) {
@@ -45,17 +39,9 @@
     if (defined(invoker.deps)) {
       deps += invoker.deps
     }
-    if (target_type == "split_static_library") {
-      split_count = invoker.split_count
-    }
 
     # Take everything else not handled above from the invoker.
-    forward_variables_from(invoker,
-                           "*",
-                           [
-                             "deps",
-                             "split_count",
-                           ])
+    forward_variables_from(invoker, "*", [ "deps" ])
   }
 }
 set_defaults("blink_modules_sources") {
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index 2fb3d77c..39fbbaf 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -354,6 +354,8 @@
           "vr/vr_pose.idl",
           "vr/vr_stage_parameters.idl",
           "wake_lock/wake_lock.idl",
+          "wake_lock/wake_lock_event.idl",
+          "wake_lock/wake_lock_sentinel.idl",
           "webaudio/analyser_node.idl",
           "webaudio/audio_buffer.idl",
           "webaudio/audio_buffer_source_node.idl",
@@ -801,7 +803,7 @@
           "storage/storage_event_init.idl",
           "vr/vr_display_event_init.idl",
           "vr/vr_layer_init.idl",
-          "wake_lock/wake_lock_request_options.idl",
+          "wake_lock/wake_lock_event_init.idl",
           "webaudio/analyser_options.idl",
           "webaudio/audio_buffer_options.idl",
           "webaudio/audio_buffer_source_options.idl",
@@ -1011,6 +1013,8 @@
           "storage/window_storage.idl",
           "vibration/navigator_vibration.idl",
           "vr/navigator_vr.idl",
+          "wake_lock/navigator_wake_lock.idl",
+          "wake_lock/worker_navigator_wake_lock.idl",
           "webdatabase/window_web_database.idl",
           "webgl/webgl2_rendering_context_base.idl",
           "webgl/webgl_rendering_context_base.idl",
diff --git a/third_party/blink/renderer/modules/peerconnection/OWNERS b/third_party/blink/renderer/modules/peerconnection/OWNERS
index 347366a..f2eebf8 100644
--- a/third_party/blink/renderer/modules/peerconnection/OWNERS
+++ b/third_party/blink/renderer/modules/peerconnection/OWNERS
@@ -1,6 +1,7 @@
 guidou@chromium.org
 hbos@chromium.org
 orphis@chromium.org
+sergeyu@chromium.org
 steveanton@chromium.org
 tommi@chromium.org
 
diff --git a/third_party/blink/renderer/modules/wake_lock/BUILD.gn b/third_party/blink/renderer/modules/wake_lock/BUILD.gn
index 5ac56b2..d9feea5 100644
--- a/third_party/blink/renderer/modules/wake_lock/BUILD.gn
+++ b/third_party/blink/renderer/modules/wake_lock/BUILD.gn
@@ -6,14 +6,20 @@
 
 blink_modules_sources("wake_lock") {
   sources = [
+    "navigator_wake_lock.cc",
+    "navigator_wake_lock.h",
     "wake_lock.cc",
     "wake_lock.h",
-    "wake_lock_controller.cc",
-    "wake_lock_controller.h",
+    "wake_lock_event.cc",
+    "wake_lock_event.h",
+    "wake_lock_sentinel.cc",
+    "wake_lock_sentinel.h",
     "wake_lock_state_record.cc",
     "wake_lock_state_record.h",
     "wake_lock_type.cc",
     "wake_lock_type.h",
+    "worker_navigator_wake_lock.cc",
+    "worker_navigator_wake_lock.h",
   ]
   deps = [
     "//mojo/public/cpp/bindings",
diff --git a/third_party/blink/renderer/modules/wake_lock/DEPS b/third_party/blink/renderer/modules/wake_lock/DEPS
index 12b0536..271ccdb 100644
--- a/third_party/blink/renderer/modules/wake_lock/DEPS
+++ b/third_party/blink/renderer/modules/wake_lock/DEPS
@@ -6,7 +6,7 @@
 ]
 
 specific_include_rules = {
-  "wake_lock_test_utils\.cc": [
+  "wake_lock_test_utils\.cc|.+_test\.cc": [
     "+base/run_loop.h",
   ],
 }
diff --git a/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.cc b/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.cc
new file mode 100644
index 0000000..e6f900b
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.cc
@@ -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.
+
+#include "third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.h"
+
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock.h"
+
+namespace blink {
+
+NavigatorWakeLock::NavigatorWakeLock(Navigator& navigator)
+    : Supplement<Navigator>(navigator) {}
+
+WakeLock* NavigatorWakeLock::GetWakeLock() {
+  if (!wake_lock_) {
+    auto* frame = GetSupplementable()->GetFrame();
+    if (frame) {
+      DCHECK(frame->GetDocument());
+      wake_lock_ = MakeGarbageCollected<WakeLock>(*frame->GetDocument());
+    }
+  }
+  return wake_lock_;
+}
+
+// static
+const char NavigatorWakeLock::kSupplementName[] = "NavigatorWakeLock";
+
+// static
+NavigatorWakeLock& NavigatorWakeLock::From(Navigator& navigator) {
+  NavigatorWakeLock* supplement =
+      Supplement<Navigator>::From<NavigatorWakeLock>(navigator);
+  if (!supplement) {
+    supplement = MakeGarbageCollected<NavigatorWakeLock>(navigator);
+    ProvideTo(navigator, supplement);
+  }
+  return *supplement;
+}
+
+// static
+WakeLock* NavigatorWakeLock::wakeLock(Navigator& navigator) {
+  return NavigatorWakeLock::From(navigator).GetWakeLock();
+}
+
+void NavigatorWakeLock::Trace(blink::Visitor* visitor) {
+  visitor->Trace(wake_lock_);
+  Supplement<Navigator>::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.h b/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.h
new file mode 100644
index 0000000..bdfd505
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.h
@@ -0,0 +1,39 @@
+// 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_MODULES_WAKE_LOCK_NAVIGATOR_WAKE_LOCK_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_NAVIGATOR_WAKE_LOCK_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class Navigator;
+class WakeLock;
+
+class NavigatorWakeLock final : public GarbageCollected<NavigatorWakeLock>,
+                                public Supplement<Navigator> {
+  USING_GARBAGE_COLLECTED_MIXIN(NavigatorWakeLock);
+
+ public:
+  static const char kSupplementName[];
+
+  static NavigatorWakeLock& From(Navigator&);
+
+  static WakeLock* wakeLock(Navigator&);
+
+  explicit NavigatorWakeLock(Navigator&);
+
+  void Trace(blink::Visitor*) override;
+
+ private:
+  WakeLock* GetWakeLock();
+
+  Member<WakeLock> wake_lock_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_NAVIGATOR_WAKE_LOCK_H_
diff --git a/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl b/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl
new file mode 100644
index 0000000..36fc458
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl
@@ -0,0 +1,11 @@
+// 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.
+
+[
+  ImplementedAs=NavigatorWakeLock,
+  RuntimeEnabled=WakeLock,
+  SecureContext
+] partial interface Navigator {
+  [SameObject] readonly attribute WakeLock wakeLock;
+};
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
index e73c883..4d6da59 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
@@ -6,13 +6,13 @@
 
 #include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/abort_signal.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_request_options.h"
+#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h"
 #include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -20,28 +20,28 @@
 
 namespace blink {
 
-// static
-ScriptPromise WakeLock::requestPermission(ScriptState* script_state,
-                                          const String& type) {
-  // https://w3c.github.io/wake-lock/#requestpermission-static-method
-  // 1. Let promise be a new promise.
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-  ScriptPromise promise = resolver->Promise();
+using mojom::blink::PermissionService;
+using mojom::blink::PermissionStatus;
 
-  // 2. Return promise and run the following steps in parallel:
-  // 2.1. Let state be the result of running and waiting for the obtain
-  //      permission steps with type.
-  // 2.2. Resolve promise with state.
-  auto* document = To<Document>(ExecutionContext::From(script_state));
-  WakeLockController::From(document).RequestPermission(ToWakeLockType(type),
-                                                       resolver);
-  return promise;
-}
+WakeLock::WakeLock(Document& document)
+    : ContextLifecycleObserver(&document),
+      PageVisibilityObserver(document.GetPage()),
+      state_records_{
+          MakeGarbageCollected<WakeLockStateRecord>(&document,
+                                                    WakeLockType::kScreen),
+          MakeGarbageCollected<WakeLockStateRecord>(&document,
+                                                    WakeLockType::kSystem)} {}
 
-// static
-ScriptPromise WakeLock::request(ScriptState* script_state,
-                                const String& type,
-                                WakeLockRequestOptions* options) {
+WakeLock::WakeLock(DedicatedWorkerGlobalScope& worker_scope)
+    : ContextLifecycleObserver(&worker_scope),
+      PageVisibilityObserver(nullptr),
+      state_records_{
+          MakeGarbageCollected<WakeLockStateRecord>(&worker_scope,
+                                                    WakeLockType::kScreen),
+          MakeGarbageCollected<WakeLockStateRecord>(&worker_scope,
+                                                    WakeLockType::kSystem)} {}
+
+ScriptPromise WakeLock::request(ScriptState* script_state, const String& type) {
   // https://w3c.github.io/wake-lock/#request-static-method
   auto* context = ExecutionContext::From(script_state);
   DCHECK(context->IsDocument() || context->IsDedicatedWorkerGlobalScope());
@@ -112,21 +112,10 @@
     }
   }
 
-  // 5. If options' signal member is present, then run the following steps:
-  // 5.1. Let signal be options's signal member.
-  // 5.2. If signal’s aborted flag is set, then reject promise with an
-  //      "AbortError" DOMException and return promise.
-  if (options->hasSignal() && options->signal()->aborted()) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state,
-        MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError));
-  }
-
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
 
   WakeLockType wake_lock_type = ToWakeLockType(type);
-  WakeLockController& controller = WakeLockController::From(context);
 
   switch (wake_lock_type) {
     case WakeLockType::kScreen:
@@ -140,20 +129,140 @@
       break;
   }
 
-  // 5.3. Otherwise, add to signal:
-  // 5.3.1. Run release a wake lock with promise and type.
-  if (options->hasSignal()) {
-    options->signal()->AddAlgorithm(WTF::Bind(
-        &WakeLockController::ReleaseWakeLock, WrapWeakPersistent(&controller),
-        wake_lock_type, WrapPersistent(resolver)));
-  }
-
   // 6. Run the following steps in parallel, but abort when options' signal
   // member is present and its aborted flag is set:
-  controller.RequestWakeLock(wake_lock_type, resolver, options->signal());
+  // 6.1. Let state be the result of awaiting obtain permission steps with
+  //      type:
+  DoRequest(wake_lock_type, resolver);
 
   // 7. Return promise.
   return promise;
 }
 
+void WakeLock::DoRequest(WakeLockType type, ScriptPromiseResolver* resolver) {
+  ObtainPermission(
+      type, WTF::Bind(&WakeLock::DidReceivePermissionResponse,
+                      WrapPersistent(this), type, WrapPersistent(resolver)));
+}
+
+void WakeLock::DidReceivePermissionResponse(WakeLockType type,
+                                            ScriptPromiseResolver* resolver,
+                                            PermissionStatus status) {
+  // https://w3c.github.io/wake-lock/#request-static-method
+  DCHECK(status == PermissionStatus::GRANTED ||
+         status == PermissionStatus::DENIED);
+  DCHECK(resolver);
+  // 6.1.1. If state is "denied", then reject promise with a "NotAllowedError"
+  //        DOMException, and abort these steps.
+  if (status != PermissionStatus::GRANTED) {
+    resolver->Reject(MakeGarbageCollected<DOMException>(
+        DOMExceptionCode::kNotAllowedError,
+        "Wake Lock permission request denied"));
+    return;
+  }
+  // https://github.com/w3c/wake-lock/issues/222: the page can become hidden
+  // between request() and WakeLockStateRecord::AcquireWakeLock(), in which case
+  // we need to abort early.
+  if (type == WakeLockType::kScreen &&
+      !(GetPage() && GetPage()->IsPageVisible())) {
+    resolver->Reject(MakeGarbageCollected<DOMException>(
+        DOMExceptionCode::kNotAllowedError,
+        "The requesting page is not visible"));
+    return;
+  }
+  // 6.2. Let success be the result of awaiting acquire a wake lock with promise
+  // and type:
+  // 6.2.1. If success is false then reject promise with a "NotAllowedError"
+  //        DOMException, and abort these steps.
+  WakeLockStateRecord* state_record = state_records_[static_cast<size_t>(type)];
+  DCHECK(state_record);
+  state_record->AcquireWakeLock(resolver);
+}
+
+void WakeLock::ContextDestroyed(ExecutionContext*) {
+  // https://w3c.github.io/wake-lock/#handling-document-loss-of-full-activity
+  // 1. Let document be the responsible document of the current settings object.
+  // 2. Let screenRecord be the platform wake lock's state record associated
+  // with document and wake lock type "screen".
+  // 3. For each lockPromise in screenRecord.[[WakeLockStateRecord]]:
+  // 3.1. Run release a wake lock with lockPromise and "screen".
+  // 4. Let systemRecord be the platform wake lock's state record associated
+  // with document and wake lock type "system".
+  // 5. For each lockPromise in systemRecord.[[WakeLockStateRecord]]:
+  // 5.1. Run release a wake lock with lockPromise and "system".
+  for (WakeLockStateRecord* state_record : state_records_) {
+    if (state_record)
+      state_record->ClearWakeLocks();
+  }
+}
+
+void WakeLock::PageVisibilityChanged() {
+  // https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
+  // 1. Let document be the Document of the top-level browsing context.
+  // 2. If document's visibility state is "visible", abort these steps.
+  if (GetPage() && GetPage()->IsPageVisible())
+    return;
+  // 3. Let screenRecord be the platform wake lock's state record associated
+  // with wake lock type "screen".
+  // 4. For each lockPromise in screenRecord.[[WakeLockStateRecord]]:
+  // 4.1. Run release a wake lock with lockPromise and "screen".
+  WakeLockStateRecord* state_record =
+      state_records_[static_cast<size_t>(WakeLockType::kScreen)];
+  if (state_record)
+    state_record->ClearWakeLocks();
+}
+
+void WakeLock::ObtainPermission(
+    WakeLockType type,
+    base::OnceCallback<void(PermissionStatus)> callback) {
+  // https://w3c.github.io/wake-lock/#dfn-obtain-permission
+  // Note we actually implement a simplified version of the "obtain permission"
+  // algorithm that essentially just calls the "request permission to use"
+  // algorithm from the Permissions spec (i.e. we bypass all the steps covering
+  // calling the "query a permission" algorithm and handling its result).
+  // * Right now, we can do that because there is no way for Chromium's
+  //   permission system to get to the "prompt" state given how
+  //   WakeLockPermissionContext is currently implemented.
+  // * Even if WakeLockPermissionContext changes in the future, this Blink
+  //   implementation is unlikely to change because
+  //   WakeLockPermissionContext::RequestPermission() will take its
+  //   |user_gesture| argument into account to actually implement a slightly
+  //   altered version of "request permission to use", the behavior of which
+  //   will match the definition of "obtain permission" in the Wake Lock spec.
+  DCHECK(type == WakeLockType::kScreen || type == WakeLockType::kSystem);
+  static_assert(
+      static_cast<mojom::blink::WakeLockType>(WakeLockType::kScreen) ==
+          mojom::blink::WakeLockType::kScreen,
+      "WakeLockType and mojom::blink::WakeLockType must have identical values");
+  static_assert(
+      static_cast<mojom::blink::WakeLockType>(WakeLockType::kSystem) ==
+          mojom::blink::WakeLockType::kSystem,
+      "WakeLockType and mojom::blink::WakeLockType must have identical values");
+
+  auto* local_frame = GetExecutionContext()->IsDocument()
+                          ? To<Document>(GetExecutionContext())->GetFrame()
+                          : nullptr;
+  GetPermissionService()->RequestPermission(
+      CreateWakeLockPermissionDescriptor(
+          static_cast<mojom::blink::WakeLockType>(type)),
+      LocalFrame::HasTransientUserActivation(local_frame), std::move(callback));
+}
+
+PermissionService* WakeLock::GetPermissionService() {
+  if (!permission_service_) {
+    ConnectToPermissionService(
+        GetExecutionContext(),
+        permission_service_.BindNewPipeAndPassReceiver());
+  }
+  return permission_service_.get();
+}
+
+void WakeLock::Trace(Visitor* visitor) {
+  for (WakeLockStateRecord* state_record : state_records_)
+    visitor->Trace(state_record);
+  PageVisibilityObserver::Trace(visitor);
+  ContextLifecycleObserver::Trace(visitor);
+  ScriptWrappable::Trace(visitor);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock.h b/third_party/blink/renderer/modules/wake_lock/wake_lock.h
index 4042b2b..a22e5e2 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock.h
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock.h
@@ -5,8 +5,18 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_H_
 
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
+#include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace WTF {
 
@@ -16,17 +26,59 @@
 
 namespace blink {
 
+class ExecutionContext;
 class ScriptState;
-class WakeLockRequestOptions;
+class WakeLockStateRecord;
 
-class WakeLock final : public ScriptWrappable {
+class MODULES_EXPORT WakeLock final : public ScriptWrappable,
+                                      public ContextLifecycleObserver,
+                                      public PageVisibilityObserver {
+  USING_GARBAGE_COLLECTED_MIXIN(WakeLock);
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static ScriptPromise requestPermission(ScriptState*, const WTF::String& type);
-  static ScriptPromise request(ScriptState*,
-                               const WTF::String& type,
-                               WakeLockRequestOptions*);
+  explicit WakeLock(Document&);
+  explicit WakeLock(DedicatedWorkerGlobalScope&);
+
+  ScriptPromise request(ScriptState*, const WTF::String& type);
+
+  void Trace(blink::Visitor*) override;
+
+ private:
+  // While this could be part of request() itself, having it as a separate
+  // function makes testing (which uses a custom ScriptPromiseResolver) a lot
+  // easier.
+  void DoRequest(WakeLockType, ScriptPromiseResolver*);
+
+  void DidReceivePermissionResponse(WakeLockType,
+                                    ScriptPromiseResolver*,
+                                    mojom::blink::PermissionStatus);
+
+  // ContextLifecycleObserver implementation
+  void ContextDestroyed(ExecutionContext*) override;
+
+  // PageVisibilityObserver implementation
+  void PageVisibilityChanged() override;
+
+  // Permission handling
+  void ObtainPermission(
+      WakeLockType,
+      base::OnceCallback<void(mojom::blink::PermissionStatus)> callback);
+  mojom::blink::PermissionService* GetPermissionService();
+
+  mojo::Remote<mojom::blink::PermissionService> permission_service_;
+
+  // https://w3c.github.io/wake-lock/#concepts-and-state-record
+  // Each platform wake lock (one per wake lock type) has an associated state
+  // record per responsible document [...] internal slots.
+  Member<WakeLockStateRecord> state_records_[kWakeLockTypeCount];
+
+  FRIEND_TEST_ALL_PREFIXES(WakeLockTest, RequestWakeLockGranted);
+  FRIEND_TEST_ALL_PREFIXES(WakeLockTest, RequestWakeLockDenied);
+  FRIEND_TEST_ALL_PREFIXES(WakeLockTest, LossOfDocumentActivity);
+  FRIEND_TEST_ALL_PREFIXES(WakeLockTest, PageVisibilityHidden);
+  FRIEND_TEST_ALL_PREFIXES(WakeLockTest,
+                           PageVisibilityHiddenBeforeLockAcquisition);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock.idl b/third_party/blink/renderer/modules/wake_lock/wake_lock.idl
index 6fd074a..806981c 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock.idl
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock.idl
@@ -13,6 +13,5 @@
   Exposed=(DedicatedWorker,Window),
   RuntimeEnabled=WakeLock
 ] interface WakeLock {
-  [CallWith=ScriptState, Exposed=Window] static Promise<PermissionState> requestPermission(WakeLockType type);
-  [CallWith=ScriptState] static Promise<void> request(WakeLockType type, optional WakeLockRequestOptions options);
+  [CallWith=ScriptState] Promise<WakeLockSentinel> request(WakeLockType type);
 };
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc
deleted file mode 100644
index d760cfe..0000000
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc
+++ /dev/null
@@ -1,236 +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 "third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/abort_signal.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-
-namespace blink {
-
-using mojom::blink::PermissionService;
-using mojom::blink::PermissionStatus;
-
-WakeLockController::WakeLockController(Document& document)
-    : Supplement<ExecutionContext>(document),
-      ContextLifecycleObserver(&document),
-      PageVisibilityObserver(document.GetPage()),
-      state_records_{
-          MakeGarbageCollected<WakeLockStateRecord>(&document,
-                                                    WakeLockType::kScreen),
-          MakeGarbageCollected<WakeLockStateRecord>(&document,
-                                                    WakeLockType::kSystem)} {}
-
-WakeLockController::WakeLockController(DedicatedWorkerGlobalScope& worker_scope)
-    : Supplement<ExecutionContext>(worker_scope),
-      ContextLifecycleObserver(&worker_scope),
-      PageVisibilityObserver(nullptr),
-      state_records_{
-          MakeGarbageCollected<WakeLockStateRecord>(&worker_scope,
-                                                    WakeLockType::kScreen),
-          MakeGarbageCollected<WakeLockStateRecord>(&worker_scope,
-                                                    WakeLockType::kSystem)} {}
-
-const char WakeLockController::kSupplementName[] = "WakeLockController";
-
-// static
-WakeLockController& WakeLockController::From(
-    ExecutionContext* execution_context) {
-  DCHECK(execution_context->IsDocument() ||
-         execution_context->IsDedicatedWorkerGlobalScope());
-  auto* controller =
-      Supplement<ExecutionContext>::From<WakeLockController>(execution_context);
-  if (!controller) {
-    if (execution_context->IsDocument()) {
-      controller = MakeGarbageCollected<WakeLockController>(
-          *To<Document>(execution_context));
-    } else {
-      controller = MakeGarbageCollected<WakeLockController>(
-          *To<DedicatedWorkerGlobalScope>(execution_context));
-    }
-    Supplement<ExecutionContext>::ProvideTo(*execution_context, controller);
-  }
-  return *controller;
-}
-
-void WakeLockController::Trace(Visitor* visitor) {
-  for (WakeLockStateRecord* state_record : state_records_)
-    visitor->Trace(state_record);
-  PageVisibilityObserver::Trace(visitor);
-  ContextLifecycleObserver::Trace(visitor);
-  Supplement<ExecutionContext>::Trace(visitor);
-}
-
-void WakeLockController::RequestWakeLock(WakeLockType type,
-                                         ScriptPromiseResolver* resolver,
-                                         AbortSignal* signal) {
-  // https://w3c.github.io/wake-lock/#request-static-method
-  // 6. [...] abort when options' signal member is present and its aborted flag
-  // is set:
-  DCHECK(resolver);
-  // We were called via WakeLock::request(), which should have handled the
-  // signal->aborted() case.
-  DCHECK(!signal || !signal->aborted());
-  // 6.1. Let state be the result of awaiting obtain permission steps with
-  // type:
-  ObtainPermission(
-      type, WTF::Bind(&WakeLockController::DidReceivePermissionResponse,
-                      WrapPersistent(this), type, WrapPersistent(resolver),
-                      WrapPersistent(signal)));
-}
-
-void WakeLockController::DidReceivePermissionResponse(
-    WakeLockType type,
-    ScriptPromiseResolver* resolver,
-    AbortSignal* signal,
-    PermissionStatus status) {
-  // https://w3c.github.io/wake-lock/#request-static-method
-  DCHECK(status == PermissionStatus::GRANTED ||
-         status == PermissionStatus::DENIED);
-  DCHECK(resolver);
-  if (signal && signal->aborted())
-    return;
-  // 6.1.1. If state is "denied", then reject promise with a "NotAllowedError"
-  //        DOMException, and abort these steps.
-  if (status != PermissionStatus::GRANTED) {
-    resolver->Reject(MakeGarbageCollected<DOMException>(
-        DOMExceptionCode::kNotAllowedError,
-        "Wake Lock permission request denied"));
-    return;
-  }
-  // https://github.com/w3c/wake-lock/issues/222: the page can become hidden
-  // between RequestWakeLock() and AcquireWakeLock(), in which case we need to
-  // abort early.
-  if (type == WakeLockType::kScreen &&
-      !(GetPage() && GetPage()->IsPageVisible())) {
-    resolver->Reject(MakeGarbageCollected<DOMException>(
-        DOMExceptionCode::kNotAllowedError,
-        "The requesting page is not visible"));
-    return;
-  }
-  // 6.2. Let success be the result of awaiting acquire a wake lock with promise
-  // and type:
-  // 6.2.1. If success is false then reject promise with a "NotAllowedError"
-  //        DOMException, and abort these steps.
-  AcquireWakeLock(type, resolver);
-}
-
-void WakeLockController::ReleaseWakeLock(WakeLockType type,
-                                         ScriptPromiseResolver* resolver) {
-  DCHECK_LE(type, WakeLockType::kMaxValue);
-  WakeLockStateRecord* state_record = state_records_[static_cast<size_t>(type)];
-  DCHECK(state_record);
-  state_record->ReleaseWakeLock(resolver);
-}
-
-void WakeLockController::RequestPermission(WakeLockType type,
-                                           ScriptPromiseResolver* resolver) {
-  // https://w3c.github.io/wake-lock/#requestpermission-static-method
-  // 2.1. Let state be the result of running and waiting for the obtain
-  //      permission steps with type.
-  // 2.2. Resolve promise with state.
-  auto permission_callback = WTF::Bind(
-      [](ScriptPromiseResolver* resolver, PermissionStatus status) {
-        DCHECK(status == PermissionStatus::GRANTED ||
-               status == PermissionStatus::DENIED);
-        DCHECK(resolver);
-        resolver->Resolve(PermissionStatusToString(status));
-      },
-      WrapPersistent(resolver));
-  ObtainPermission(type, std::move(permission_callback));
-}
-
-void WakeLockController::ContextDestroyed(ExecutionContext*) {
-  // https://w3c.github.io/wake-lock/#handling-document-loss-of-full-activity
-  // 1. Let document be the responsible document of the current settings object.
-  // 2. Let screenRecord be the platform wake lock's state record associated
-  // with document and wake lock type "screen".
-  // 3. For each lockPromise in screenRecord.[[WakeLockStateRecord]]:
-  // 3.1. Run release a wake lock with lockPromise and "screen".
-  // 4. Let systemRecord be the platform wake lock's state record associated
-  // with document and wake lock type "system".
-  // 5. For each lockPromise in systemRecord.[[WakeLockStateRecord]]:
-  // 5.1. Run release a wake lock with lockPromise and "system".
-  for (WakeLockStateRecord* state_record : state_records_) {
-    if (state_record)
-      state_record->ClearWakeLocks();
-  }
-}
-
-void WakeLockController::PageVisibilityChanged() {
-  // https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
-  // 1. Let document be the Document of the top-level browsing context.
-  // 2. If document's visibility state is "visible", abort these steps.
-  if (GetPage() && GetPage()->IsPageVisible())
-    return;
-  // 3. Let screenRecord be the platform wake lock's state record associated
-  // with wake lock type "screen".
-  // 4. For each lockPromise in screenRecord.[[WakeLockStateRecord]]:
-  // 4.1. Run release a wake lock with lockPromise and "screen".
-  WakeLockStateRecord* state_record =
-      state_records_[static_cast<size_t>(WakeLockType::kScreen)];
-  if (state_record)
-    state_record->ClearWakeLocks();
-}
-
-void WakeLockController::AcquireWakeLock(WakeLockType type,
-                                         ScriptPromiseResolver* resolver) {
-  DCHECK_LE(type, WakeLockType::kMaxValue);
-  WakeLockStateRecord* state_record = state_records_[static_cast<size_t>(type)];
-  DCHECK(state_record);
-  state_record->AcquireWakeLock(resolver);
-}
-
-void WakeLockController::ObtainPermission(
-    WakeLockType type,
-    base::OnceCallback<void(PermissionStatus)> callback) {
-  // https:w3c.github.io/wake-lock/#dfn-obtain-permission
-  // Note we actually implement a simplified version of the "obtain permission"
-  // algorithm that essentially just calls the "request permission to use"
-  // algorithm from the Permissions spec (i.e. we bypass all the steps covering
-  // calling the "query a permission" algorithm and handling its result).
-  // * Right now, we can do that because there is no way for Chromium's
-  //   permission system to get to the "prompt" state given how
-  //   WakeLockPermissionContext is currently implemented.
-  // * Even if WakeLockPermissionContext changes in the future, this Blink
-  //   implementation is unlikely to change because
-  //   WakeLockPermissionContext::RequestPermission() will take its
-  //   |user_gesture| argument into account to actually implement a slightly
-  //   altered version of "request permission to use", the behavior of which
-  //   will match the definition of "obtain permission" in the Wake Lock spec.
-  DCHECK(type == WakeLockType::kScreen || type == WakeLockType::kSystem);
-  static_assert(
-      static_cast<mojom::blink::WakeLockType>(WakeLockType::kScreen) ==
-          mojom::blink::WakeLockType::kScreen,
-      "WakeLockType and mojom::blink::WakeLockType must have identical values");
-  static_assert(
-      static_cast<mojom::blink::WakeLockType>(WakeLockType::kSystem) ==
-          mojom::blink::WakeLockType::kSystem,
-      "WakeLockType and mojom::blink::WakeLockType must have identical values");
-
-  auto* local_frame = GetExecutionContext()->IsDocument()
-                          ? To<Document>(GetExecutionContext())->GetFrame()
-                          : nullptr;
-
-  GetPermissionService()->RequestPermission(
-      CreateWakeLockPermissionDescriptor(
-          static_cast<mojom::blink::WakeLockType>(type)),
-      LocalFrame::HasTransientUserActivation(local_frame), std::move(callback));
-}
-
-PermissionService* WakeLockController::GetPermissionService() {
-  if (!permission_service_) {
-    ConnectToPermissionService(
-        GetExecutionContext(),
-        permission_service_.BindNewPipeAndPassReceiver());
-  }
-  return permission_service_.get();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h b/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h
deleted file mode 100644
index 2cc46bb..0000000
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h
+++ /dev/null
@@ -1,88 +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 THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_CONTROLLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_CONTROLLER_H_
-
-#include "base/callback.h"
-#include "base/gtest_prod_util.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
-#include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-class AbortSignal;
-class ExecutionContext;
-class ScriptPromiseResolver;
-class WakeLockStateRecord;
-
-// WakeLockController is used to track per-Document wake lock state and react to
-// Document changes appropriately.
-class MODULES_EXPORT WakeLockController final
-    : public GarbageCollected<WakeLockController>,
-      public Supplement<ExecutionContext>,
-      public ContextLifecycleObserver,
-      public PageVisibilityObserver {
-  USING_GARBAGE_COLLECTED_MIXIN(WakeLockController);
-
- public:
-  static const char kSupplementName[];
-
-  explicit WakeLockController(Document&);
-  explicit WakeLockController(DedicatedWorkerGlobalScope&);
-
-  static WakeLockController& From(ExecutionContext*);
-
-  void Trace(blink::Visitor*) override;
-
-  void RequestWakeLock(WakeLockType type,
-                       ScriptPromiseResolver* resolver,
-                       AbortSignal* signal);
-
-  void ReleaseWakeLock(WakeLockType type, ScriptPromiseResolver*);
-
-  void RequestPermission(WakeLockType type, ScriptPromiseResolver*);
-
- private:
-  // ContextLifecycleObserver implementation
-  void ContextDestroyed(ExecutionContext*) override;
-
-  // PageVisibilityObserver implementation
-  void PageVisibilityChanged() override;
-
-  void AcquireWakeLock(WakeLockType type, ScriptPromiseResolver*);
-
-  void DidReceivePermissionResponse(WakeLockType type,
-                                    ScriptPromiseResolver*,
-                                    AbortSignal*,
-                                    mojom::blink::PermissionStatus);
-
-  // Permission handling
-  void ObtainPermission(
-      WakeLockType type,
-      base::OnceCallback<void(mojom::blink::PermissionStatus)> callback);
-  mojom::blink::PermissionService* GetPermissionService();
-
-  mojo::Remote<mojom::blink::PermissionService> permission_service_;
-
-  // https://w3c.github.io/wake-lock/#concepts-and-state-record
-  // Each platform wake lock (one per wake lock type) has an associated state
-  // record per responsible document [...] internal slots.
-  Member<WakeLockStateRecord> state_records_[kWakeLockTypeCount];
-
-  FRIEND_TEST_ALL_PREFIXES(WakeLockControllerTest, AcquireScreenWakeLock);
-  FRIEND_TEST_ALL_PREFIXES(WakeLockControllerTest, AcquireSystemWakeLock);
-  FRIEND_TEST_ALL_PREFIXES(WakeLockControllerTest, AcquireMultipleLocks);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_CONTROLLER_H_
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc
deleted file mode 100644
index 1d14f44fe..0000000
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc
+++ /dev/null
@@ -1,488 +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 "third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/abort_signal.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-TEST(WakeLockControllerTest, RequestWakeLockGranted) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
-  auto* screen_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise screen_promise = screen_resolver->Promise();
-
-  controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver, nullptr);
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  MockPermissionService& permission_service = context.GetPermissionService();
-
-  permission_service.WaitForPermissionRequest(WakeLockType::kScreen);
-  screen_lock.WaitForRequest();
-
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(screen_promise));
-  EXPECT_TRUE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, RequestWakeLockDenied) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kSystem, mojom::blink::PermissionStatus::DENIED);
-
-  auto* system_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise system_promise = system_resolver->Promise();
-
-  controller.RequestWakeLock(WakeLockType::kSystem, system_resolver, nullptr);
-
-  MockWakeLock& system_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
-  MockPermissionService& permission_service = context.GetPermissionService();
-
-  permission_service.WaitForPermissionRequest(WakeLockType::kSystem);
-  context.WaitForPromiseRejection(system_promise);
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(system_promise));
-  EXPECT_FALSE(system_lock.is_acquired());
-
-  // System locks are not allowed by default, so the promise should have been
-  // rejected with a NotAllowedError DOMException.
-  DOMException* dom_exception =
-      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(system_promise);
-  ASSERT_NE(dom_exception, nullptr);
-  EXPECT_EQ("NotAllowedError", dom_exception->name());
-}
-
-// Abort early in DidReceivePermissionResponse().
-TEST(WakeLockControllerTest, RequestWakeLockAbortEarly) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  auto* screen_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise screen_promise = screen_resolver->Promise();
-
-  auto* abort_signal = MakeGarbageCollected<AbortSignal>(context.GetDocument());
-  abort_signal->AddAlgorithm(WTF::Bind(
-      &WakeLockController::ReleaseWakeLock, WrapWeakPersistent(&controller),
-      WakeLockType::kScreen, WrapPersistent(screen_resolver)));
-
-  controller.RequestWakeLock(
-      WakeLockType::kScreen,
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()),
-      abort_signal);
-
-  MockPermissionService& permission_service = context.GetPermissionService();
-
-  permission_service.WaitForPermissionRequest(WakeLockType::kScreen);
-  abort_signal->SignalAbort();
-
-  context.WaitForPromiseRejection(screen_promise);
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(screen_promise));
-  EXPECT_FALSE(screen_lock.is_acquired());
-
-  DOMException* dom_exception =
-      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(screen_promise);
-  ASSERT_NE(dom_exception, nullptr);
-  EXPECT_EQ("AbortError", dom_exception->name());
-}
-
-TEST(WakeLockControllerTest, AcquireScreenWakeLock) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  controller.AcquireWakeLock(
-      WakeLockType::kScreen,
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  screen_lock.WaitForRequest();
-
-  EXPECT_TRUE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, AcquireSystemWakeLock) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  controller.AcquireWakeLock(
-      WakeLockType::kSystem,
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
-  MockWakeLock& system_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
-  system_lock.WaitForRequest();
-
-  EXPECT_TRUE(system_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, AcquireMultipleLocks) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  controller.AcquireWakeLock(
-      WakeLockType::kScreen,
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
-  controller.AcquireWakeLock(
-      WakeLockType::kSystem,
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
-  controller.AcquireWakeLock(
-      WakeLockType::kSystem,
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  screen_lock.WaitForRequest();
-  MockWakeLock& system_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
-  system_lock.WaitForRequest();
-
-  EXPECT_TRUE(screen_lock.is_acquired());
-  EXPECT_TRUE(system_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, ReleaseUnaquiredWakeLockRejectsPromise) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-
-  auto* resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise promise = resolver->Promise();
-
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(promise));
-  controller.ReleaseWakeLock(WakeLockType::kScreen, resolver);
-  context.WaitForPromiseRejection(promise);
-
-  // The promise is always rejected, even if it is not in [[ActiveLocks]].
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise));
-  EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, ReleaseWakeLock) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-
-  auto* resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise promise = resolver->Promise();
-
-  controller.RequestWakeLock(WakeLockType::kScreen, resolver,
-                             /*signal=*/nullptr);
-  screen_lock.WaitForRequest();
-  controller.ReleaseWakeLock(WakeLockType::kScreen, resolver);
-  context.WaitForPromiseRejection(promise);
-  screen_lock.WaitForCancelation();
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise));
-  EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-// This is actually part of WakeLock::request(), but it is easier to just test
-// it here.
-TEST(WakeLockControllerTest, AbortSignal) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  auto* screen_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise screen_promise = screen_resolver->Promise();
-
-  auto* abort_signal = MakeGarbageCollected<AbortSignal>(context.GetDocument());
-  abort_signal->AddAlgorithm(WTF::Bind(
-      &WakeLockController::ReleaseWakeLock, WrapWeakPersistent(&controller),
-      WakeLockType::kScreen, WrapPersistent(screen_resolver)));
-
-  controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver,
-                             /*signal=*/nullptr);
-  screen_lock.WaitForRequest();
-
-  abort_signal->SignalAbort();
-  context.WaitForPromiseRejection(screen_promise);
-  screen_lock.WaitForCancelation();
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(screen_promise));
-  EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-// https://w3c.github.io/wake-lock/#handling-document-loss-of-full-activity
-TEST(WakeLockControllerTest, LossOfDocumentActivity) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  MockWakeLock& system_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
-
-  // First, acquire a handful of locks of different types.
-  auto* screen_resolver1 =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  screen_resolver1->Promise();
-  auto* screen_resolver2 =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  screen_resolver2->Promise();
-  auto* system_resolver1 =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  system_resolver1->Promise();
-  controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver1,
-                             /*signal=*/nullptr);
-  controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver2,
-                             /*signal=*/nullptr);
-  screen_lock.WaitForRequest();
-  controller.RequestWakeLock(WakeLockType::kSystem, system_resolver1,
-                             /*signal=*/nullptr);
-  system_lock.WaitForRequest();
-
-  // Now shut down our Document and make sure all [[ActiveLocks]] slots have
-  // been cleared. We cannot check that the promises have been rejected because
-  // ScriptPromiseResolver::Reject() will bail out if we no longer have a valid
-  // execution context.
-  context.GetDocument()->Shutdown();
-  screen_lock.WaitForCancelation();
-  system_lock.WaitForCancelation();
-
-  EXPECT_FALSE(screen_lock.is_acquired());
-  EXPECT_FALSE(system_lock.is_acquired());
-}
-
-// https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
-TEST(WakeLockControllerTest, PageVisibilityHidden) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  auto* screen_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise screen_promise = screen_resolver->Promise();
-
-  MockWakeLock& system_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
-  auto* system_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise system_promise = system_resolver->Promise();
-
-  controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver,
-                             /*signal=*/nullptr);
-  controller.RequestWakeLock(WakeLockType::kSystem, system_resolver,
-                             /*signal=*/nullptr);
-
-  screen_lock.WaitForRequest();
-  system_lock.WaitForRequest();
-
-  context.GetDocument()->GetPage()->SetIsHidden(true, false);
-
-  context.WaitForPromiseRejection(screen_promise);
-  screen_lock.WaitForCancelation();
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(screen_promise));
-  DOMException* dom_exception =
-      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(screen_promise);
-  ASSERT_NE(dom_exception, nullptr);
-  EXPECT_EQ("AbortError", dom_exception->name());
-  EXPECT_FALSE(screen_lock.is_acquired());
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(system_promise));
-  EXPECT_TRUE(system_lock.is_acquired());
-
-  context.GetDocument()->GetPage()->SetIsHidden(false, false);
-
-  auto* other_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise other_promise = system_resolver->Promise();
-  controller.RequestWakeLock(WakeLockType::kScreen, other_resolver,
-                             /*signal=*/nullptr);
-  screen_lock.WaitForRequest();
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(other_promise));
-  EXPECT_TRUE(screen_lock.is_acquired());
-}
-
-// https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
-TEST(WakeLockControllerTest, PageVisibilityHiddenBeforeLockAcquisition) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  auto* screen_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise screen_promise = screen_resolver->Promise();
-
-  MockWakeLock& system_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
-  auto* system_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise system_promise = system_resolver->Promise();
-
-  controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver,
-                             /*signal=*/nullptr);
-  controller.RequestWakeLock(WakeLockType::kSystem, system_resolver,
-                             /*signal=*/nullptr);
-  context.GetDocument()->GetPage()->SetIsHidden(true, false);
-
-  context.WaitForPromiseRejection(screen_promise);
-  system_lock.WaitForRequest();
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(screen_promise));
-  EXPECT_FALSE(screen_lock.is_acquired());
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(system_promise));
-  EXPECT_TRUE(system_lock.is_acquired());
-}
-
-// Check that hiding a page and signaling abort does not try to delete a
-// screen lock twice.
-TEST(WakeLockControllerTest, PageVisibilityAndAbortSignal) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  auto* screen_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise screen_promise = screen_resolver->Promise();
-
-  auto* abort_signal = MakeGarbageCollected<AbortSignal>(context.GetDocument());
-  abort_signal->AddAlgorithm(WTF::Bind(
-      &WakeLockController::ReleaseWakeLock, WrapWeakPersistent(&controller),
-      WakeLockType::kScreen, WrapPersistent(screen_resolver)));
-
-  controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver,
-                             /*signal=*/nullptr);
-  screen_lock.WaitForRequest();
-
-  context.GetDocument()->GetPage()->SetIsHidden(true, false);
-  context.WaitForPromiseRejection(screen_promise);
-  screen_lock.WaitForCancelation();
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(screen_promise));
-  EXPECT_FALSE(screen_lock.is_acquired());
-
-  abort_signal->SignalAbort();
-  test::RunPendingTasks();
-
-  EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, RequestPermissionGranted) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
-
-  auto* system_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise system_promise = system_resolver->Promise();
-
-  controller.RequestPermission(WakeLockType::kSystem, system_resolver);
-  context.WaitForPromiseFulfillment(system_promise);
-
-  EXPECT_EQ(v8::Promise::kFulfilled,
-            ScriptPromiseUtils::GetPromiseState(system_promise));
-  EXPECT_EQ("granted",
-            ScriptPromiseUtils::GetPromiseResolutionAsString(system_promise));
-}
-
-TEST(WakeLockControllerTest, RequestPermissionDenied) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto& controller = WakeLockController::From(context.GetDocument());
-
-  context.GetPermissionService().SetPermissionResponse(
-      WakeLockType::kSystem, mojom::blink::PermissionStatus::DENIED);
-
-  auto* system_resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise system_promise = system_resolver->Promise();
-
-  controller.RequestPermission(WakeLockType::kSystem, system_resolver);
-  context.WaitForPromiseFulfillment(system_promise);
-
-  EXPECT_EQ(v8::Promise::kFulfilled,
-            ScriptPromiseUtils::GetPromiseState(system_promise));
-  EXPECT_EQ("denied",
-            ScriptPromiseUtils::GetPromiseResolutionAsString(system_promise));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_event.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_event.cc
new file mode 100644
index 0000000..866fbaeb
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_event.cc
@@ -0,0 +1,46 @@
+// 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 "third_party/blink/renderer/modules/wake_lock/wake_lock_event.h"
+
+#include "base/logging.h"
+#include "third_party/blink/renderer/modules/event_interface_modules_names.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
+namespace blink {
+
+// static
+WakeLockEvent* WakeLockEvent::Create(const AtomicString& type,
+                                     const WakeLockEventInit* initializer) {
+  DCHECK(initializer->hasLock());
+  return MakeGarbageCollected<WakeLockEvent>(type, initializer);
+}
+
+WakeLockEvent::WakeLockEvent(const AtomicString& type,
+                             const WakeLockEventInit* initializer)
+    : Event(type, initializer), lock_(initializer->lock()) {
+  DCHECK_NE(nullptr, lock_);
+}
+
+WakeLockEvent::WakeLockEvent(const AtomicString& type, WakeLockSentinel* lock)
+    : Event(type, Bubbles::kNo, Cancelable::kNo), lock_(lock) {}
+
+WakeLockEvent::~WakeLockEvent() = default;
+
+WakeLockSentinel* WakeLockEvent::lock() const {
+  return lock_;
+}
+
+const AtomicString& WakeLockEvent::InterfaceName() const {
+  return event_interface_names::kWakeLockEvent;
+}
+
+void WakeLockEvent::Trace(blink::Visitor* visitor) {
+  visitor->Trace(lock_);
+  Event::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_event.h b/third_party/blink/renderer/modules/wake_lock/wake_lock_event.h
new file mode 100644
index 0000000..228a4b13
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_event.h
@@ -0,0 +1,41 @@
+// 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_MODULES_WAKE_LOCK_WAKE_LOCK_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_EVENT_H_
+
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class WakeLockEventInit;
+class WakeLockSentinel;
+
+class WakeLockEvent final : public Event {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static WakeLockEvent* Create(const AtomicString& type,
+                               const WakeLockEventInit* initializer);
+
+  WakeLockEvent(const AtomicString& type, const WakeLockEventInit* initializer);
+  WakeLockEvent(const AtomicString& type, WakeLockSentinel* lock);
+  ~WakeLockEvent() override;
+
+  // Web-exposed APIs.
+  WakeLockSentinel* lock() const;
+
+  // Event overrides.
+  const AtomicString& InterfaceName() const override;
+  void Trace(blink::Visitor* visitor) override;
+
+ private:
+  const Member<WakeLockSentinel> lock_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_EVENT_H_
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_event.idl b/third_party/blink/renderer/modules/wake_lock/wake_lock_event.idl
new file mode 100644
index 0000000..9ad1cfb
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_event.idl
@@ -0,0 +1,12 @@
+// 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.
+
+[
+  SecureContext,
+  Exposed=(DedicatedWorker,Window),
+  Constructor(DOMString type, WakeLockEventInit init),
+  RuntimeEnabled=WakeLock
+] interface WakeLockEvent : Event {
+  readonly attribute WakeLockSentinel lock;
+};
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.idl b/third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.idl
new file mode 100644
index 0000000..40d203e
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.idl
@@ -0,0 +1,7 @@
+// 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.
+
+dictionary WakeLockEventInit : EventInit {
+  required WakeLockSentinel lock;
+};
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_request_options.idl b/third_party/blink/renderer/modules/wake_lock/wake_lock_request_options.idl
deleted file mode 100644
index 074fe3c7..0000000
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_request_options.idl
+++ /dev/null
@@ -1,8 +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.
-
-// https://w3c.github.io/wake-lock/#the-wakelockrequestoptions-dictionary
-dictionary WakeLockRequestOptions {
-  AbortSignal signal;
-};
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.cc
new file mode 100644
index 0000000..9a3ad58ced
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.cc
@@ -0,0 +1,76 @@
+// 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 "third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h"
+
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/event_target_modules_names.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_event.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+WakeLockSentinel::WakeLockSentinel(ScriptState* script_state,
+                                   WakeLockType type,
+                                   WakeLockStateRecord* manager)
+    : ContextLifecycleObserver(ExecutionContext::From(script_state)),
+      manager_(manager),
+      type_(type) {}
+
+WakeLockSentinel::~WakeLockSentinel() = default;
+
+ScriptPromise WakeLockSentinel::release(ScriptState* script_state) {
+  DoRelease();
+  return ScriptPromise::CastUndefined(script_state);
+}
+
+String WakeLockSentinel::type() const {
+  switch (type_) {
+    case WakeLockType::kScreen:
+      return "screen";
+    case WakeLockType::kSystem:
+      return "system";
+  }
+}
+
+ExecutionContext* WakeLockSentinel::GetExecutionContext() const {
+  return ContextLifecycleObserver::GetExecutionContext();
+}
+
+const AtomicString& WakeLockSentinel::InterfaceName() const {
+  return event_target_names::kWakeLockSentinel;
+}
+
+void WakeLockSentinel::Trace(blink::Visitor* visitor) {
+  visitor->Trace(manager_);
+  EventTargetWithInlineData::Trace(visitor);
+  ContextLifecycleObserver::Trace(visitor);
+}
+
+bool WakeLockSentinel::HasPendingActivity() const {
+  return HasEventListeners();
+}
+
+void WakeLockSentinel::ContextDestroyed(ExecutionContext*) {
+  // Release all event listeners so that HasPendingActivity() does not return
+  // true forever once a listener has been added to the object.
+  RemoveAllEventListeners();
+  DCHECK(!HasEventListeners());
+}
+
+void WakeLockSentinel::DoRelease() {
+  if (!manager_)
+    return;
+
+  manager_->UnregisterSentinel(this);
+  manager_.Clear();
+
+  DispatchEvent(
+      *MakeGarbageCollected<WakeLockEvent>(event_type_names::kRelease, this));
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h b/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h
new file mode 100644
index 0000000..30d954a
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h
@@ -0,0 +1,72 @@
+// 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_MODULES_WAKE_LOCK_WAKE_LOCK_SENTINEL_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_SENTINEL_H_
+
+#include "base/gtest_prod_util.h"
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ExecutionContext;
+class ScriptState;
+class WakeLockStateRecord;
+
+class MODULES_EXPORT WakeLockSentinel final
+    : public EventTargetWithInlineData,
+      public ActiveScriptWrappable<WakeLockSentinel>,
+      public ContextLifecycleObserver {
+  DEFINE_WRAPPERTYPEINFO();
+  USING_GARBAGE_COLLECTED_MIXIN(WakeLockSentinel);
+
+ public:
+  WakeLockSentinel(ScriptState* script_state,
+                   WakeLockType type,
+                   WakeLockStateRecord* manager);
+  ~WakeLockSentinel() override;
+
+  // Web-exposed interfaces
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(release, kRelease)
+  ScriptPromise release(ScriptState*);
+  String type() const;
+
+  // EventTarget overrides.
+  ExecutionContext* GetExecutionContext() const override;
+  const AtomicString& InterfaceName() const override;
+  void Trace(blink::Visitor*) override;
+
+  // ActiveScriptWrappable overrides.
+  bool HasPendingActivity() const override;
+
+  // ContextLifecycleObserver overrides.
+  void ContextDestroyed(ExecutionContext*) override;
+
+ private:
+  friend class WakeLockStateRecord;
+
+  // This function, which only has any effect once, detaches this sentinel from
+  // its |manager_|, and fires a "release" event.
+  // It is implemented separately from release() itself so that |manager_| can
+  // call it without triggering the creation of a new ScriptPromise, as it is
+  // not relevant to |manager_| and this function may be called from a context
+  // where |script_state_|'s context is no longer valid.
+  void DoRelease();
+
+  Member<WakeLockStateRecord> manager_;
+  const WakeLockType type_;
+
+  FRIEND_TEST_ALL_PREFIXES(WakeLockSentinelTest, MultipleReleaseCalls);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_SENTINEL_H_
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.idl b/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.idl
new file mode 100644
index 0000000..f747650
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.idl
@@ -0,0 +1,16 @@
+// 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.
+
+[
+  ActiveScriptWrappable,
+  Exposed=(DedicatedWorker,Window),
+  RuntimeEnabled=WakeLock,
+  SecureContext
+] interface WakeLockSentinel : EventTarget {
+  attribute EventHandler onrelease;
+
+  readonly attribute WakeLockType type;
+
+  [CallWith=ScriptState] Promise<void> release();
+};
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel_test.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel_test.cc
new file mode 100644
index 0000000..70cf9dd5
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel_test.cc
@@ -0,0 +1,106 @@
+// 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 "third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h"
+
+#include "base/callback.h"
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
+#include "third_party/blink/renderer/modules/event_target_modules_names.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+namespace {
+
+class SyncEventListener final : public NativeEventListener {
+ public:
+  SyncEventListener(base::OnceClosure invocation_callback)
+      : invocation_callback_(std::move(invocation_callback)) {}
+  void Invoke(ExecutionContext*, Event*) override {
+    DCHECK(invocation_callback_);
+    std::move(invocation_callback_).Run();
+  }
+
+ private:
+  base::OnceClosure invocation_callback_;
+};
+
+}  // namespace
+
+TEST(WakeLockSentinelTest, SentinelType) {
+  MockWakeLockService wake_lock_service;
+  WakeLockTestingContext context(&wake_lock_service);
+
+  auto* sentinel = MakeGarbageCollected<WakeLockSentinel>(
+      context.GetScriptState(), WakeLockType::kScreen, /*manager=*/nullptr);
+  EXPECT_EQ("screen", sentinel->type());
+
+  sentinel = MakeGarbageCollected<WakeLockSentinel>(
+      context.GetScriptState(), WakeLockType::kSystem, /*manager=*/nullptr);
+  EXPECT_EQ("system", sentinel->type());
+}
+
+TEST(WakeLockSentinelTest, MultipleReleaseCalls) {
+  MockWakeLockService wake_lock_service;
+  WakeLockTestingContext context(&wake_lock_service);
+
+  auto* state_record = MakeGarbageCollected<WakeLockStateRecord>(
+      context.GetDocument(), WakeLockType::kScreen);
+  auto* resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  ScriptPromise promise = resolver->Promise();
+  state_record->AcquireWakeLock(resolver);
+  context.WaitForPromiseFulfillment(promise);
+  auto* sentinel =
+      ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise);
+  ASSERT_NE(nullptr, sentinel);
+
+  base::RunLoop run_loop;
+  auto* event_listener =
+      MakeGarbageCollected<SyncEventListener>(run_loop.QuitClosure());
+  sentinel->addEventListener(event_type_names::kRelease, event_listener);
+  sentinel->release(context.GetScriptState());
+  run_loop.Run();
+  sentinel->removeEventListener(event_type_names::kRelease, event_listener);
+
+  EXPECT_EQ(nullptr, sentinel->manager_);
+
+  event_listener = MakeGarbageCollected<SyncEventListener>(WTF::Bind([]() {
+    EXPECT_TRUE(false) << "This event handler should not be reached.";
+  }));
+  sentinel->addEventListener(event_type_names::kRelease, event_listener);
+  sentinel->release(context.GetScriptState());
+}
+
+TEST(WakeLockSentinelTest, ContextDestruction) {
+  MockWakeLockService wake_lock_service;
+  WakeLockTestingContext context(&wake_lock_service);
+
+  auto* sentinel = MakeGarbageCollected<WakeLockSentinel>(
+      context.GetScriptState(), WakeLockType::kScreen,
+      MakeGarbageCollected<WakeLockStateRecord>(context.GetDocument(),
+                                                WakeLockType::kScreen));
+
+  auto* event_listener =
+      MakeGarbageCollected<SyncEventListener>(WTF::Bind([]() {
+        EXPECT_TRUE(false) << "This event handler should not be reached.";
+      }));
+  sentinel->addEventListener(event_type_names::kRelease, event_listener);
+  EXPECT_TRUE(sentinel->HasPendingActivity());
+
+  context.GetDocument()->Shutdown();
+
+  // If the method returns false the object can be GC'ed.
+  EXPECT_FALSE(sentinel->HasPendingActivity());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc
index 13fd3241..c5194fb2de 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc
@@ -10,14 +10,14 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
 WakeLockStateRecord::WakeLockStateRecord(ExecutionContext* execution_context,
                                          WakeLockType type)
-    : wake_lock_type_(ToMojomWakeLockType(type)),
-      execution_context_(execution_context) {
+    : wake_lock_type_(type), execution_context_(execution_context) {
   DCHECK_NE(execution_context, nullptr);
 }
 
@@ -41,54 +41,35 @@
     execution_context_->GetBrowserInterfaceBroker().GetInterface(
         wake_lock_service.BindNewPipeAndPassReceiver());
 
-    wake_lock_service->GetWakeLock(
-        wake_lock_type_, device::mojom::blink::WakeLockReason::kOther,
-        "Blink Wake Lock", wake_lock_.BindNewPipeAndPassReceiver());
+    wake_lock_service->GetWakeLock(ToMojomWakeLockType(wake_lock_type_),
+                                   device::mojom::blink::WakeLockReason::kOther,
+                                   "Blink Wake Lock",
+                                   wake_lock_.BindNewPipeAndPassReceiver());
     wake_lock_.set_disconnect_handler(
         WTF::Bind(&WakeLockStateRecord::OnWakeLockConnectionError,
                   WrapWeakPersistent(this)));
     wake_lock_->RequestWakeLock();
   }
-  DCHECK(!active_locks_.Contains(resolver));
-  active_locks_.insert(resolver);
+  auto* sentinel = MakeGarbageCollected<WakeLockSentinel>(
+      resolver->GetScriptState(), wake_lock_type_, this);
+  wake_lock_sentinels_.insert(sentinel);
+  resolver->Resolve(sentinel);
 }
 
-void WakeLockStateRecord::ReleaseWakeLock(ScriptPromiseResolver* resolver) {
-  // https://w3c.github.io/wake-lock/#release-wake-lock-algorithm
-  // 1. Reject lockPromise with an "AbortError" DOMException.
-  resolver->Reject(MakeGarbageCollected<DOMException>(
-      DOMExceptionCode::kAbortError, "Wake Lock released"));
+void WakeLockStateRecord::UnregisterSentinel(WakeLockSentinel* sentinel) {
+  auto iterator = wake_lock_sentinels_.find(sentinel);
+  DCHECK(iterator != wake_lock_sentinels_.end());
+  wake_lock_sentinels_.erase(iterator);
 
-  // 2. Let document be the responsible document of the current settings object.
-  // 3. Let record be the platform wake lock's state record associated with
-  // document and type.
-  // 4. If record.[[ActiveLocks]] does not contain lockPromise, abort these
-  // steps.
-  auto iterator = active_locks_.find(resolver);
-  if (iterator == active_locks_.end())
-    return;
-
-  // 5. Remove lockPromise from record.[[ActiveLocks]].
-  active_locks_.erase(iterator);
-
-  // 6. If the internal slot [[ActiveLocks]] of all the platform wake lock's
-  // state records are all empty, then run the following steps in parallel:
-  // 6.1. Ask the underlying operation system to release the wake lock of type
-  //      type and let success be true if the operation succeeded, or else
-  //      false.
-  if (active_locks_.IsEmpty() && wake_lock_.is_bound()) {
+  if (wake_lock_sentinels_.IsEmpty() && wake_lock_.is_bound()) {
     wake_lock_->CancelWakeLock();
     wake_lock_.reset();
-
-    // 6.2. If success is true and type is "screen" run the following:
-    // 6.2.1. Reset the platform-specific inactivity timer after which the
-    //        screen is actually turned off.
   }
 }
 
 void WakeLockStateRecord::ClearWakeLocks() {
-  while (!active_locks_.IsEmpty())
-    ReleaseWakeLock(*active_locks_.begin());
+  while (!wake_lock_sentinels_.IsEmpty())
+    (*wake_lock_sentinels_.begin())->DoRelease();
 }
 
 void WakeLockStateRecord::OnWakeLockConnectionError() {
@@ -98,7 +79,7 @@
 
 void WakeLockStateRecord::Trace(blink::Visitor* visitor) {
   visitor->Trace(execution_context_);
-  visitor->Trace(active_locks_);
+  visitor->Trace(wake_lock_sentinels_);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h
index 9873b0c..86f624c 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h
@@ -16,6 +16,7 @@
 
 class ExecutionContext;
 class ScriptPromiseResolver;
+class WakeLockSentinel;
 
 // https://w3c.github.io/wake-lock/#concepts-and-state-record
 // Per-document and per-wake lock type internal data.
@@ -25,36 +26,31 @@
   WakeLockStateRecord(ExecutionContext*, WakeLockType);
 
   void AcquireWakeLock(ScriptPromiseResolver*);
-  void ReleaseWakeLock(ScriptPromiseResolver*);
   void ClearWakeLocks();
 
+  void UnregisterSentinel(WakeLockSentinel*);
+
   void Trace(blink::Visitor* visitor);
 
  private:
-  using ActiveLocksType = HeapHashSet<Member<ScriptPromiseResolver>>;
-
-  friend class WakeLockControllerTest;
-
   // Handle connection errors from |wake_lock_|.
   void OnWakeLockConnectionError();
 
-  // A list of Promises representing active wake locks associated with the
-  // responsible document.
-  ActiveLocksType active_locks_;
+  // A set with all WakeLockSentinel instances belonging to this
+  // Navigator/WorkerNavigator.
+  HeapHashSet<Member<WakeLockSentinel>> wake_lock_sentinels_;
 
   // An actual platform WakeLock. If bound, it means there is an active wake
   // lock for a given type.
   mojo::Remote<device::mojom::blink::WakeLock> wake_lock_;
-  device::mojom::blink::WakeLockType wake_lock_type_;
+  WakeLockType wake_lock_type_;
 
   // ExecutionContext from which we will connect to |wake_lock_service_|.
   Member<ExecutionContext> execution_context_;
 
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, AcquireWakeLock);
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseAllWakeLocks);
-  FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseNonExistentWakeLock);
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseOneWakeLock);
-  FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseRejectsPromise);
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ClearWakeLocks);
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, WakeLockConnectionError);
 };
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc
index 3fea7bc..ed2828c 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc
@@ -33,6 +33,7 @@
   MockWakeLock& screen_lock =
       wake_lock_service.get_wake_lock(WakeLockType::kScreen);
   EXPECT_FALSE(screen_lock.is_acquired());
+  EXPECT_FALSE(state_record->wake_lock_.is_bound());
 
   auto* resolver1 =
       MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
@@ -45,12 +46,19 @@
   state_record->AcquireWakeLock(resolver2);
   screen_lock.WaitForRequest();
 
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(promise1));
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(promise2));
+  context.WaitForPromiseFulfillment(promise1);
+  context.WaitForPromiseFulfillment(promise2);
+
+  auto* sentinel1 =
+      ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise1);
+  auto* sentinel2 =
+      ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise2);
+
+  EXPECT_TRUE(state_record->wake_lock_sentinels_.Contains(sentinel1));
+  EXPECT_TRUE(state_record->wake_lock_sentinels_.Contains(sentinel2));
+  EXPECT_EQ(2U, state_record->wake_lock_sentinels_.size());
   EXPECT_TRUE(screen_lock.is_acquired());
-  EXPECT_EQ(2U, state_record->active_locks_.size());
+  EXPECT_TRUE(state_record->wake_lock_.is_bound());
 }
 
 TEST(WakeLockStateRecordTest, ReleaseAllWakeLocks) {
@@ -67,61 +75,20 @@
 
   state_record->AcquireWakeLock(resolver);
   screen_lock.WaitForRequest();
+  context.WaitForPromiseFulfillment(promise);
 
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(promise));
-  EXPECT_EQ(1U, state_record->active_locks_.size());
+  EXPECT_EQ(1U, state_record->wake_lock_sentinels_.size());
   EXPECT_TRUE(screen_lock.is_acquired());
 
-  state_record->ReleaseWakeLock(resolver);
-  context.WaitForPromiseRejection(promise);
+  auto* sentinel =
+      ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise);
+
+  state_record->UnregisterSentinel(sentinel);
   screen_lock.WaitForCancelation();
 
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise));
-  DOMException* dom_exception =
-      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise);
-  ASSERT_NE(nullptr, dom_exception);
-  EXPECT_EQ("AbortError", dom_exception->name());
-
-  EXPECT_EQ(0U, state_record->active_locks_.size());
+  EXPECT_EQ(0U, state_record->wake_lock_sentinels_.size());
   EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-// Test that trying to remove an entry that does not exist is a no-op. This can
-// happen, for example, when a page visibility change releases a screen lock
-// and a call to AbortController.abort() causes an attempt to release the same
-// lock again.
-TEST(WakeLockStateRecordTest, ReleaseNonExistentWakeLock) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto* state_record = MakeStateRecord(context, WakeLockType::kScreen);
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-
-  auto* resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise promise = resolver->Promise();
-
-  state_record->AcquireWakeLock(resolver);
-  screen_lock.WaitForRequest();
-  state_record->ReleaseWakeLock(resolver);
-  context.WaitForPromiseRejection(promise);
-  screen_lock.WaitForCancelation();
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise));
-  EXPECT_EQ(0U, state_record->active_locks_.size());
-  EXPECT_FALSE(screen_lock.is_acquired());
-
-  state_record->ReleaseWakeLock(resolver);
-  test::RunPendingTasks();
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise));
-  EXPECT_EQ(0U, state_record->active_locks_.size());
-  EXPECT_FALSE(screen_lock.is_acquired());
+  EXPECT_FALSE(state_record->wake_lock_.is_bound());
 }
 
 TEST(WakeLockStateRecordTest, ReleaseOneWakeLock) {
@@ -143,54 +110,24 @@
   state_record->AcquireWakeLock(resolver2);
   screen_lock.WaitForRequest();
 
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(promise1));
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(promise2));
-  EXPECT_EQ(2U, state_record->active_locks_.size());
+  context.WaitForPromiseFulfillment(promise1);
+  context.WaitForPromiseFulfillment(promise2);
+
   EXPECT_TRUE(screen_lock.is_acquired());
+  EXPECT_EQ(2U, state_record->wake_lock_sentinels_.size());
 
-  state_record->ReleaseWakeLock(resolver1);
-  context.WaitForPromiseRejection(promise1);
+  auto* sentinel1 =
+      ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise1);
+  EXPECT_TRUE(state_record->wake_lock_sentinels_.Contains(sentinel1));
 
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise1));
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(promise2));
-  DOMException* dom_exception =
-      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise1);
-  ASSERT_NE(nullptr, dom_exception);
-  EXPECT_EQ("AbortError", dom_exception->name());
-
-  EXPECT_EQ(1U, state_record->active_locks_.size());
+  state_record->UnregisterSentinel(sentinel1);
+  EXPECT_FALSE(state_record->wake_lock_sentinels_.Contains(sentinel1));
+  EXPECT_TRUE(state_record->wake_lock_.is_bound());
+  EXPECT_EQ(1U, state_record->wake_lock_sentinels_.size());
   EXPECT_TRUE(screen_lock.is_acquired());
 }
 
-TEST(WakeLockStateRecordTest, ReleaseRejectsPromise) {
-  MockWakeLockService wake_lock_service;
-  WakeLockTestingContext context(&wake_lock_service);
-  auto* state_record = MakeStateRecord(context, WakeLockType::kScreen);
-
-  MockWakeLock& screen_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-
-  auto* resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
-  ScriptPromise promise = resolver->Promise();
-
-  EXPECT_EQ(v8::Promise::kPending,
-            ScriptPromiseUtils::GetPromiseState(promise));
-
-  state_record->ReleaseWakeLock(resolver);
-  context.WaitForPromiseRejection(promise);
-
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise));
-  EXPECT_EQ(0U, state_record->active_locks_.size());
-  EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockStateRecordTest, ClearEmptyActiveLocksList) {
+TEST(WakeLockStateRecordTest, ClearEmptyWakeLockSentinelList) {
   MockWakeLockService wake_lock_service;
   WakeLockTestingContext context(&wake_lock_service);
   auto* state_record = MakeStateRecord(context, WakeLockType::kSystem);
@@ -223,26 +160,15 @@
   state_record->AcquireWakeLock(resolver1);
   state_record->AcquireWakeLock(resolver2);
   system_lock.WaitForRequest();
+  context.WaitForPromiseFulfillment(promise1);
+  context.WaitForPromiseFulfillment(promise2);
+
+  EXPECT_EQ(2U, state_record->wake_lock_sentinels_.size());
 
   state_record->ClearWakeLocks();
-  context.WaitForPromiseRejection(promise1);
-  context.WaitForPromiseRejection(promise2);
   system_lock.WaitForCancelation();
 
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise1));
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise2));
-  DOMException* dom_exception =
-      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise1);
-  ASSERT_NE(nullptr, dom_exception);
-  EXPECT_EQ("AbortError", dom_exception->name());
-  dom_exception =
-      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise2);
-  ASSERT_NE(nullptr, dom_exception);
-  EXPECT_EQ("AbortError", dom_exception->name());
-
-  EXPECT_EQ(0U, state_record->active_locks_.size());
+  EXPECT_EQ(0U, state_record->wake_lock_sentinels_.size());
   EXPECT_FALSE(system_lock.is_acquired());
 }
 
@@ -264,25 +190,17 @@
   state_record->AcquireWakeLock(resolver1);
   state_record->AcquireWakeLock(resolver2);
   system_lock.WaitForRequest();
+  context.WaitForPromiseFulfillment(promise1);
+  context.WaitForPromiseFulfillment(promise2);
 
+  EXPECT_EQ(2U, state_record->wake_lock_sentinels_.size());
+
+  // Unbind and wait for the disconnection to reach |wake_lock_|'s
+  // disconnection handler.
   system_lock.Unbind();
-  context.WaitForPromiseRejection(promise1);
-  context.WaitForPromiseRejection(promise2);
+  state_record->wake_lock_.FlushForTesting();
 
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise1));
-  EXPECT_EQ(v8::Promise::kRejected,
-            ScriptPromiseUtils::GetPromiseState(promise2));
-  DOMException* dom_exception =
-      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise1);
-  ASSERT_NE(nullptr, dom_exception);
-  EXPECT_EQ("AbortError", dom_exception->name());
-  dom_exception =
-      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise2);
-  ASSERT_NE(nullptr, dom_exception);
-  EXPECT_EQ("AbortError", dom_exception->name());
-
-  EXPECT_EQ(0U, state_record->active_locks_.size());
+  EXPECT_EQ(0U, state_record->wake_lock_sentinels_.size());
   EXPECT_FALSE(state_record->wake_lock_);
   EXPECT_FALSE(system_lock.is_acquired());
 }
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_test.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_test.cc
new file mode 100644
index 0000000..049f2e9
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_test.cc
@@ -0,0 +1,212 @@
+// 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 "third_party/blink/renderer/modules/wake_lock/wake_lock.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+TEST(WakeLockTest, RequestWakeLockGranted) {
+  MockWakeLockService wake_lock_service;
+  WakeLockTestingContext context(&wake_lock_service);
+
+  context.GetPermissionService().SetPermissionResponse(
+      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
+
+  auto* screen_resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  ScriptPromise screen_promise = screen_resolver->Promise();
+
+  auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+  wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver);
+
+  MockWakeLock& screen_lock =
+      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
+  MockPermissionService& permission_service = context.GetPermissionService();
+
+  permission_service.WaitForPermissionRequest(WakeLockType::kScreen);
+  screen_lock.WaitForRequest();
+  context.WaitForPromiseFulfillment(screen_promise);
+
+  EXPECT_NE(nullptr, ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(
+                         screen_promise));
+  EXPECT_TRUE(screen_lock.is_acquired());
+}
+
+TEST(WakeLockTest, RequestWakeLockDenied) {
+  MockWakeLockService wake_lock_service;
+  WakeLockTestingContext context(&wake_lock_service);
+
+  context.GetPermissionService().SetPermissionResponse(
+      WakeLockType::kSystem, mojom::blink::PermissionStatus::DENIED);
+
+  auto* system_resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  ScriptPromise system_promise = system_resolver->Promise();
+
+  auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+  wake_lock->DoRequest(WakeLockType::kSystem, system_resolver);
+
+  MockWakeLock& system_lock =
+      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
+  MockPermissionService& permission_service = context.GetPermissionService();
+
+  permission_service.WaitForPermissionRequest(WakeLockType::kSystem);
+  context.WaitForPromiseRejection(system_promise);
+
+  EXPECT_EQ(v8::Promise::kRejected,
+            ScriptPromiseUtils::GetPromiseState(system_promise));
+  EXPECT_FALSE(system_lock.is_acquired());
+
+  // System locks are not allowed by default, so the promise should have been
+  // rejected with a NotAllowedError DOMException.
+  DOMException* dom_exception =
+      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(system_promise);
+  ASSERT_NE(dom_exception, nullptr);
+  EXPECT_EQ("NotAllowedError", dom_exception->name());
+}
+
+// https://w3c.github.io/wake-lock/#handling-document-loss-of-full-activity
+TEST(WakeLockTest, LossOfDocumentActivity) {
+  MockWakeLockService wake_lock_service;
+  WakeLockTestingContext context(&wake_lock_service);
+
+  MockWakeLock& screen_lock =
+      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
+  MockWakeLock& system_lock =
+      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
+  context.GetPermissionService().SetPermissionResponse(
+      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
+  context.GetPermissionService().SetPermissionResponse(
+      WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
+
+  // First, acquire a handful of locks of different types.
+  auto* screen_resolver1 =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  screen_resolver1->Promise();
+  auto* screen_resolver2 =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  screen_resolver2->Promise();
+  auto* system_resolver1 =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  system_resolver1->Promise();
+
+  auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+  wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver1);
+  wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver2);
+  screen_lock.WaitForRequest();
+  wake_lock->DoRequest(WakeLockType::kSystem, system_resolver1);
+  system_lock.WaitForRequest();
+
+  // Now shut down our Document and make sure all [[ActiveLocks]] slots have
+  // been cleared. We cannot check that the promises have been rejected because
+  // ScriptPromiseResolver::Reject() will bail out if we no longer have a valid
+  // execution context.
+  context.GetDocument()->Shutdown();
+  screen_lock.WaitForCancelation();
+  system_lock.WaitForCancelation();
+
+  EXPECT_FALSE(screen_lock.is_acquired());
+  EXPECT_FALSE(system_lock.is_acquired());
+}
+
+// https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
+TEST(WakeLockTest, PageVisibilityHidden) {
+  MockWakeLockService wake_lock_service;
+  WakeLockTestingContext context(&wake_lock_service);
+
+  context.GetPermissionService().SetPermissionResponse(
+      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
+  context.GetPermissionService().SetPermissionResponse(
+      WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
+
+  MockWakeLock& screen_lock =
+      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
+  auto* screen_resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  ScriptPromise screen_promise = screen_resolver->Promise();
+
+  MockWakeLock& system_lock =
+      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
+  auto* system_resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  ScriptPromise system_promise = system_resolver->Promise();
+
+  auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+  wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver);
+  screen_lock.WaitForRequest();
+  wake_lock->DoRequest(WakeLockType::kSystem, system_resolver);
+  system_lock.WaitForRequest();
+
+  context.WaitForPromiseFulfillment(screen_promise);
+  context.WaitForPromiseFulfillment(system_promise);
+
+  context.GetDocument()->GetPage()->SetIsHidden(true, false);
+
+  screen_lock.WaitForCancelation();
+
+  EXPECT_FALSE(screen_lock.is_acquired());
+  EXPECT_TRUE(system_lock.is_acquired());
+
+  context.GetDocument()->GetPage()->SetIsHidden(false, false);
+
+  auto* other_resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  ScriptPromise other_promise = other_resolver->Promise();
+  wake_lock->DoRequest(WakeLockType::kScreen, other_resolver);
+  screen_lock.WaitForRequest();
+  context.WaitForPromiseFulfillment(other_promise);
+  EXPECT_TRUE(screen_lock.is_acquired());
+}
+
+// https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
+TEST(WakeLockTest, PageVisibilityHiddenBeforeLockAcquisition) {
+  MockWakeLockService wake_lock_service;
+  WakeLockTestingContext context(&wake_lock_service);
+
+  context.GetPermissionService().SetPermissionResponse(
+      WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
+  context.GetPermissionService().SetPermissionResponse(
+      WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
+
+  MockWakeLock& screen_lock =
+      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
+  auto* screen_resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  ScriptPromise screen_promise = screen_resolver->Promise();
+
+  MockWakeLock& system_lock =
+      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
+  auto* system_resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  ScriptPromise system_promise = system_resolver->Promise();
+
+  auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+  wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver);
+  wake_lock->DoRequest(WakeLockType::kSystem, system_resolver);
+  context.GetDocument()->GetPage()->SetIsHidden(true, false);
+
+  context.WaitForPromiseRejection(screen_promise);
+  system_lock.WaitForRequest();
+  context.WaitForPromiseFulfillment(system_promise);
+
+  EXPECT_EQ(v8::Promise::kRejected,
+            ScriptPromiseUtils::GetPromiseState(screen_promise));
+  DOMException* dom_exception =
+      ScriptPromiseUtils::GetPromiseResolutionAsDOMException(screen_promise);
+  ASSERT_NE(dom_exception, nullptr);
+  EXPECT_EQ("NotAllowedError", dom_exception->name());
+
+  EXPECT_FALSE(screen_lock.is_acquired());
+  EXPECT_TRUE(system_lock.is_acquired());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc
index ccb0301a..80416984 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_function.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_sentinel.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
 #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
@@ -317,25 +318,17 @@
 }
 
 // static
-String ScriptPromiseUtils::GetPromiseResolutionAsString(
-    const ScriptPromise& promise) {
-  auto v8_promise = promise.V8Value().As<v8::Promise>();
-  if (v8_promise->State() == v8::Promise::kPending) {
-    return g_empty_string;
-  }
-  ScriptValue promise_result(promise.GetIsolate(), v8_promise->Result());
-  String value;
-  if (!promise_result.ToString(value)) {
-    return g_empty_string;
-  }
-  return value;
-}
-
-// static
 DOMException* ScriptPromiseUtils::GetPromiseResolutionAsDOMException(
     const ScriptPromise& promise) {
   return V8DOMException::ToImplWithTypeCheck(
       promise.GetIsolate(), promise.V8Value().As<v8::Promise>()->Result());
 }
 
+// static
+WakeLockSentinel* ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(
+    const ScriptPromise& promise) {
+  return V8WakeLockSentinel::ToImplWithTypeCheck(
+      promise.GetIsolate(), promise.V8Value().As<v8::Promise>()->Result());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h b/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h
index 136613a..3228e9c 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h
@@ -22,7 +22,9 @@
 
 namespace blink {
 
+class DOMException;
 class Document;
+class WakeLockSentinel;
 
 // Mock WakeLock implementation that tracks whether it's bound or acquired, and
 // provides a few helper methods to synchronously wait for RequestWakeLock()
@@ -175,15 +177,16 @@
   static v8::Promise::PromiseState GetPromiseState(
       const ScriptPromise& promise);
 
-  // Shorthand for getting a String out of a ScriptPromise. This assumes the
-  // promise has been resolved with a string. If anything wrong happens during
-  // the conversion, an empty string is returned.
-  static String GetPromiseResolutionAsString(const ScriptPromise&);
-
   // Shorthand for getting a DOMException* out of a ScriptPromise. This assumes
   // the promise has been resolved with a DOMException. If the conversion fails,
   // nullptr is returned.
   static DOMException* GetPromiseResolutionAsDOMException(const ScriptPromise&);
+
+  // Shorthand for getting a WakeLockSentinel* out of a ScriptPromise. This
+  // assumes the promise has been resolved with a WakeLockSentinel. If the
+  // conversion fails, nullptr is returned.
+  static WakeLockSentinel* GetPromiseResolutionAsWakeLockSentinel(
+      const ScriptPromise&);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.cc b/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.cc
new file mode 100644
index 0000000..094a3ba
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.cc
@@ -0,0 +1,57 @@
+// 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 "third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.h"
+
+#include "third_party/blink/renderer/core/workers/worker_navigator.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock.h"
+
+namespace blink {
+
+WorkerNavigatorWakeLock::WorkerNavigatorWakeLock(WorkerNavigator& navigator)
+    : Supplement<WorkerNavigator>(navigator) {}
+
+// static
+const char WorkerNavigatorWakeLock::kSupplementName[] =
+    "WorkerNavigatorWakeLock";
+
+// static
+WorkerNavigatorWakeLock& WorkerNavigatorWakeLock::From(
+    WorkerNavigator& navigator) {
+  WorkerNavigatorWakeLock* supplement =
+      Supplement<WorkerNavigator>::From<WorkerNavigatorWakeLock>(navigator);
+  if (!supplement) {
+    supplement = MakeGarbageCollected<WorkerNavigatorWakeLock>(navigator);
+    ProvideTo(navigator, supplement);
+  }
+  return *supplement;
+}
+
+// static
+WakeLock* WorkerNavigatorWakeLock::wakeLock(ScriptState* script_state,
+                                            WorkerNavigator& navigator) {
+  return WorkerNavigatorWakeLock::From(navigator).GetWakeLock(script_state);
+}
+
+WakeLock* WorkerNavigatorWakeLock::GetWakeLock(ScriptState* script_state) {
+  if (!wake_lock_) {
+    auto* execution_context = ExecutionContext::From(script_state);
+    DCHECK(execution_context);
+
+    // TODO(https://crbug.com/839117): Remove this check once the Exposed
+    // attribute is fixed to only expose this property in dedicated workers.
+    if (execution_context->IsDedicatedWorkerGlobalScope()) {
+      wake_lock_ = MakeGarbageCollected<WakeLock>(
+          *To<DedicatedWorkerGlobalScope>(execution_context));
+    }
+  }
+  return wake_lock_;
+}
+
+void WorkerNavigatorWakeLock::Trace(blink::Visitor* visitor) {
+  visitor->Trace(wake_lock_);
+  Supplement<WorkerNavigator>::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.h b/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.h
new file mode 100644
index 0000000..bc01e30
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.h
@@ -0,0 +1,41 @@
+// 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_MODULES_WAKE_LOCK_WORKER_NAVIGATOR_WAKE_LOCK_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WORKER_NAVIGATOR_WAKE_LOCK_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class ScriptState;
+class WakeLock;
+class WorkerNavigator;
+
+class WorkerNavigatorWakeLock final
+    : public GarbageCollected<WorkerNavigatorWakeLock>,
+      public Supplement<WorkerNavigator> {
+  USING_GARBAGE_COLLECTED_MIXIN(WorkerNavigatorWakeLock);
+
+ public:
+  static const char kSupplementName[];
+
+  static WorkerNavigatorWakeLock& From(WorkerNavigator&);
+
+  static WakeLock* wakeLock(ScriptState*, WorkerNavigator&);
+
+  explicit WorkerNavigatorWakeLock(WorkerNavigator&);
+
+  void Trace(blink::Visitor*) override;
+
+ private:
+  WakeLock* GetWakeLock(ScriptState*);
+
+  Member<WakeLock> wake_lock_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WORKER_NAVIGATOR_WAKE_LOCK_H_
diff --git a/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.idl b/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.idl
new file mode 100644
index 0000000..ddcc2c2
--- /dev/null
+++ b/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.idl
@@ -0,0 +1,11 @@
+// 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.
+
+[
+  ImplementedAs=WorkerNavigatorWakeLock,
+  RuntimeEnabled=WakeLock,
+  SecureContext
+] partial interface WorkerNavigator {
+  [CallWith=ScriptState, SameObject] readonly attribute WakeLock wakeLock;
+};
diff --git a/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc b/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
index d0c04723..ef3b966 100644
--- a/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
+++ b/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc
@@ -83,52 +83,74 @@
   DCHECK(destination);
 
   float sample_rate = this->SampleRate();
-  double delay_time = 0;
-  float* delay_times = delay_times_.Data();
   double max_time = MaxDelayTime();
 
-  bool sample_accurate = HasSampleAccurateValues();
-
-  if (sample_accurate) {
+  if (HasSampleAccurateValues()) {
+    float* delay_times = delay_times_.Data();
     CalculateSampleAccurateValues(delay_times, frames_to_process);
-  } else {
-    delay_time = this->DelayTime(sample_rate);
 
-    // Make sure the delay time is in a valid range.
-    delay_time = clampTo(delay_time, 0.0, max_time);
-  }
-
-  for (unsigned i = 0; i < frames_to_process; ++i) {
-    if (sample_accurate) {
-      delay_time = delay_times[i];
+    for (unsigned i = 0; i < frames_to_process; ++i) {
+      double delay_time = delay_times[i];
       if (std::isnan(delay_time))
         delay_time = max_time;
       else
         delay_time = clampTo(delay_time, 0.0, max_time);
+
+      double desired_delay_frames = delay_time * sample_rate;
+
+      double read_position =
+          write_index_ + buffer_length - desired_delay_frames;
+      if (read_position >= buffer_length)
+        read_position -= buffer_length;
+
+      // Linearly interpolate in-between delay times.
+      int read_index1 = static_cast<int>(read_position);
+      int read_index2 = (read_index1 + 1) % buffer_length;
+      double interpolation_factor = read_position - read_index1;
+
+      double input = static_cast<float>(*source++);
+      buffer[write_index_] = static_cast<float>(input);
+      write_index_ = (write_index_ + 1) % buffer_length;
+
+      double sample1 = buffer[read_index1];
+      double sample2 = buffer[read_index2];
+
+      double output = (1.0 - interpolation_factor) * sample1 +
+                      interpolation_factor * sample2;
+
+      *destination++ = static_cast<float>(output);
     }
+  } else {
+    double delay_time = this->DelayTime(sample_rate);
 
-    double desired_delay_frames = delay_time * sample_rate;
+    // Make sure the delay time is in a valid range.
+    delay_time = clampTo(delay_time, 0.0, max_time);
 
-    double read_position = write_index_ + buffer_length - desired_delay_frames;
-    if (read_position >= buffer_length)
-      read_position -= buffer_length;
+    for (unsigned i = 0; i < frames_to_process; ++i) {
+      double desired_delay_frames = delay_time * sample_rate;
 
-    // Linearly interpolate in-between delay times.
-    int read_index1 = static_cast<int>(read_position);
-    int read_index2 = (read_index1 + 1) % buffer_length;
-    double interpolation_factor = read_position - read_index1;
+      double read_position =
+          write_index_ + buffer_length - desired_delay_frames;
+      if (read_position >= buffer_length)
+        read_position -= buffer_length;
 
-    double input = static_cast<float>(*source++);
-    buffer[write_index_] = static_cast<float>(input);
-    write_index_ = (write_index_ + 1) % buffer_length;
+      // Linearly interpolate in-between delay times.
+      int read_index1 = static_cast<int>(read_position);
+      int read_index2 = (read_index1 + 1) % buffer_length;
+      double interpolation_factor = read_position - read_index1;
 
-    double sample1 = buffer[read_index1];
-    double sample2 = buffer[read_index2];
+      double input = static_cast<float>(*source++);
+      buffer[write_index_] = static_cast<float>(input);
+      write_index_ = (write_index_ + 1) % buffer_length;
 
-    double output =
-        (1.0 - interpolation_factor) * sample1 + interpolation_factor * sample2;
+      double sample1 = buffer[read_index1];
+      double sample2 = buffer[read_index2];
 
-    *destination++ = static_cast<float>(output);
+      double output = (1.0 - interpolation_factor) * sample1 +
+                      interpolation_factor * sample2;
+
+      *destination++ = static_cast<float>(output);
+    }
   }
 }
 
diff --git a/third_party/blink/renderer/platform/heap/persistent_node.h b/third_party/blink/renderer/platform/heap/persistent_node.h
index 70bc04a8..bc76a01 100644
--- a/third_party/blink/renderer/platform/heap/persistent_node.h
+++ b/third_party/blink/renderer/platform/heap/persistent_node.h
@@ -293,6 +293,14 @@
 
 inline void CrossThreadPersistentRegion::FreeNode(PersistentNode* node) {
   PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired();
+  // PersistentBase::UninitializeSafe opportunistically checks for uninitialized
+  // nodes to allow a fast path destruction of unused nodes. This check is
+  // performed without taking the lock that is required for processing a
+  // cross-thread node. After taking the lock the condition needs to checked
+  // again to avoid double-freeing a node because the node may have been
+  // concurrently freed by the garbage collector on another thread.
+  if (!node)
+    return;
   PersistentRegionBase::FreeNode(node);
 }
 
diff --git a/third_party/blink/renderer/platform/heap/unified_heap_controller.cc b/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
index 649b6f3..9df99b39 100644
--- a/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
+++ b/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
@@ -177,6 +177,10 @@
       class_id != WrapperTypeInfo::kObjectClassId)
     return;
 
+  // Clearing the wrapper below adjusts the DOM wrapper store which may
+  // re-allocate its backing. We have to avoid report memory to V8 as that may
+  // trigger GC during GC.
+  ThreadState::GCForbiddenScope gc_forbidden(thread_state());
   const v8::TracedReference<v8::Object>& traced = handle.As<v8::Object>();
   bool success = DOMWrapperWorld::UnsetSpecificWrapperIfSet(
       ToScriptWrappable(traced), traced);
diff --git a/third_party/blink/renderer/platform/image-decoders/image_frame.cc b/third_party/blink/renderer/platform/image-decoders/image_frame.cc
index 99b5cd1..600c03c 100644
--- a/third_party/blink/renderer/platform/image-decoders/image_frame.cc
+++ b/third_party/blink/renderer/platform/image-decoders/image_frame.cc
@@ -122,6 +122,10 @@
                                    sk_sp<SkColorSpace> color_space) {
   // AllocatePixelData() should only be called once.
   DCHECK(!Width() && !Height());
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+  if (new_width > 1000 || new_height > 1000)
+    return false;
+#endif
 
   SkImageInfo info = SkImageInfo::MakeN32(
       new_width, new_height,
diff --git a/third_party/blink/renderer/platform/peerconnection/OWNERS b/third_party/blink/renderer/platform/peerconnection/OWNERS
index b3a7338c..b30d5fd 100644
--- a/third_party/blink/renderer/platform/peerconnection/OWNERS
+++ b/third_party/blink/renderer/platform/peerconnection/OWNERS
@@ -1,3 +1,5 @@
 file://third_party/blink/renderer/modules/peerconnection/OWNERS
 
+per-file rtc_video_*=file://media/gpu/OWNERS
+
 # COMPONENT: Blink>WebRTC
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
index 32eb85ff..73f15e94 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
@@ -36,7 +36,7 @@
 from blinkpy.common.memoized import memoized
 from blinkpy.common.net.buildbot import Build
 from blinkpy.tool.commands.command import Command
-from blinkpy.web_tests.controllers.test_result_writer import TestResultWriter
+from blinkpy.web_tests.models import test_failures
 from blinkpy.web_tests.models.test_expectations import TestExpectations
 from blinkpy.web_tests.port import base, factory
 
@@ -101,12 +101,12 @@
     def _file_name_for_actual_result(self, test_name, suffix):
         # output_filename takes extensions starting with '.'.
         return self._host_port.output_filename(
-            test_name, TestResultWriter.FILENAME_SUFFIX_ACTUAL, '.' + suffix)
+            test_name, test_failures.FILENAME_SUFFIX_ACTUAL, '.' + suffix)
 
     def _file_name_for_expected_result(self, test_name, suffix):
         # output_filename takes extensions starting with '.'.
         return self._host_port.output_filename(
-            test_name, TestResultWriter.FILENAME_SUFFIX_EXPECTED, '.' + suffix)
+            test_name, test_failures.FILENAME_SUFFIX_EXPECTED, '.' + suffix)
 
 
 class ChangeSet(object):
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py b/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
index ff9d78c1..0a840ca6 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
@@ -47,7 +47,6 @@
 from blinkpy.common.net.file_uploader import FileUploader
 from blinkpy.common.path_finder import PathFinder
 from blinkpy.tool import grammar
-from blinkpy.web_tests.controllers.test_result_writer import TestResultWriter
 from blinkpy.web_tests.controllers.web_test_finder import WebTestFinder
 from blinkpy.web_tests.controllers.web_test_runner import WebTestRunner
 from blinkpy.web_tests.layout_package import json_results_generator
@@ -288,10 +287,11 @@
 
         return tests_to_run, tests_to_skip
 
-    def _test_input_for_file(self, test_file):
+    def _test_input_for_file(self, test_file, retry_attempt):
         return TestInput(test_file,
                          self._options.slow_time_out_ms if self._test_is_slow(test_file) else self._options.time_out_ms,
-                         self._test_requires_lock(test_file))
+                         self._test_requires_lock(test_file),
+                         retry_attempt=retry_attempt)
 
     def _test_requires_lock(self, test_file):
         """Returns True if the test needs to be locked when running multiple
@@ -382,7 +382,8 @@
         for _ in xrange(iterations):
             for test in tests_to_run:
                 for _ in xrange(repeat_each):
-                    test_inputs.append(self._test_input_for_file(test))
+                    test_inputs.append(
+                        self._test_input_for_file(test, retry_attempt))
         return self._runner.run_tests(self._expectations, test_inputs,
                                       tests_to_skip, num_workers, retry_attempt)
 
@@ -436,28 +437,50 @@
                 logs after that time.
         """
         crashed_processes = []
+        test_to_crash_failure = {}
+
+        # reset static variables for Failure type classes
+        test_failures.TestFailure.port = self._port
+        test_failures.TestFailure.result_directory = self._results_directory
+        test_failures.TestFailure.filesystem = self._filesystem
+
         for test, result in run_results.unexpected_results_by_name.iteritems():
             if result.type != test_expectations.CRASH:
                 continue
             for failure in result.failures:
-                if not isinstance(failure, test_failures.FailureCrash):
-                    continue
-                if failure.has_log:
+                if (not isinstance(failure, test_failures.FailureCrash) or
+                        failure.has_log):
                     continue
                 crashed_processes.append([test, failure.process_name, failure.pid])
+                test_to_crash_failure[test] = failure
 
-        sample_files = self._port.look_for_new_samples(crashed_processes, start_time)
-        if sample_files:
-            for test, sample_file in sample_files.iteritems():
-                writer = TestResultWriter(self._filesystem, self._port, self._port.results_directory(), test)
-                writer.copy_sample_file(sample_file)
+        sample_files = self._port.look_for_new_samples(
+            crashed_processes, start_time) or {}
+        for test, sample_file in sample_files.iteritems():
+            test_failures.TestFailure.test_name = test
+            test_result = run_results.unexpected_results_by_name[test]
+            artifact_relative_path = self._port.output_filename(
+                test, test_failures.FILENAME_SUFFIX_SAMPLE, '.txt')
+            artifacts_sub_dir = test_result.artifacts.ArtifactsSubDirectory()
+            artifact_abspath = self._filesystem.join(
+                self._results_directory, artifacts_sub_dir, artifact_relative_path)
+            self._filesystem.maybe_make_directory(
+                self._filesystem.dirname(artifact_abspath))
+            self._filesystem.copyfile(sample_file, artifact_abspath)
+            test_result.artifacts.AddArtifact('sample_file',
+                self._filesystem.join(artifacts_sub_dir, artifact_relative_path))
 
-        crash_logs = self._port.look_for_new_crash_logs(crashed_processes, start_time)
-        if crash_logs:
-            for test, (crash_log, crash_site) in crash_logs.iteritems():
-                writer = TestResultWriter(self._filesystem, self._port, self._port.results_directory(), test)
-                writer.write_crash_log(crash_log)
-                run_results.unexpected_results_by_name[test].crash_site = crash_site
+        new_crash_logs = self._port.look_for_new_crash_logs(
+            crashed_processes, start_time) or {}
+        for test, (crash_log, crash_site) in new_crash_logs.iteritems():
+            test_failures.TestFailure.test_name = test
+            failure.crash_log = crash_log
+            failure.has_log = self._port.output_contains_sanitizer_messages(
+                failure.crash_log)
+            test_result = run_results.unexpected_results_by_name[test]
+            test_result.crash_site = crash_site
+            test_to_crash_failure[test].create_artifacts(
+                test_result.artifacts, force_overwrite=True)
 
     def _clobber_old_results(self):
         dir_above_results_path = self._filesystem.dirname(self._results_directory)
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py b/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
index 0c9b8a7..2c9f902 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
@@ -31,11 +31,10 @@
 import logging
 import re
 
-from blinkpy.web_tests.controllers import test_result_writer
 from blinkpy.web_tests.port.driver import DeviceFailure, DriverInput, DriverOutput
 from blinkpy.web_tests.models import test_expectations
 from blinkpy.web_tests.models import test_failures
-from blinkpy.web_tests.models.test_results import TestResult
+from blinkpy.web_tests.models.test_results import TestResult, build_test_result
 from blinkpy.web_tests.models import testharness_results
 
 
@@ -49,7 +48,9 @@
         port, options, results_directory, worker_name, primary_driver,
         secondary_driver, test_input)
     try:
-        return runner.run()
+        test_result =  runner.run()
+        test_result.create_artifacts()
+        return test_result
     except DeviceFailure as error:
         _log.error('device failed: %s', error)
         return TestResult(test_input.test_name, device_failed=True)
@@ -68,6 +69,16 @@
         self._worker_name = worker_name
         self._test_name = test_input.test_name
         self._reference_files = test_input.reference_files
+        self._retry_attempt = test_input.retry_attempt
+
+        test_failures.TestFailure.port = port
+        test_failures.TestFailure.test_name = test_input.test_name
+        test_failures.TestFailure.result_directory = results_directory
+        test_failures.TestFailure.filesystem = self._filesystem
+        TestResult.repeat_tests = (
+            self._options.watch or self._options.repeat_each > 1 or self._options.iterations > 1)
+        TestResult.results_directory = self._results_directory
+        TestResult.filesystem = port.host.filesystem
 
         # If this is a virtual test that uses the default flags instead of the
         # virtual flags for it's references, run it on the secondary driver so
@@ -116,12 +127,11 @@
         driver_output = self._driver.run_test(self._driver_input())
         expected_driver_output = self._expected_driver_output()
         failures = self._handle_error(driver_output)
-        test_result = TestResult(
-            self._test_name, failures=failures, test_run_time=driver_output.test_time,
+
+        test_result = build_test_result(
+            driver_output, self._test_name, retry_attempt=self._retry_attempt,
+            failures=failures, test_run_time=driver_output.test_time,
             pid=driver_output.pid, crash_site=driver_output.crash_site)
-        test_result_writer.write_test_result(
-            self._filesystem, self._port, self._results_directory,
-            self._test_name, driver_output, expected_driver_output, failures)
         return test_result
 
     def _run_compare_test(self):
@@ -129,11 +139,10 @@
         driver_output = self._driver.run_test(self._driver_input())
         baseline_output = self._expected_driver_output()
         failures = self._compare_output(baseline_output, driver_output)
-        test_result_writer.write_test_result(
-            self._filesystem, self._port, self._results_directory,
-            self._test_name, driver_output, baseline_output, failures)
-        return TestResult(
-            self._test_name, failures=failures, test_run_time=driver_output.test_time,
+
+        return build_test_result(
+            driver_output, self._test_name, retry_attempt=self._retry_attempt,
+            failures=failures, test_run_time=driver_output.test_time,
             pid=driver_output.pid, crash_site=driver_output.crash_site)
 
     def _run_rebaseline(self):
@@ -156,16 +165,12 @@
             # output as well as leaks, timeouts and crashes
             reported_failures = all_failures
 
-        test_result_writer.write_test_result(
-            self._filesystem, self._port, self._results_directory,
-            self._test_name, driver_output, baseline_output, reported_failures)
-
         self._update_or_add_new_baselines(driver_output, all_failures)
 
-        return TestResult(
-            self._test_name, failures=reported_failures,
-            test_run_time=driver_output.test_time, pid=driver_output.pid,
-            crash_site=driver_output.crash_site)
+        return build_test_result(
+            driver_output, self._test_name, retry_attempt=self._retry_attempt,
+            failures=reported_failures, test_run_time=driver_output.test_time,
+            pid=driver_output.pid, crash_site=driver_output.crash_site)
 
     def _update_or_add_new_baselines(self, driver_output, failures):
         """Updates or adds new baselines for the test if necessary."""
@@ -184,19 +189,22 @@
         #    optimize them later with optimize-baselines.
         if self._is_all_pass_testharness_text_not_needing_baseline(driver_output.text):
             driver_output.text = None
-        self._save_baseline_data(driver_output.text, '.txt',
-                                 test_failures.has_failure_type(test_failures.FailureMissingResult, failures) or
-                                 test_failures.has_failure_type(test_failures.FailureTestHarnessAssertion, failures))
-        self._save_baseline_data(driver_output.audio, '.wav',
-                                 test_failures.has_failure_type(test_failures.FailureMissingAudio, failures))
+        self._save_baseline_data(
+            driver_output.text, '.txt',
+            test_failures.has_failure_type(test_failures.FailureMissingResult, failures) or
+            test_failures.has_failure_type(test_failures.FailureTestHarnessAssertion, failures))
+        self._save_baseline_data(
+            driver_output.audio, '.wav',
+            test_failures.has_failure_type(test_failures.FailureMissingAudio, failures))
 
         expected_png = driver_output.image
         if self._reference_files:
             _log.warning('Can not rebaseline the image baseline of reftest %s', self._test_name)
             # Let _save_baseline_data remove the '-expected.png' if it exists.
             expected_png = None
-        self._save_baseline_data(expected_png, '.png',
-                                 test_failures.has_failure_type(test_failures.FailureMissingImage, failures))
+        self._save_baseline_data(
+            expected_png, '.png',
+            test_failures.has_failure_type(test_failures.FailureMissingImage, failures))
 
     def _save_baseline_data(self, data, extension, force_create_new_baseline):
         port = self._port
@@ -213,7 +221,8 @@
         elif self._options.copy_baselines:
             output_dir = fs.join(port.baseline_version_dir(), fs.dirname(self._test_name))
         else:
-            output_dir = fs.dirname(port.expected_filename(self._test_name, extension, fallback_base_for_virtual=False))
+            output_dir = fs.dirname(
+                port.expected_filename(self._test_name, extension, fallback_base_for_virtual=False))
 
         fs.maybe_make_directory(output_dir)
         output_basename = fs.basename(fs.splitext(self._test_name)[0] + '-expected' + extension)
@@ -221,8 +230,9 @@
 
         # Remove |output_path| if it exists and is not the generic expectation to
         # avoid extra baseline if the new baseline is the same as the fallback baseline.
-        generic_dir = fs.join(port.web_tests_dir(),
-                              fs.dirname(port.lookup_virtual_test_base(self._test_name) or self._test_name))
+        generic_dir = fs.join(
+            port.web_tests_dir(), fs.dirname(
+                port.lookup_virtual_test_base(self._test_name) or self._test_name))
         if (not data or output_dir != generic_dir) and fs.exists(output_path):
             _log.info('Removing the current baseline "%s"', port.relative_test_filename(output_path))
             fs.remove(output_path)
@@ -233,11 +243,13 @@
         if (current_expected_path and
                 fs.sha1(current_expected_path) == hashlib.sha1(data).hexdigest()):
             if self._options.reset_results:
-                _log.info('Not writing new baseline "%s" because it is the same as the current baseline',
-                          port.relative_test_filename(output_path))
+                _log.info(
+                    'Not writing new baseline "%s" because it is the same as the current baseline',
+                    port.relative_test_filename(output_path))
             else:
-                _log.info('Not copying baseline to "%s" because the actual result is the same as the current baseline',
-                          port.relative_test_filename(output_path))
+                _log.info(
+                    'Not copying baseline to "%s" because the actual result is the same as the current baseline',
+                    port.relative_test_filename(output_path))
             return
 
         if not data and not current_expected_path:
@@ -254,22 +266,24 @@
             if fs.exists(current_expected_path):
                 fs.copyfile(current_expected_path, output_path)
             else:
-                _log.error('Could not copy baseline to "%s" from "%s" because the source file does not exist',
-                           port.relative_test_filename(output_path), current_expected_path)
+                _log.error(
+                    'Could not copy baseline to "%s" from "%s" because the source file does not exist',
+                    port.relative_test_filename(output_path), current_expected_path)
 
     def _handle_error(self, driver_output, reference_filename=None):
         """Returns test failures if some unusual errors happen in driver's run.
 
         Args:
           driver_output: The output from the driver.
-          reference_filename: The full path to the reference file which produced the driver_output.
-              This arg is optional and should be used only in reftests until we have a better way to know
-              which html file is used for producing the driver_output.
+          reference_filename: The full path to the reference file which produced
+               the driver_output. This arg is optional and should be used only in
+               reftests until we have a better way to know which html file
+               is used for producing the driver_output.
         """
         failures = []
         if driver_output.timeout:
             failures.append(test_failures.FailureTimeout(
-                driver_output, None, bool(reference_filename)))
+                driver_output, bool(reference_filename)))
 
         if reference_filename:
             testname = self._port.relative_test_filename(reference_filename)
@@ -278,16 +292,17 @@
 
         if driver_output.crash:
             failures.append(test_failures.FailureCrash(
-                driver_output, None, bool(reference_filename),
-                driver_output.crashed_process_name, driver_output.crashed_pid,
-                self._port.output_contains_sanitizer_messages(driver_output.crash_log)))
+                driver_output, is_reftest=bool(reference_filename),
+                process_name=driver_output.crashed_process_name,
+                pid=driver_output.crashed_pid,
+                has_log=self._port.output_contains_sanitizer_messages(driver_output.crash_log)))
             if driver_output.error:
                 _log.debug('%s %s crashed, (stderr lines):', self._worker_name, testname)
             else:
                 _log.debug('%s %s crashed, (no stderr)', self._worker_name, testname)
         elif driver_output.leak:
             failures.append(test_failures.FailureLeak(
-                driver_output, None, bool(reference_filename), driver_output.leak_log))
+                driver_output, bool(reference_filename)))
             _log.debug('%s %s leaked', self._worker_name, testname)
         elif driver_output.error:
             _log.debug('%s %s output stderr lines:', self._worker_name, testname)
@@ -358,7 +373,7 @@
                 failures.append(test_failures.FailureMissingResult(
                     driver_output, expected_driver_output))
         elif self._report_extra_baseline(driver_output, '.txt', 'does not produce text result'):
-            failures.append(test_failures.FailureTextMismatch(
+            failures.append(test_failures.FailureTextNotGenerated(
                 driver_output, expected_driver_output))
 
         if driver_output.image_hash:
@@ -370,11 +385,11 @@
                 if not expected_driver_output.image:
                     failures.append(test_failures.FailureMissingImage(
                         driver_output, expected_driver_output))
-                if not expected_driver_output.image_hash:
+                elif not expected_driver_output.image_hash:
                     failures.append(test_failures.FailureMissingImageHash(
                         driver_output, expected_driver_output))
         elif self._report_extra_baseline(driver_output, '.png', 'does not produce image result'):
-            failures.append(test_failures.FailureImageHashMismatch(
+            failures.append(test_failures.FailureImageHashNotGenerated(
                 driver_output, expected_driver_output))
 
         if driver_output.audio:
@@ -382,7 +397,7 @@
                 failures.append(test_failures.FailureMissingAudio(
                     driver_output, expected_driver_output))
         elif self._report_extra_baseline(driver_output, '.wav', 'does not produce audio result'):
-            failures.append(test_failures.FailureAudioMismatch(
+            failures.append(test_failures.FailureAudioNotGenerated(
                 driver_output, expected_driver_output))
 
         return failures
@@ -426,7 +441,8 @@
             return text
 
         def remove_ng_text(results):
-            processed = re.sub(r'LayoutNG(BlockFlow|ListItem|TableCell)', r'Layout\1', results)
+            processed = re.sub(
+                r'LayoutNG(BlockFlow|ListItem|TableCell)', r'Layout\1', results)
             # LayoutTableCaption doesn't override LayoutBlockFlow::GetName, so
             # render tree dumps have "LayoutBlockFlow" for captions.
             processed = re.sub('LayoutNGTableCaption', 'LayoutBlockFlow', processed)
@@ -439,7 +455,8 @@
                 return False
             # There's a mix of NG and legacy names in both expected and actual,
             # so just remove NG from both.
-            return not self._port.do_text_results_differ(remove_ng_text(expected), remove_ng_text(actual))
+            return not self._port.do_text_results_differ(
+                remove_ng_text(expected), remove_ng_text(actual))
 
         # LayoutNG name mismatch (e.g., LayoutBlockFlow vs. LayoutNGBlockFlow)
         # is treated as pass
@@ -474,8 +491,10 @@
     def _compare_audio(self, expected_driver_output, driver_output):
         if not expected_driver_output.audio or not driver_output.audio:
             return []
-        if self._port.do_audio_results_differ(expected_driver_output.audio, driver_output.audio):
-            return [test_failures.FailureAudioMismatch(driver_output, expected_driver_output)]
+        if self._port.do_audio_results_differ(
+            expected_driver_output.audio, driver_output.audio):
+            return [test_failures.FailureAudioMismatch(
+                        driver_output, expected_driver_output)]
         return []
 
     def _get_normalized_output_text(self, output):
@@ -501,18 +520,37 @@
         if driver_output.image_hash != expected_driver_output.image_hash:
             diff, err_str = self._port.diff_image(
                 expected_driver_output.image, driver_output.image)
+
+            if diff:
+                driver_output.image_diff = diff
+
             if err_str:
-                _log.warning('  %s : %s', self._test_name, err_str)
+                _log.error('  %s : %s', self._test_name, err_str)
                 driver_output.error = (driver_output.error or '') + err_str
+
+            if diff or err_str:
+                return [
+                    test_failures.FailureImageHashMismatch(
+                        driver_output, expected_driver_output)]
             else:
-                # See https://bugs.webkit.org/show_bug.cgi?id=69444 for why this isn't a full failure.
+                # See https://bugs.webkit.org/show_bug.cgi?id=69444 for why this
+                # isn't a full failure.
                 _log.warning(
                     '  %s -> pixel hash failed (but diff passed)', self._test_name)
-                driver_output.image_diff = diff
-            if err_str or diff:
-                return [test_failures.FailureImageHashMismatch(
-                    driver_output, expected_driver_output, diff)]
 
+            if err_str:
+                _log.error(err_str)
+                driver_output.error = (driver_output.error or '') + err_str
+
+            if diff or err_str:
+                return [
+                    test_failures.FailureImageHashMismatch(
+                        driver_output, expected_driver_output)]
+            else:
+                # See https://bugs.webkit.org/show_bug.cgi?id=69444 for why this
+                # isn't a full failure.
+                _log.warning(
+                    '  %s -> pixel hash failed (but diff passed)', self._test_name)
         return []
 
     def _run_reftest(self):
@@ -531,20 +569,17 @@
         # If the test crashed, or timed out, there's no point in running the reference at all.
         # This can save a lot of execution time if we have a lot of crashes or timeouts.
         if test_output.crash or test_output.timeout:
-            if test_output.crash:
-                test_result_writer.write_test_result(
-                    self._filesystem, self._port, self._results_directory, self._test_name,
-                    test_output, expected_text_output, compare_text_failures)
-            return TestResult(
-                self._test_name, failures=compare_text_failures,
-                test_run_time=test_output.test_time, pid=test_output.pid,
-                crash_site=test_output.crash_site)
+            return build_test_result(
+                test_output, self._test_name, retry_attempt=self._retry_attempt,
+                failures=compare_text_failures, test_run_time=test_output.test_time,
+                pid=test_output.pid, crash_site=test_output.crash_site)
 
         # A reftest can have multiple match references and multiple mismatch references;
         # the test fails if any mismatch matches and all of the matches don't match.
-        # To minimize the number of references we have to check, we run all of the mismatches first,
-        # then the matches, and short-circuit out as soon as we can.
-        # Note that sorting by the expectation sorts "!=" before "==" so this is easy to do.
+        # To minimize the number of references we have to check, we run all of the
+        # mismatches first, then the matches, and short-circuit out as soon as we can.
+        # Note that sorting by the expectation sorts "!=" before "==" so this is easy
+        # to do.
         expected_output = None
         reference_test_names = []
         reftest_failures = []
@@ -552,6 +587,7 @@
             args = self._port.lookup_virtual_reference_args(self._test_name)
         else:
             args = self._port.lookup_physical_reference_args(self._test_name)
+
         # sort self._reference_files to put mismatch tests first
         for expectation, reference_filename in sorted(self._reference_files):
             reference_test_name = self._port.relative_test_filename(reference_filename)
@@ -573,17 +609,16 @@
         expected_output.text = expected_text_output.text
         failures = reftest_failures + compare_text_failures
 
-        test_result_writer.write_test_result(
-            self._filesystem, self._port, self._results_directory,
-            self._test_name, test_output, expected_output, failures)
-
-        # FIXME: We don't really deal with a mix of reftest types properly. We pass in a set() to reftest_type
-        # and only really handle the first of the references in the result.
+        # FIXME: We don't really deal with a mix of reftest types properly. We
+        # pass in a set() to reftest_type and only really handle the first of
+        # the references in the result.
         reftest_type = list(set([reference_file[0] for reference_file in self._reference_files]))
-        return TestResult(
-            self._test_name, failures=failures, test_run_time=total_test_time,
-            reftest_type=reftest_type, pid=test_output.pid,
-            crash_site=test_output.crash_site, references=reference_test_names)
+
+        return build_test_result(
+            test_output, self._test_name, retry_attempt=self._retry_attempt,
+            failures=failures, test_run_time=total_test_time, reftest_type=reftest_type,
+            pid=test_output.pid, crash_site=test_output.crash_site,
+            references=reference_test_names)
 
     def _compare_output_with_reference(
         self, reference_driver_output, actual_driver_output, reference_filename, mismatch):
@@ -613,14 +648,23 @@
             diff, err_str = self._port.diff_image(
                 reference_driver_output.image, actual_driver_output.image)
             if diff:
+                actual_driver_output.image_diff = diff
+
+            if err_str:
+                _log.error(err_str)
+                actual_driver_output.error = (actual_driver_output.error or '') + err_str
+
+            if diff or err_str:
                 failures.append(
                     test_failures.FailureReftestMismatch(
                         actual_driver_output, reference_driver_output,
                         reference_filename))
             elif err_str:
                 # TODO(rmhasan) Should we include this error message in the artifacts ?
-                _log.error(err_str)
+                _log.error('  %s : %s', self._test_name, err_str)
             else:
-                _log.warning("  %s -> ref test hashes didn't match but diff passed", self._test_name)
+                _log.warning(
+                    "  %s -> ref test hashes didn't match but diff passed",
+                    self._test_name)
 
         return failures
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer.py b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer.py
deleted file mode 100644
index 531f7e7..0000000
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer.py
+++ /dev/null
@@ -1,277 +0,0 @@
-# Copyright (C) 2011 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-import logging
-
-from blinkpy.common.html_diff import html_diff
-from blinkpy.common.unified_diff import unified_diff
-from blinkpy.web_tests.controllers import repaint_overlay
-from blinkpy.web_tests.models import test_failures
-
-
-_log = logging.getLogger(__name__)
-
-
-def write_test_result(filesystem, port, results_directory, test_name, driver_output,
-                      expected_driver_output, failures):
-    """Write the test result to the result output directory."""
-    root_output_dir = results_directory
-    writer = TestResultWriter(filesystem, port, root_output_dir, test_name)
-
-    # TODO(rmhasan): If the reference file driver output has stderr, we should
-    # write out that standard error
-    if driver_output.error:
-        writer.write_stderr(driver_output.error)
-
-    for failure in failures:
-        # FIXME: Instead of this long 'if' block, each failure class might
-        # have a responsibility for writing a test result.
-        if isinstance(failure, (test_failures.FailureMissingResult,
-                                test_failures.FailureTextMismatch,
-                                test_failures.FailureTestHarnessAssertion)):
-            writer.write_text_files(driver_output.text, expected_driver_output.text)
-            writer.create_text_diff_and_write_result(driver_output.text, expected_driver_output.text)
-        elif isinstance(failure, test_failures.FailureMissingImage):
-            writer.write_image_files(driver_output.image, expected_image=None)
-        elif isinstance(failure, test_failures.FailureMissingImageHash):
-            writer.write_image_files(driver_output.image, expected_driver_output.image)
-        elif isinstance(failure, test_failures.FailureImageHashMismatch):
-            writer.write_image_files(driver_output.image, expected_driver_output.image)
-            writer.write_image_diff_files(driver_output.image_diff)
-        elif isinstance(failure, (test_failures.FailureAudioMismatch,
-                                  test_failures.FailureMissingAudio)):
-            writer.write_audio_files(driver_output.audio, expected_driver_output.audio)
-        elif isinstance(failure, test_failures.FailureCrash):
-            crashed_driver_output = expected_driver_output if failure.is_reftest else driver_output
-            writer.write_crash_log(crashed_driver_output.crash_log)
-        elif isinstance(failure, test_failures.FailureLeak):
-            writer.write_leak_log(driver_output.leak_log)
-        elif isinstance(failure, (
-                test_failures.FailureReftestMismatch,
-                test_failures.FailureReftestNoImageGenerated,
-                test_failures.FailureReftestNoReferenceImageGenerated)):
-            writer.write_image_files(driver_output.image, expected_driver_output.image)
-            if driver_output.image and expected_driver_output.image:
-                diff_image, _ = port.diff_image(expected_driver_output.image, driver_output.image)
-                if diff_image:
-                    writer.write_image_diff_files(diff_image)
-                else:
-                    _log.warning('ref test mismatch did not produce an image diff.')
-            if filesystem.exists(failure.reference_filename):
-                writer.write_reftest(failure.reference_filename)
-            else:
-                _log.warning("reference %s was not found", failure.reference_filename)
-        elif isinstance(failure, test_failures.FailureReftestMismatchDidNotOccur):
-            writer.write_image_files(driver_output.image, expected_image=None)
-            if filesystem.exists(failure.reference_filename):
-                writer.write_reftest(failure.reference_filename)
-            else:
-                _log.warning("reference %s was not found", failure.reference_filename)
-        else:
-            assert isinstance(failure, test_failures.FailureTimeout)
-
-        if expected_driver_output is not None:
-            writer.create_repaint_overlay_result(driver_output.text, expected_driver_output.text)
-
-
-class TestResultWriter(object):
-    """A class which handles all writing operations to the result directory."""
-
-    # Filename pieces when writing failures to the test results directory.
-    FILENAME_SUFFIX_ACTUAL = "-actual"
-    FILENAME_SUFFIX_EXPECTED = "-expected"
-    FILENAME_SUFFIX_DIFF = "-diff"
-    FILENAME_SUFFIX_DIFFS = "-diffs"
-    FILENAME_SUFFIX_STDERR = "-stderr"
-    FILENAME_SUFFIX_CRASH_LOG = "-crash-log"
-    FILENAME_SUFFIX_SAMPLE = "-sample"
-    FILENAME_SUFFIX_LEAK_LOG = "-leak-log"
-    FILENAME_SUFFIX_HTML_DIFF = "-pretty-diff"
-    FILENAME_SUFFIX_OVERLAY = "-overlay"
-
-    def __init__(self, filesystem, port, root_output_dir, test_name):
-        self._filesystem = filesystem
-        self._port = port
-        self._root_output_dir = root_output_dir
-        self._test_name = test_name
-
-    def _write_file(self, path, contents):
-        if contents is not None:
-            fs = self._filesystem
-            fs.maybe_make_directory(fs.dirname(path))
-            fs.write_binary_file(path, contents)
-
-    def _output_filename(self, suffix, extension):
-        """Returns a filename based on the given suffix and extension.
-
-        For example, if test name is "fast/dom/foo.html", the suffix is
-        "-expected", and the extension is "-expected.txt", the return value is
-        "fast/dom/foo-expected.txt".
-        """
-        return self._port.output_filename(self._test_name, suffix, extension)
-
-    def _output_abspath(self, suffix, extension):
-        """Similar to _output_filename, but returns an absolute path in output dir."""
-        filename = self._output_filename(suffix, extension)
-        return self._filesystem.join(self._root_output_dir, filename)
-
-    def write_output_files(self, file_type, output, expected):
-        """Writes the test output, the expected output in the results directory.
-
-        The full output filename of the actual, for example, will be
-          <filename>-actual<file_type>
-        For instance,
-          my_test-actual.txt
-
-        Args:
-          file_type: A string describing the test output file type, e.g. ".txt"
-          output: A string containing the test output
-          expected: A string containing the expected test output
-        """
-        actual_filename = self._output_abspath(self.FILENAME_SUFFIX_ACTUAL, file_type)
-        expected_filename = self._output_abspath(self.FILENAME_SUFFIX_EXPECTED, file_type)
-
-        self._write_file(actual_filename, output)
-        self._write_file(expected_filename, expected)
-
-    def write_stderr(self, error):
-        filename = self._output_abspath(self.FILENAME_SUFFIX_STDERR, ".txt")
-        self._write_file(filename, error)
-
-    def write_crash_log(self, crash_log):
-        filename = self._output_abspath(self.FILENAME_SUFFIX_CRASH_LOG, ".txt")
-        self._write_file(filename, crash_log.encode('utf8', 'replace'))
-
-    def write_leak_log(self, leak_log):
-        filename = self._output_abspath(self.FILENAME_SUFFIX_LEAK_LOG, ".txt")
-        self._write_file(filename, leak_log)
-
-    def copy_sample_file(self, sample_file):
-        filename = self._output_abspath(self.FILENAME_SUFFIX_SAMPLE, ".txt")
-        self._filesystem.copyfile(sample_file, filename)
-
-    def write_text_files(self, actual_text, expected_text):
-        self.write_output_files(".txt", actual_text, expected_text)
-
-    def create_text_diff_and_write_result(self, actual_text, expected_text):
-        # FIXME: This function is actually doing the diffs as well as writing results.
-        # It might be better to extract code which does 'diff' and make it a separate function.
-        actual_text = actual_text or ''
-        expected_text = expected_text or ''
-
-        # Output a plain-text diff file.
-        file_type = '.txt'
-        actual_filename = self._output_abspath(self.FILENAME_SUFFIX_ACTUAL, file_type)
-        expected_filename = self._output_abspath(self.FILENAME_SUFFIX_EXPECTED, file_type)
-        diff = unified_diff(expected_text, actual_text, expected_filename, actual_filename)
-        diff_filename = self._output_abspath(self.FILENAME_SUFFIX_DIFF, file_type)
-        self._write_file(diff_filename, diff)
-
-        # Output a HTML diff file.
-        html_diff_filename = self._output_abspath(self.FILENAME_SUFFIX_HTML_DIFF, '.html')
-        html_diff_contents = html_diff(expected_text, actual_text)
-        self._write_file(html_diff_filename, html_diff_contents)
-
-    def create_repaint_overlay_result(self, actual_text, expected_text):
-        html = repaint_overlay.generate_repaint_overlay_html(self._test_name, actual_text, expected_text)
-        if html:
-            overlay_filename = self._output_abspath(self.FILENAME_SUFFIX_OVERLAY, '.html')
-            self._write_file(overlay_filename, html)
-
-    def write_audio_files(self, actual_audio, expected_audio):
-        self.write_output_files('.wav', actual_audio, expected_audio)
-
-    def write_image_files(self, actual_image, expected_image):
-        self.write_output_files('.png', actual_image, expected_image)
-
-    def write_image_diff_files(self, image_diff):
-        diff_filename = self._output_abspath(self.FILENAME_SUFFIX_DIFF, '.png')
-        self._write_file(diff_filename, image_diff)
-
-        diffs_html_filename = self._output_abspath(self.FILENAME_SUFFIX_DIFFS, '.html')
-        # FIXME: old-run-webkit-tests shows the diff percentage as the text contents of the "diff" link.
-        # FIXME: old-run-webkit-tests include a link to the test file.
-        html = ("""<!DOCTYPE HTML>
-<html>
-<head>
-<title>%(title)s</title>
-<style>.label{font-weight:bold}</style>
-</head>
-<body>
-Difference between images: <a href="%(diff_filename)s">diff</a><br>
-<div class=imageText></div>
-<div class=imageContainer data-prefix="%(prefix)s">Loading...</div>
-<script>
-(function() {
-    var preloadedImageCount = 0;
-    function preloadComplete() {
-        ++preloadedImageCount;
-        if (preloadedImageCount < 2)
-            return;
-        toggleImages();
-        setInterval(toggleImages, 2000)
-    }
-
-    function preloadImage(url) {
-        image = new Image();
-        image.addEventListener('load', preloadComplete);
-        image.src = url;
-        return image;
-    }
-
-    function toggleImages() {
-        if (text.textContent == 'Expected Image') {
-            text.textContent = 'Actual Image';
-            container.replaceChild(actualImage, container.firstChild);
-        } else {
-            text.textContent = 'Expected Image';
-            container.replaceChild(expectedImage, container.firstChild);
-        }
-    }
-
-    var text = document.querySelector('.imageText');
-    var container = document.querySelector('.imageContainer');
-    var actualImage = preloadImage(container.getAttribute('data-prefix') + '-actual.png');
-    var expectedImage = preloadImage(container.getAttribute('data-prefix') + '-expected.png');
-})();
-</script>
-</body>
-</html>"""
-                % {
-                    'title': self._test_name,
-                    'diff_filename': self._output_filename(self.FILENAME_SUFFIX_DIFF, '.png'),
-                    'prefix': self._output_filename('', ''),
-                })
-        self._write_file(diffs_html_filename, html)
-
-    def write_reftest(self, src_filepath):
-        fs = self._filesystem
-        dst_dir = fs.dirname(fs.join(self._root_output_dir, self._test_name))
-        dst_filepath = fs.join(dst_dir, fs.basename(src_filepath))
-        self._write_file(dst_filepath, fs.read_binary_file(src_filepath))
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer_unittest.py b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer_unittest.py
deleted file mode 100644
index f0fdedc..0000000
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer_unittest.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright (C) 2013 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import optparse
-import unittest
-
-from blinkpy.common.system.filesystem_mock import MockFileSystem
-from blinkpy.common.system.system_host_mock import MockSystemHost
-from blinkpy.web_tests.controllers.test_result_writer import write_test_result
-from blinkpy.web_tests.port.driver import DriverOutput
-from blinkpy.web_tests.port.test import TestPort
-from blinkpy.web_tests.models import test_failures
-
-
-class TestResultWriterTests(unittest.TestCase):
-
-    def setUp(self):
-        self._actual_output = DriverOutput(
-            text='', image=None, image_hash=None, audio=None)
-        self._expected_output = DriverOutput(
-            text='', image=None, image_hash=None, audio=None)
-
-    def run_test(self, failures=None, files=None, filename='foo.html'):
-        failures = failures or []
-        host = MockSystemHost()
-        host.filesystem.files = files or {}
-        port = TestPort(host=host, port_name='test-mac-mac10.11', options=optparse.Values())
-        write_test_result(
-            host.filesystem, port, '/tmp', filename, self._actual_output,
-            self._expected_output, failures)
-        return host.filesystem
-
-    def test_success(self):
-        # Nothing is written when the test passes.
-        fs = self.run_test(failures=[])
-        self.assertEqual(fs.written_files, {})
-
-    def test_reference_exists(self):
-        failure = test_failures.FailureReftestMismatch(
-            self._actual_output, self._expected_output)
-        failure.reference_filename = '/src/exists-expected.html'
-        files = {'/src/exists-expected.html': 'yup'}
-        fs = self.run_test(failures=[failure], files=files)
-        self.assertEqual(fs.written_files, {'/tmp/exists-expected.html': 'yup'})
-
-        failure = test_failures.FailureReftestMismatchDidNotOccur(
-            self._actual_output, self._expected_output)
-        failure.reference_filename = '/src/exists-expected-mismatch.html'
-        files = {'/src/exists-expected-mismatch.html': 'yup'}
-        fs = self.run_test(failures=[failure], files=files)
-        self.assertEqual(fs.written_files, {'/tmp/exists-expected-mismatch.html': 'yup'})
-
-    def test_reference_is_missing(self):
-        failure = test_failures.FailureReftestMismatch(
-            self._actual_output, self._expected_output)
-        failure.reference_filename = 'notfound.html'
-        fs = self.run_test(failures=[failure], files={})
-        self.assertEqual(fs.written_files, {})
-
-        failure = test_failures.FailureReftestMismatchDidNotOccur(
-            self._actual_output, self._expected_output)
-        failure.reference_filename = 'notfound.html'
-        fs = self.run_test(failures=[failure], files={})
-        self.assertEqual(fs.written_files, {})
-
-    def test_reftest_image_missing(self):
-        failure = test_failures.FailureReftestNoImageGenerated(
-            self._actual_output, self._expected_output)
-        failure.reference_filename = '/src/exists-expected.html'
-        files = {'/src/exists-expected.html': 'yup'}
-        fs = self.run_test(failures=[failure], files=files)
-        self.assertEqual(fs.written_files, {'/tmp/exists-expected.html': 'yup'})
-
-        failure = test_failures.FailureReftestNoReferenceImageGenerated(
-            self._actual_output, self._expected_output)
-        failure.reference_filename = '/src/exists-expected.html'
-        files = {'/src/exists-expected.html': 'yup'}
-        fs = self.run_test(failures=[failure], files=files)
-        self.assertEqual(fs.written_files, {'/tmp/exists-expected.html': 'yup'})
-
-    def test_slash_in_test_name(self):
-        failure = test_failures.FailureTestHarnessAssertion(
-            self._actual_output, self._expected_output)
-        fs = self.run_test(failures=[failure], filename='foo.html?a/b')
-        self.assertTrue('/tmp/foo_a_b-actual.txt' in fs.written_files)
-        self.assertEqual(set(fs.written_files.keys()), {
-            '/tmp/foo_a_b-actual.txt',
-            '/tmp/foo_a_b-diff.txt',
-            '/tmp/foo_a_b-expected.txt',
-            '/tmp/foo_a_b-pretty-diff.html',
-        })
-        # Should not mkdir '/tmp/foo.html?a'
-        self.assertEqual(fs.dirs, {'/', '/tmp'})
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py
index 4980b26..16b1678 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py
@@ -69,7 +69,6 @@
 
         self._expectations = None
         self._test_inputs = []
-        self._retry_attempt = 0
         self._shards_to_redo = []
 
         self._current_run_results = None
@@ -84,10 +83,8 @@
         # prevents content shell reuse.
         if not self._options.must_use_derived_batch_size and retry_attempt >= 1:
             batch_size = 1
-
         self._expectations = expectations
         self._test_inputs = test_inputs
-        self._retry_attempt = retry_attempt
 
         test_run_results = TestRunResults(self._expectations, len(test_inputs) + len(tests_to_skip))
         self._current_run_results = test_run_results
@@ -162,17 +159,12 @@
             shard.test_inputs = list(itertools.chain(*tests_by_args.values()))
 
     def _worker_factory(self, worker_connection):
-        results_directory = self._results_directory
-        if self._retry_attempt > 0:
-            results_directory = self._filesystem.join(self._results_directory,
-                                                      'retry_%d' % self._retry_attempt)
-            self._filesystem.maybe_make_directory(results_directory)
-        return Worker(worker_connection, results_directory, self._options)
+        return Worker(worker_connection, self._results_directory, self._options)
 
     def _mark_interrupted_tests_as_skipped(self, test_run_results):
         for test_input in self._test_inputs:
             if test_input.test_name not in test_run_results.results_by_name:
-                result = test_results.TestResult(test_input.test_name, [test_failures.FailureEarlyExit()])
+                result = test_results.TestResult(test_input.test_name, failures=[test_failures.FailureEarlyExit()])
                 # FIXME: We probably need to loop here if there are multiple iterations.
                 # FIXME: Also, these results are really neither expected nor unexpected. We probably
                 # need a third type of result.
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py b/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
index 678587d..96bb096 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
@@ -30,7 +30,77 @@
 
 from blinkpy.web_tests.models import test_expectations
 from blinkpy.web_tests.controllers import repaint_overlay
+from blinkpy.common.html_diff import html_diff
+from blinkpy.common.unified_diff import unified_diff
 
+# TODO(rmhasan) Create a unit test for each Failure type and make
+# sure each artifact is written to the correct path
+
+# FIXME: old-run-webkit-tests shows the diff percentage as the text
+#   contents of the "diff" link.
+# FIXME: old-run-webkit-tests include a link to the test file.
+_image_diff_html_template = """<!DOCTYPE HTML>
+<html>
+<head>
+<title>%(title)s</title>
+<style>.label{font-weight:bold}</style>
+</head>
+<body>
+Difference between images: <a href="%(diff_filename)s">diff</a><br>
+<div class=imageText></div>
+<div class=imageContainer data-prefix="%(prefix)s">Loading...</div>
+<script>
+(function() {
+var preloadedImageCount = 0;
+function preloadComplete() {
+++preloadedImageCount;
+if (preloadedImageCount < 2)
+    return;
+toggleImages();
+setInterval(toggleImages, 2000)
+}
+
+function preloadImage(url) {
+image = new Image();
+image.addEventListener('load', preloadComplete);
+image.src = url;
+return image;
+}
+
+function toggleImages() {
+if (text.textContent == 'Expected Image') {
+    text.textContent = 'Actual Image';
+    container.replaceChild(actualImage, container.firstChild);
+} else {
+    text.textContent = 'Expected Image';
+    container.replaceChild(expectedImage, container.firstChild);
+}
+}
+
+var text = document.querySelector('.imageText');
+var container = document.querySelector('.imageContainer');
+var actualImage = preloadImage(container.getAttribute('data-prefix') + '-actual.png');
+var expectedImage = preloadImage(container.getAttribute('data-prefix') + '-expected.png');
+})();
+</script>
+</body>
+</html>"""
+
+# Filename pieces when writing failures to the test results directory.
+FILENAME_SUFFIX_ACTUAL = "-actual"
+FILENAME_SUFFIX_EXPECTED = "-expected"
+FILENAME_SUFFIX_DIFF = "-diff"
+FILENAME_SUFFIX_DIFFS = "-diffs"
+FILENAME_SUFFIX_STDERR = "-stderr"
+FILENAME_SUFFIX_CRASH_LOG = "-crash-log"
+FILENAME_SUFFIX_SAMPLE = "-sample"
+FILENAME_SUFFIX_LEAK_LOG = "-leak-log"
+FILENAME_SUFFIX_HTML_DIFF = "-pretty-diff"
+FILENAME_SUFFIX_OVERLAY = "-overlay"
+
+
+_ext_to_file_type = {
+    '.txt': 'text', '.png': 'image', '.wav': 'audio'}
 
 def is_reftest_failure(failure_list):
     input_failure_types = {type(f) for f in failure_list}
@@ -59,10 +129,12 @@
     Returns:
       one of the test_expectations result types - PASS, FAIL, CRASH, etc.
     """
-
     if not failure_list or len(failure_list) == 0:
         return test_expectations.PASS
 
+    if has_failure_type(PassWithStderr, failure_list):
+        assert len(failure_list) == 1
+        return test_expectations.PASS
     if has_failure_type(FailureCrash, failure_list):
         return test_expectations.CRASH
     elif has_failure_type(FailureLeak, failure_list):
@@ -78,11 +150,13 @@
         return test_expectations.MISSING
     else:
         is_text_failure = (has_failure_type(FailureTextMismatch, failure_list) or
-                           has_failure_type(FailureTestHarnessAssertion, failure_list))
-        is_image_failure = (has_failure_type(FailureImageHashIncorrect, failure_list) or
-                            has_failure_type(FailureImageHashMismatch, failure_list) or
+                           has_failure_type(FailureTestHarnessAssertion, failure_list) or
+                           has_failure_type(FailureTextNotGenerated, failure_list))
+        is_image_failure = (has_failure_type(FailureImageHashMismatch, failure_list) or
+                            has_failure_type(FailureImageHashNotGenerated, failure_list) or
                             is_reftest_failure(failure_list))
-        is_audio_failure = has_failure_type(FailureAudioMismatch, failure_list)
+        is_audio_failure = (has_failure_type(FailureAudioMismatch, failure_list) or
+                            has_failure_type(FailureAudioNotGenerated, failure_list))
         if is_text_failure and is_image_failure:
             return test_expectations.IMAGE_PLUS_TEXT
         elif is_text_failure:
@@ -99,11 +173,17 @@
 
 class TestFailure(object):
 
+    port = None
+    test_name = None
+    filesystem = None
+    result_directory = None
+
     def __init__(self, actual_driver_output, expected_driver_output):
         self.actual_driver_output = actual_driver_output
         self.expected_driver_output = expected_driver_output
         self._has_stderr = False
         self._repaint_overlay = False
+        self.is_reftest = False
         if actual_driver_output:
             self._has_stderr = actual_driver_output.has_stderr()
         if expected_driver_output:
@@ -117,6 +197,28 @@
     def has_repaint_overlay(self):
         return self._repaint_overlay
 
+    def _write_to_artifacts(
+            self, typ_artifacts, artifact_name, path, content, force_overwrite):
+        typ_artifacts.CreateArtifact(
+            artifact_name, path, content, force_overwrite=force_overwrite)
+
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        if self.actual_driver_output.error:
+            artifact_filename = self.port.output_filename(
+                self.test_name, FILENAME_SUFFIX_STDERR, '.txt')
+
+            # some ref tests don't produce any text output and also
+            # have a text baseline. They also produce an image mismatch
+            # error. If the test driver produces stderr then an exception
+            # will be raised because we will be writing that stderr twice
+            artifacts_abspath = self.filesystem.join(
+                self.result_directory, typ_artifacts.ArtifactsSubDirectory(),
+                artifact_filename)
+            if not self.filesystem.exists(artifacts_abspath):
+                self._write_to_artifacts(
+                    typ_artifacts, 'stderr', artifact_filename,
+                    self.actual_driver_output.error, force_overwrite=True)
+
     @staticmethod
     def loads(s):
         """Creates a TestFailure object from the specified string."""
@@ -143,15 +245,34 @@
         """Returns True if we should kill the driver before the next test."""
         return False
 
+    def message(self):
+        raise NotImplementedError
+
+    def text_mismatch_category(self):
+        raise NotImplementedError
+
+
+class PassWithStderr(TestFailure):
+
+    def __init__(self, driver_output):
+        # TODO (rmhasan): Should we write out the reference driver standard
+        # error
+        super(PassWithStderr, self).__init__(driver_output, None)
+
+    def message(self):
+        return 'test passed but has standard error output'
+
 
 class FailureTimeout(TestFailure):
 
-    def __init__(self, actual_driver_output, expected_driver_output,
-                is_reftest=False):
+    def __init__(self, actual_driver_output, is_reftest=False):
         super(FailureTimeout, self).__init__(
-            actual_driver_output, expected_driver_output)
+            actual_driver_output, None)
         self.is_reftest = is_reftest
 
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        pass
+
     def message(self):
         return 'test timed out'
 
@@ -161,15 +282,24 @@
 
 class FailureCrash(TestFailure):
 
-    def __init__(self, actual_driver_output, expected_driver_output,
-                 is_reftest=False, process_name='content_shell', pid=None,
-                 has_log=False):
+    def __init__(self, actual_driver_output, is_reftest=False,
+                 process_name='content_shell', pid=None, has_log=False):
         super(FailureCrash, self).__init__(
-            actual_driver_output, expected_driver_output)
+            actual_driver_output, None)
         self.process_name = process_name
         self.pid = pid
         self.is_reftest = is_reftest
         self.has_log = has_log
+        self.crash_log = self.actual_driver_output.crash_log
+
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        super(FailureCrash, self).create_artifacts(typ_artifacts, force_overwrite)
+        if self.crash_log:
+            artifact_filename = self.port.output_filename(
+                self.test_name, FILENAME_SUFFIX_CRASH_LOG, '.txt')
+            self._write_to_artifacts(
+                typ_artifacts, 'crash_log', artifact_filename,
+                self.crash_log.encode('utf8', 'replace'), force_overwrite)
 
     def message(self):
         if self.pid:
@@ -182,43 +312,115 @@
 
 class FailureLeak(TestFailure):
 
-    def __init__(self, actual_driver_output, expected_driver_output,
-                 is_reftest=False, log=''):
+    def __init__(self, actual_driver_output, is_reftest=False):
         super(FailureLeak, self).__init__(
-            actual_driver_output, expected_driver_output)
+            actual_driver_output, None)
         self.is_reftest = is_reftest
-        self.log = log
+
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        super(FailureLeak, self).create_artifacts(typ_artifacts, force_overwrite)
+        artifact_filename = self.port.output_filename(
+            self.test_name, FILENAME_SUFFIX_LEAK_LOG, '.txt')
+        self.log = self.actual_driver_output.leak_log
+        self._write_to_artifacts(
+            typ_artifacts, 'leak_log', artifact_filename, self.log, force_overwrite)
 
     def message(self):
         return 'leak detected: %s' % (self.log)
 
 
-class FailureMissingResult(TestFailure):
+class ActualAndBaselineArtifacts(TestFailure):
+
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        super(ActualAndBaselineArtifacts, self).create_artifacts(
+            typ_artifacts, force_overwrite)
+        self.actual_artifact_filename = self.port.output_filename(
+            self.test_name, FILENAME_SUFFIX_ACTUAL, self.file_ext)
+        self.expected_artifact_filename = self.port.output_filename(
+            self.test_name, FILENAME_SUFFIX_EXPECTED, self.file_ext)
+        attr = _ext_to_file_type[self.file_ext]
+        if getattr(self.actual_driver_output, attr):
+            self._write_to_artifacts(
+                typ_artifacts, 'actual_%s' % attr, self.actual_artifact_filename,
+                getattr(self.actual_driver_output, attr), force_overwrite)
+        if getattr(self.expected_driver_output, attr):
+            self._write_to_artifacts(
+                typ_artifacts, 'expected_%s' % attr, self.expected_artifact_filename,
+                getattr(self.expected_driver_output, attr), force_overwrite)
+
+    def message(self):
+        raise NotImplementedError
+
+
+class FailureText(ActualAndBaselineArtifacts):
+
+    def __init__(self, actual_driver_output, expected_driver_output):
+        super(FailureText, self).__init__(
+            actual_driver_output, expected_driver_output)
+        self._repaint_overlay = (
+            repaint_overlay.result_contains_repaint_rects(
+                actual_driver_output.text) or
+            repaint_overlay.result_contains_repaint_rects(
+                expected_driver_output.text))
+        self.file_ext = '.txt'
+
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        # TODO (rmhasan): See if you can can only output diff files for
+        # non empty text.
+        super(FailureText, self).create_artifacts(
+            typ_artifacts, force_overwrite)
+        expected_text = self.expected_driver_output.text or ''
+        actual_text = self.actual_driver_output.text or ''
+        artifacts_abs_path = self.filesystem.join(
+            self.result_directory, typ_artifacts.ArtifactsSubDirectory())
+        diff_content = unified_diff(
+          expected_text, actual_text,
+          self.filesystem.join(artifacts_abs_path, self.expected_artifact_filename),
+          self.filesystem.join(artifacts_abs_path, self.actual_artifact_filename))
+        diff_filename = self.port.output_filename(
+          self.test_name, FILENAME_SUFFIX_DIFF, '.txt')
+        html_diff_content = html_diff(expected_text, actual_text)
+        html_diff_filename = self.port.output_filename(
+            self.test_name, FILENAME_SUFFIX_HTML_DIFF, '.html')
+        self._write_to_artifacts(
+            typ_artifacts, 'text_diff', diff_filename, diff_content, force_overwrite)
+        self._write_to_artifacts(
+            typ_artifacts, 'pretty_text_diff', html_diff_filename,
+            html_diff_content, force_overwrite)
+
+    def message(self):
+        raise NotImplementedError
+
+    def text_mismatch_category(self):
+        raise NotImplementedError
+
+
+class FailureMissingResult(FailureText):
 
     def message(self):
         return '-expected.txt was missing'
 
 
-class FailureTestHarnessAssertion(TestFailure):
+class FailureTextNotGenerated(FailureText):
 
     def message(self):
-        return 'asserts failed'
-
-
-class FailureText(TestFailure):
-
-    def __init__(self, actual_output, expected_output):
-        super(FailureText, self).__init__(actual_output, expected_output)
-        if actual_output:
-            self._repaint_overlay = (
-                repaint_overlay.result_contains_repaint_rects(actual_output.text))
-        if expected_output:
-            self._repaint_overlay |= (
-                repaint_overlay.result_contains_repaint_rects(expected_output.text))
+        return 'test did not generate text results'
 
 
 class FailureTextMismatch(FailureText):
 
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        super(FailureTextMismatch, self).create_artifacts(
+            typ_artifacts, force_overwrite)
+        html = repaint_overlay.generate_repaint_overlay_html(
+            self.test_name, self.actual_driver_output.text,
+            self.expected_driver_output.text)
+        if html:
+            overlay_filename = self.port.output_filename(
+                self.test_name, FILENAME_SUFFIX_OVERLAY, '.html')
+            self._write_to_artifacts(
+                typ_artifacts, 'overlay', overlay_filename, html, force_overwrite)
+
     def message(self):
         return 'text diff'
 
@@ -226,6 +428,12 @@
         return 'general text mismatch'
 
 
+class FailureTestHarnessAssertion(FailureText):
+
+    def message(self):
+        return 'asserts failed'
+
+
 class FailureSpacesAndTabsTextMismatch(FailureTextMismatch):
 
     def message(self):
@@ -253,84 +461,169 @@
         return 'spaces, tabs and newlines only'
 
 
-class FailureMissingImageHash(TestFailure):
+class FailureImage(ActualAndBaselineArtifacts):
+
+    def __init__(self, actual_driver_output, expected_driver_output):
+        super(FailureImage, self).__init__(
+            actual_driver_output, expected_driver_output)
+        self.file_ext = '.png'
+
+    def message(self):
+        raise NotImplementedError
+
+
+class FailureImageHashNotGenerated(FailureImage):
+
+    def message(self):
+        return 'test did not generate image results'
+
+
+class FailureMissingImageHash(FailureImage):
 
     def message(self):
         return '-expected.png was missing an embedded checksum'
 
 
-class FailureMissingImage(TestFailure):
+class FailureMissingImage(FailureImage):
 
     def message(self):
         return '-expected.png was missing'
 
 
-class FailureImageHashMismatch(TestFailure):
-
-    def __init__(self, actual_driver_output, expected_driver_output,
-                 image_diff=None):
-        super(FailureImageHashMismatch, self).__init__(
-              actual_driver_output, expected_driver_output)
-        self.image_diff = image_diff
+class FailureImageHashMismatch(FailureImage):
 
     def message(self):
         return 'image diff'
 
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        # Need this if statement in case the image diff process fails
+        if self.actual_driver_output.image_diff:
+            diff_filename = self.port.output_filename(
+                self.test_name, FILENAME_SUFFIX_DIFF, '.png')
+            diff = self.actual_driver_output.image_diff
+            self._write_to_artifacts(
+                typ_artifacts, 'image_diff', diff_filename, diff, force_overwrite)
+            diffs_html_filename = self.port.output_filename(
+                self.test_name, FILENAME_SUFFIX_DIFFS, '.html')
+            diffs_html = _image_diff_html_template % {
+                'title': self.test_name, 'diff_filename': diff_filename,
+                'prefix': self.port.output_filename(self.test_name, '', '')}
+            self._write_to_artifacts(
+                typ_artifacts, 'pretty_image_diff', diffs_html_filename,
+                diffs_html, force_overwrite)
 
-# TODO(rmhasan): Get rid of this because it is not used?
-class FailureImageHashIncorrect(TestFailure):
-
-    def message(self):
-        return '-expected.png embedded checksum is incorrect'
+        super(FailureImageHashMismatch, self).create_artifacts(
+            typ_artifacts, force_overwrite)
 
 
-class FailureReftest(TestFailure):
+class FailureReftestMixin(object):
+    # This mixin will be used by reftest failure types to create a reference
+    # file artifact along with image mismatch artifacts, actual image output,
+    # reference driver output, and standard error output. The actual reftest
+    # failure types used in single_test_runner.py each have an inheritance list.
+    # The order of this list decides the call order of overridden methods like the
+    # constructor and create_artifacts. For example, FailureReftestMismatch
+    # has FailureReftestMixin followed by FailureImageHashMismatch. So when
+    # create_artifacts is called on that class, FailureReftestMixin's create_artifacts
+    # will be called first and then when that method calls the super class's
+    # create_artifacts, it will call FailureImageHashMismatch's create_artifacts.
 
     def __init__(self, actual_driver_output, expected_driver_output,
                  reference_filename=None):
-        super(FailureReftest, self).__init__(
+        super(FailureReftestMixin, self).__init__(
             actual_driver_output, expected_driver_output)
         self.reference_filename = reference_filename
+        self.reference_file_type = 'reference_file_mismatch'
 
-class FailureReftestMismatch(FailureReftest):
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        super(FailureReftestMixin, self).create_artifacts(
+            typ_artifacts, force_overwrite)
+        sub_dir = typ_artifacts.ArtifactsSubDirectory()
+        artifact_filename = self.filesystem.join(
+            sub_dir, self.filesystem.dirname(self.test_name),
+            self.filesystem.basename(self.reference_filename))
+        artifact_abspath = self.filesystem.join(
+            self.result_directory, artifact_filename)
+        # a reference test may include a page that does not exist in the
+        # web test directory, like about:blank pages
+        if (not self.filesystem.exists(artifact_abspath) and
+                self.filesystem.exists(self.reference_filename)):
+            self.filesystem.maybe_make_directory(
+                self.filesystem.dirname(artifact_abspath))
+            self.filesystem.copyfile(self.reference_filename, artifact_abspath)
+        typ_artifacts.AddArtifact(self.reference_file_type, artifact_filename,
+                                  raise_exception_for_duplicates=False)
+
+    def message(self):
+        raise NotImplementedError
+
+
+class FailureReftestMismatch(FailureReftestMixin, FailureImageHashMismatch):
 
     def message(self):
         return 'reference mismatch'
 
 
-class FailureReftestMismatchDidNotOccur(FailureReftest):
+class FailureReftestMismatchDidNotOccur(FailureReftestMixin, FailureImage):
+
+    def __init__(self, actual_driver_output, expected_driver_output,
+                 reference_filename=None):
+        super(FailureReftestMismatchDidNotOccur, self).__init__(
+            actual_driver_output, expected_driver_output, reference_filename)
+        self.reference_file_type = 'reference_file_match'
 
     def message(self):
         return "reference mismatch didn't happen"
 
 
-class FailureReftestNoImageGenerated(FailureReftest):
+class FailureReftestNoImageGenerated(FailureReftestMixin, FailureImage):
 
     def message(self):
         return "reference test didn't generate pixel results"
 
 
-class FailureReftestNoReferenceImageGenerated(FailureReftest):
+class FailureReftestNoReferenceImageGenerated(FailureReftestMixin, FailureImage):
 
     def message(self):
         return "-expected.html didn't generate pixel results"
 
 
-class FailureMissingAudio(TestFailure):
+class FailureAudio(ActualAndBaselineArtifacts):
+
+    def __init__(self, actual_driver_output, expected_driver_output):
+        super(FailureAudio, self).__init__(
+            actual_driver_output, expected_driver_output)
+        self.file_ext = '.wav'
+
+    def message(self):
+        raise NotImplementedError
+
+
+class FailureMissingAudio(FailureAudio):
 
     def message(self):
         return 'expected audio result was missing'
 
 
-class FailureAudioMismatch(TestFailure):
+class FailureAudioMismatch(FailureAudio):
 
     def message(self):
         return 'audio mismatch'
 
 
+class FailureAudioNotGenerated(FailureAudio):
+
+    def message(self):
+        return 'audio result not generated'
+
+
 class FailureEarlyExit(TestFailure):
-    def __init__(self, actual_output=None, expected_output=None):
-        super(FailureEarlyExit, self).__init__(actual_output, expected_output)
+    def __init__(self, actual_driver_output=None, expected_driver_output=None):
+        super(FailureEarlyExit, self).__init__(
+            actual_driver_output, expected_driver_output)
+
+    def create_artifacts(self, typ_artifacts, force_overwrite=False):
+        pass
 
     def message(self):
         return 'skipped due to early exit'
@@ -344,9 +637,10 @@
                        FailureLineBreaksTextMismatch, FailureSpaceTabLineBreakTextMismatch,
                        FailureMissingImageHash,
                        FailureMissingImage, FailureImageHashMismatch,
-                       FailureImageHashIncorrect, FailureReftestMismatch,
+                       FailureReftestMismatch,
                        FailureReftestMismatchDidNotOccur,
                        FailureReftestNoImageGenerated,
                        FailureReftestNoReferenceImageGenerated,
                        FailureMissingAudio, FailureAudioMismatch,
-                       FailureEarlyExit)
+                       FailureEarlyExit, FailureImageHashNotGenerated,
+                       FailureTextNotGenerated, FailureAudioNotGenerated)
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_input.py b/third_party/blink/tools/blinkpy/web_tests/models/test_input.py
index bf8af191..cfec6f8 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_input.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_input.py
@@ -31,7 +31,8 @@
 class TestInput(object):
     """Groups information about a test for easy passing of data."""
 
-    def __init__(self, test_name, timeout_ms=None, requires_lock=None, reference_files=None):
+    def __init__(self, test_name, timeout_ms=None, requires_lock=None,
+                 reference_files=None, retry_attempt=0, requires_force_overwrite=False):
         # TestInput objects are normally constructed by the manager and passed
         # to the workers, but these some fields are set lazily in the workers
         # where possible, because they require us to look at the filesystem,
@@ -40,11 +41,15 @@
         self.timeout_ms = timeout_ms
         self.requires_lock = requires_lock
         self.reference_files = reference_files
+        self.retry_attempt = retry_attempt
+        self.requires_force_overwrite = requires_force_overwrite
 
     def __repr__(self):
         return (
-            "TestInput('%s', timeout_ms=%s, requires_lock=%s, reference_files=%s)" % (
+            "TestInput('%s', timeout_ms=%s, requires_lock=%s, reference_files=%s, retry_attempt=%d, requires_force_overwrite=%s)" % (
                 self.test_name,
                 self.timeout_ms,
                 self.requires_lock,
-                self.reference_files))
+                self.reference_files,
+                self.retry_attempt,
+                self.requires_force_overwrite))
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_results.py b/third_party/blink/tools/blinkpy/web_tests/models/test_results.py
index 06327c2..9eb8895 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_results.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_results.py
@@ -30,15 +30,38 @@
 
 from blinkpy.web_tests.models import test_failures
 
+from blinkpy.common import path_finder
+
+path_finder.add_typ_dir_to_sys_path()
+
+from typ.artifacts import Artifacts
+
+def build_test_result(
+    driver_output, test_name, retry_attempt=0,
+        failures=None, test_run_time=None, reftest_type=None,
+        pid=None, references=None, device_failed=False, crash_site=None):
+    failures = failures or []
+    if not failures and driver_output.error:
+        failures.append(test_failures.PassWithStderr(driver_output))
+    return TestResult(
+        test_name, retry_attempt=retry_attempt,
+        failures=failures, test_run_time=test_run_time,
+        reftest_type=reftest_type, pid=pid, references=references,
+        device_failed=device_failed, crash_site=crash_site)
+
 
 class TestResult(object):
     """Data object containing the results of a single test."""
+    repeat_tests = True
+    results_directory = ''
+    filesystem = None
 
     @staticmethod
     def loads(string):
         return cPickle.loads(string)
 
-    def __init__(self, test_name, failures=None, test_run_time=None, reftest_type=None,
+    def __init__(self, test_name, retry_attempt=0,  failures=None,
+                 test_run_time=None, reftest_type=None,
                  pid=None, references=None, device_failed=False, crash_site=None):
         self.test_name = test_name
         self.failures = failures or []
@@ -51,7 +74,7 @@
         self.has_repaint_overlay = any(
             failure.has_repaint_overlay for failure in self.failures)
         self.crash_site = crash_site
-
+        self.retry_attempt = retry_attempt
         # FIXME: Setting this in the constructor makes this class hard to mutate.
         self.type = test_failures.determine_result_type(failures)
 
@@ -60,11 +83,20 @@
         self.shard_name = ''
         self.total_run_time = 0  # The time taken to run the test plus any references, compute diffs, etc.
         self.test_number = None
+        self.artifacts = Artifacts(
+            self.results_directory, self.filesystem, retry_attempt,
+            repeat_tests=self.repeat_tests)
+
+    def create_artifacts(self):
+        for failure in self.failures:
+            failure.create_artifacts(self.artifacts)
 
     def __eq__(self, other):
         return (self.test_name == other.test_name and
                 self.failures == other.failures and
-                self.test_run_time == other.test_run_time)
+                self.test_run_time == other.test_run_time and
+                self.retry_attempt == other.retry_attempt and
+                self.results_directory == other.results_directory)
 
     def __ne__(self, other):
         return not (self == other)
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py b/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py
index 9ad7bcc..1bec908 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py
@@ -337,6 +337,11 @@
             if is_unexpected:
                 test_dict.update(_interpret_test_failures(retry_result.failures))
 
+        for test_result, _ in merged_results:
+            for artifact_name, artifacts in test_result.artifacts.artifacts.items():
+                artifact_dict = test_dict.setdefault('artifacts', {})
+                artifact_dict.setdefault(artifact_name, []).extend(artifacts)
+
         # Store test hierarchically by directory. e.g.
         # foo/bar/baz.html: test_dict
         # foo/bar/baz1.html: test_dict
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py b/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py
index b4d8d0f..c7b4805 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py
@@ -37,18 +37,19 @@
 
 def get_result(test_name, result_type=test_expectations.PASS, run_time=0):
     failures = []
+    dummy_1, dummy_2 = DriverOutput(None, None, None, None), DriverOutput(None, None, None, None)
     if result_type == test_expectations.TIMEOUT:
-        failures = [test_failures.FailureTimeout(None, None)]
+        failures = [test_failures.FailureTimeout(dummy_1)]
     elif result_type == test_expectations.AUDIO:
-        failures = [test_failures.FailureAudioMismatch(None, None)]
+        failures = [test_failures.FailureAudioMismatch(dummy_1, dummy_2)]
     elif result_type == test_expectations.TEXT:
-        failures = [test_failures.FailureTextMismatch(None, None)]
+        failures = [test_failures.FailureTextMismatch(dummy_1, dummy_2)]
     elif result_type == test_expectations.IMAGE:
-        failures = [test_failures.FailureImageHashMismatch(None, None)]
+        failures = [test_failures.FailureImageHashMismatch(dummy_1, dummy_2)]
     elif result_type == test_expectations.CRASH:
-        failures = [test_failures.FailureCrash(None, None)]
+        failures = [test_failures.FailureCrash(dummy_1)]
     elif result_type == test_expectations.LEAK:
-        failures = [test_failures.FailureLeak(None, None)]
+        failures = [test_failures.FailureLeak(dummy_1)]
     return test_results.TestResult(test_name, failures=failures, test_run_time=run_time)
 
 
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver.py b/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver.py
index 4cdaa78..505af53 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver.py
@@ -79,7 +79,7 @@
         cmd.append(self._port._path_to_driver())
         cmd.append('--gtest_filter=PrintPreviewPdfGeneratedBrowserTest.MANUAL_LayoutTestDriver')
         cmd.append('--run-manual')
-        cmd.append('--single_process')
+        cmd.append('--single-process-tests')
         cmd.extend(per_test_args)
         cmd.extend(self._port.get_option('additional_driver_flag', []))
         return cmd
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/test.py b/third_party/blink/tools/blinkpy/web_tests/port/test.py
index 2fa55f6..fdcc94f 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/test.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/test.py
@@ -95,10 +95,10 @@
                  actual_text=None, expected_text=None, expected_image=None)
 
     def add_reftest(self, name, reference_name, same_image=True,
-                    actual_text=None, expected_text=None, crash=False):
+                    actual_text=None, expected_text=None, crash=False, error=''):
         self.add(name, actual_checksum='checksum', actual_image='IMAGE', expected_image=None,
                  actual_text=actual_text, expected_text=expected_text,
-                 crash=crash)
+                 crash=crash, error=error)
         if same_image:
             self.add_reference(reference_name)
         else:
@@ -116,14 +116,14 @@
 #
 # These numbers may need to be updated whenever we add or delete tests. This includes virtual tests.
 #
-TOTAL_TESTS = 127
+TOTAL_TESTS = 151
 TOTAL_WONTFIX = 3
 TOTAL_SKIPS = 20 + TOTAL_WONTFIX
-TOTAL_CRASHES = 76
+TOTAL_CRASHES = 78
 
 UNEXPECTED_PASSES = 1
-UNEXPECTED_NON_VIRTUAL_FAILURES = 21
-UNEXPECTED_FAILURES = 44
+UNEXPECTED_NON_VIRTUAL_FAILURES = 33
+UNEXPECTED_FAILURES = 65
 
 
 def unit_test_list():
@@ -144,6 +144,37 @@
               actual_text=None, expected_text=None,
               actual_image=None, expected_image=None,
               actual_checksum=None)
+    tests.add('failures/unexpected/image-mismatch.html',
+              actual_image='image_fail-pngtEXtchecksum\x00checksum_fail',
+              expected_image='image-pngtEXtchecksum\x00checksum-png')
+    tests.add('failures/unexpected/no-image-generated.html',
+              expected_image='image-pngtEXtchecksum\x00checksum-png',
+              actual_image=None, actual_checksum=None)
+    tests.add('failures/unexpected/no-image-baseline.html',
+              actual_image='image_fail-pngtEXtchecksum\x00checksum_fail',
+              expected_image=None)
+    tests.add('failures/unexpected/audio-mismatch.html',
+              actual_audio=base64.b64encode('audio_fail-wav'), expected_audio='audio-wav',
+              actual_text=None, expected_text=None,
+              actual_image=None, expected_image=None,
+              actual_checksum=None)
+    tests.add('failures/unexpected/no-audio-baseline.html',
+              actual_audio=base64.b64encode('audio_fail-wav'),
+              actual_text=None, expected_text=None,
+              actual_image=None, expected_image=None,
+              actual_checksum=None)
+    tests.add('failures/unexpected/no-audio-generated.html',
+              expected_audio=base64.b64encode('audio_fail-wav'),
+              actual_text=None, expected_text=None,
+              actual_image=None, expected_image=None,
+              actual_checksum=None)
+    tests.add('failures/unexpected/text-mismatch-overlay.html',
+              actual_text='"paintInvalidations": [\nfail',
+              expected_text='"paintInvalidations": [\npass')
+    tests.add('failures/unexpected/no-text-baseline.html',
+              actual_text='"paintInvalidations": [\nfail', expected_text=None)
+    tests.add('failures/unexpected/no-text-generated.html',
+              actual_text=None, expected_text='"paintInvalidations": [\npass')
     tests.add('failures/expected/keyboard.html', keyboard=True)
     tests.add('failures/expected/newlines_leading.html',
               expected_text='\nfoo\n', actual_text='foo\n')
@@ -167,6 +198,8 @@
         text run at (0,0) width 133: "This is an image test!"
 """, expected_text=None)
     tests.add('failures/unexpected/crash.html', crash=True)
+    tests.add('failures/unexpected/crash-with-sample.html', crash=True)
+    tests.add('failures/unexpected/crash-with-delayed-log.html', crash=True)
     tests.add('failures/unexpected/crash-with-stderr.html', crash=True,
               error='mock-std-error-output')
     tests.add('failures/unexpected/web-process-crash-with-stderr.html', web_process_crash=True,
@@ -238,6 +271,9 @@
     tests.add_reftest('failures/expected/mismatch.html', 'failures/expected/mismatch-expected-mismatch.html')
     tests.add_reftest('failures/unexpected/crash-reftest.html', 'failures/unexpected/crash-reftest-expected.html', crash=True)
     tests.add_reftest('failures/unexpected/reftest.html', 'failures/unexpected/reftest-expected.html', same_image=False)
+    tests.add_reftest('failures/unexpected/reftest-mismatch-with-text-mismatch-with-stderr.html',
+                      'failures/unexpected/reftest-mismatch-with-text-mismatch-with-stderr-expected.html',
+                      same_image=False, actual_text='actual', expected_text='expected', error='oops')
     tests.add_reftest('failures/unexpected/mismatch.html', 'failures/unexpected/mismatch-expected-mismatch.html')
     tests.add('failures/unexpected/reftest-nopixel.html', actual_checksum=None, actual_image=None, expected_image=None)
     tests.add('failures/unexpected/reftest-nopixel-expected.html', actual_checksum=None, actual_image=None)
@@ -419,6 +455,26 @@
             'linux': ['precise', 'trusty']
         }
 
+    def look_for_new_samples(self, crashed_processes, start_time):
+        del start_time
+        sample_files = {}
+        for cp in crashed_processes:
+            if cp[0].endswith('crash-with-sample.html'):
+                sample_file = cp[0].replace('.html', '_sample.txt')
+                self._filesystem.maybe_make_directory(
+                    self._filesystem.dirname(sample_file))
+                self._filesystem.write_binary_file(sample_file, 'crash sample file')
+                sample_files[cp[0]] = sample_file
+        return sample_files
+
+    def look_for_new_crash_logs(self, crashed_processes, start_time):
+        del start_time
+        crash_logs = {}
+        for cp in crashed_processes:
+            if cp[0].endswith('-with-delayed-log.html'):
+                crash_logs[cp[0]] = ('delayed crash log', '/tmp')
+        return crash_logs
+
     def _path_to_driver(self, target=None):
         # This routine shouldn't normally be called, but it is called by
         # the mock_drt Driver. We return something, but make sure it's useless.
@@ -560,6 +616,7 @@
         actual_text = test.actual_text
         crash = test.crash
         web_process_crash = test.web_process_crash
+        leak = test.leak
 
         if 'flaky/text.html' in test_name and not test_name in self._port._flakes:
             self._port._flakes.add(test_name)
@@ -590,24 +647,30 @@
             audio = base64.b64decode(test.actual_audio)
         crashed_process_name = None
         crashed_pid = None
+
+        leak_log = ''
+        if leak:
+            leak_log = 'leak detected'
+
+        crash_log = ''
         if crash:
             crashed_process_name = self._port.driver_name()
             crashed_pid = 1
+            crash_log = 'crash log'
         elif web_process_crash:
             crashed_process_name = 'WebProcess'
             crashed_pid = 2
+            crash_log = 'web process crash log'
 
-        crash_log = ''
         if crashed_process_name:
             crash_logs = CrashLogs(self._port.host)
-            crash_log = crash_logs.find_newest_log(crashed_process_name, None) or ''
+            crash_log = crash_logs.find_newest_log(crashed_process_name, None) or crash_log
 
         if 'crash-reftest.html' in test_name:
             crashed_process_name = self._port.driver_name()
             crashed_pid = 3
             crash = True
             crash_log = 'reftest crash log'
-
         if test.actual_checksum == driver_input.image_hash:
             image = None
         else:
@@ -616,7 +679,7 @@
                             crash=(crash or web_process_crash), crashed_process_name=crashed_process_name,
                             crashed_pid=crashed_pid, crash_log=crash_log,
                             test_time=time.time() - start_time, timeout=test.timeout, error=test.error, pid=self.pid,
-                            leak=test.leak)
+                            leak=test.leak, leak_log=leak_log)
 
     def stop(self, timeout_secs=0.0):
         self.started = False
diff --git a/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py b/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py
index 2244f962..90df72d 100644
--- a/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py
@@ -485,15 +485,127 @@
     def test_stderr_is_saved(self):
         host = MockHost()
         self.assertTrue(passing_run(host=host))
-        self.assertEqual(host.filesystem.read_text_file('/tmp/layout-test-results/passes/error-stderr.txt'),
-                         'stuff going to stderr')
+        self.assertEqual(
+            host.filesystem.read_text_file('/tmp/layout-test-results/passes/error-stderr.txt'),
+            'stuff going to stderr')
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['passes']['error.html']
+        self.assertEqual(test_results['artifacts']['stderr'], ['passes/error-stderr.txt'])
+
+    def test_crash_log_is_saved(self):
+        host = MockHost()
+        self.assertTrue(logging_run(
+            ['--order', 'natural', 'failures/unexpected/crash.html', '--num-retries', '1'],
+            tests_included=True, host=host))
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        self.assertEqual(
+            host.filesystem.read_text_file(
+                '/tmp/layout-test-results/failures/unexpected/crash-crash-log.txt'),
+                'crash log')
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['crash.html']
+        self.assertEqual(test_results['artifacts']['crash_log'], [
+            'failures/unexpected/crash-crash-log.txt',
+            'retry_1/failures/unexpected/crash-crash-log.txt'])
+
+    def test_crash_log_is_saved_after_delay(self):
+        host = MockHost()
+        self.assertTrue(logging_run(
+            ['--order', 'natural', 'failures/unexpected/crash-with-delayed-log.html',
+            '--num-retries', '1'],
+            tests_included=True, host=host))
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        self.assertEqual(
+            host.filesystem.read_text_file(
+                '/tmp/layout-test-results/failures/unexpected/crash-with-delayed-log-crash-log.txt'),
+                'delayed crash log')
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['crash-with-delayed-log.html']
+        self.assertEqual(test_results['artifacts']['crash_log'], [
+            'failures/unexpected/crash-with-delayed-log-crash-log.txt',
+            'retry_1/failures/unexpected/crash-with-delayed-log-crash-log.txt'])
+
+    def test_reftest_mismatch_with_text_mismatch_only_writes_stderr_once(self):
+        # test that there is no exception when two failure types, FailureTextMismatch and
+        # FailureReftestMismatch both have the same stderr to print out.
+        host = MockHost()
+        self.assertTrue(logging_run(
+            ['--order', 'natural', 'failures/unexpected/reftest-mismatch-with-text-mismatch-with-stderr.html',],
+            tests_included=True, host=host))
+
+    def test_crash_log_is_saved_after_delay_using_multiple_jobs(self):
+        # TODO(rmhasan): When web_test_runner.run() spawns multiple jobs it uses
+        # the non mock file system. We should figure out how to make all subprocesses
+        # use the mock file system.
+        host = MockHost()
+        self.assertTrue(logging_run(
+            ['--order', 'natural', 'failures/unexpected/crash-with-delayed-log.html',
+            'passes/args.html', '-j', '2'],
+            tests_included=True, host=host))
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['crash-with-delayed-log.html']
+        self.assertEqual(test_results['artifacts']['crash_log'], [
+            'failures/unexpected/crash-with-delayed-log-crash-log.txt'])
+
+    def test_crash_sample_file_is_saved(self):
+        host = MockHost()
+        self.assertTrue(logging_run(
+            ['--order', 'natural', 'failures/unexpected/crash-with-sample.html',
+             '--num-retries', '1'],
+            tests_included=True, host=host))
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        self.assertEqual(
+            host.filesystem.read_text_file(
+                '/tmp/layout-test-results/failures/unexpected/crash-with-sample-sample.txt'),
+                'crash sample file')
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['crash-with-sample.html']
+        self.assertEqual(test_results['artifacts']['sample_file'], [
+            'failures/unexpected/crash-with-sample-sample.txt',
+            'retry_1/failures/unexpected/crash-with-sample-sample.txt'])
+
+    def test_crash_sample_file_is_saved_multiple_jobs(self):
+        host = MockHost()
+        self.assertTrue(logging_run(
+            ['--order', 'natural', 'failures/unexpected/crash-with-sample.html',
+             'passes/image.html', '--num-retries', '1', '-j', '2'],
+            tests_included=True, host=host))
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['crash-with-sample.html']
+        self.assertEqual(test_results['artifacts']['sample_file'], [
+            'failures/unexpected/crash-with-sample-sample.txt',
+            'retry_1/failures/unexpected/crash-with-sample-sample.txt'])
 
     def test_reftest_crash_log_is_saved(self):
         host = MockHost()
-        self.assertTrue(logging_run(['--order', 'natural', 'failures/unexpected/crash-reftest.html'],
-                                    tests_included=True, host=host))
-        self.assertEqual(host.filesystem.read_text_file('/tmp/layout-test-results/failures/unexpected/crash-reftest-crash-log.txt'),
-                         'reftest crash log')
+        self.assertTrue(logging_run(
+            ['--order', 'natural', 'failures/unexpected/crash-reftest.html', '--num-retries', '1'],
+            tests_included=True, host=host))
+        self.assertEqual(
+            host.filesystem.read_text_file(
+                '/tmp/layout-test-results/failures/unexpected/crash-reftest-crash-log.txt'),
+            'reftest crash log')
+        self.assertEqual(
+            host.filesystem.read_text_file(
+                '/tmp/layout-test-results/retry_1/failures/unexpected/crash-reftest-crash-log.txt'),
+            'reftest crash log')
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['crash-reftest.html']
+        self.assertEqual(test_results['artifacts']['crash_log'], [
+            'failures/unexpected/crash-reftest-crash-log.txt',
+            'retry_1/failures/unexpected/crash-reftest-crash-log.txt'])
 
     def test_test_list(self):
         host = MockHost()
@@ -528,17 +640,17 @@
         self.assertEqual(sorted(tests_run), ['passes/error.html'])
 
         tests_run = get_tests_run(
-            ['--isolated-script-test-filter=passes/error.html::passes/image.html'],
+            ['--isolated-script-test-filter=-passes/error.html::passes/image.html'],
             host=host
         )
-        self.assertEqual(sorted(tests_run), ['passes/error.html', 'passes/image.html'])
+        self.assertEqual(sorted(tests_run), ['passes/image.html'])
 
         tests_run = get_tests_run(
             ['--isolated-script-test-filter=passes/error.html::passes/image.html',
-             '--isolated-script-test-filter=passes/error.html'],
+             '--isolated-script-test-filter=-passes/error.html'],
             host=host
         )
-        self.assertEqual(sorted(tests_run), ['passes/error.html'])
+        self.assertEqual(sorted(tests_run), ['passes/image.html'])
 
     def test_gtest_filter(self):
         host = MockHost()
@@ -623,8 +735,9 @@
         self.assertEqual(['passes/text.html'], tests_run)
 
         # Verify that --no-smoke continues to work on a smoke-by-default port.
-        tests_run = get_tests_run(['--no-smoke', '--order', 'natural'], host=host, port_obj=port_obj)
-        self.assertNotEqual(['passes/text.html'], tests_run)
+        tests_run = get_tests_run(['--no-smoke', 'passes/image.html', '--order', 'natural'],
+                                  host=host, port_obj=port_obj)
+        self.assertNotIn('passes/text.html', tests_run)
 
     def test_smoke_test_default_retry(self):
         host = MockHost()
@@ -632,10 +745,6 @@
         host.filesystem.write_text_file(
             smoke_test_filename, 'failures/unexpected/text-image-checksum.html\n')
 
-        # Retry smoke tests by default.
-        _, err, __ = logging_run(['--smoke'], host=host, tests_included=True)
-        self.assertIn('Retrying', err.getvalue())
-
         # Retry if additional tests are given.
         _, err, __ = logging_run(['--smoke', 'passes/image.html'], host=host, tests_included=True)
         self.assertIn('Retrying', err.getvalue())
@@ -650,6 +759,7 @@
                                     tests_included=True, host=host)
         self.assertEqual(details.exit_code, 2)
         results = json.loads(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        results['tests']['failures']['unexpected']['text-image-checksum.html'].pop('artifacts')
         self.assertEqual(
             results['tests']['failures']['unexpected']['text-image-checksum.html'],
             {
@@ -659,6 +769,7 @@
                 'is_regression': True,
                 'text_mismatch': 'general text mismatch',
             })
+        results['tests']['failures']['unexpected']['missing_text.html'].pop('artifacts')
         self.assertEqual(
             results['tests']['failures']['unexpected']['missing_text.html'],
             {
@@ -845,9 +956,221 @@
 
     def test_retrying_leak_tests(self):
         host = MockHost()
-        details, err, _ = logging_run(['--num-retries=3', 'failures/unexpected/leak.html'], tests_included=True, host=host)
+        details, err, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/leak.html'],
+            tests_included=True, host=host)
         self.assertEqual(details.exit_code, 1)
         self.assertIn('Retrying', err.getvalue())
+        self.assertEqual(host.filesystem.read_text_file(
+            '/tmp/layout-test-results/failures/unexpected/leak-leak-log.txt'),
+            'leak detected')
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['leak.html']
+        self.assertEqual(test_results['artifacts']['leak_log'], [
+            'failures/unexpected/leak-leak-log.txt',
+            'retry_1/failures/unexpected/leak-leak-log.txt'])
+
+    def test_unexpected_text_mismatch(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/text-mismatch-overlay.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['text-mismatch-overlay.html']
+        self.assertEqual(test_results['artifacts']['actual_text'], [
+            'failures/unexpected/text-mismatch-overlay-actual.txt',
+            'retry_1/failures/unexpected/text-mismatch-overlay-actual.txt'])
+        self.assertEqual(test_results['artifacts']['expected_text'], [
+            'failures/unexpected/text-mismatch-overlay-expected.txt',
+            'retry_1/failures/unexpected/text-mismatch-overlay-expected.txt'])
+        self.assertEqual(test_results['artifacts']['text_diff'], [
+            'failures/unexpected/text-mismatch-overlay-diff.txt',
+            'retry_1/failures/unexpected/text-mismatch-overlay-diff.txt'])
+        self.assertEqual(test_results['artifacts']['pretty_text_diff'], [
+            'failures/unexpected/text-mismatch-overlay-pretty-diff.html',
+            'retry_1/failures/unexpected/text-mismatch-overlay-pretty-diff.html'])
+        self.assertEqual(test_results['artifacts']['overlay'], [
+            'failures/unexpected/text-mismatch-overlay-overlay.html',
+            'retry_1/failures/unexpected/text-mismatch-overlay-overlay.html'])
+
+    def test_unexpected_no_text_baseline(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/no-text-baseline.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['no-text-baseline.html']
+        self.assertEqual(test_results['artifacts']['actual_text'], [
+            'failures/unexpected/no-text-baseline-actual.txt',
+            'retry_1/failures/unexpected/no-text-baseline-actual.txt'])
+        self.assertNotIn('expected_text', test_results['artifacts'])
+        self.assertEqual(test_results['artifacts']['text_diff'], [
+            'failures/unexpected/no-text-baseline-diff.txt',
+            'retry_1/failures/unexpected/no-text-baseline-diff.txt'])
+        self.assertEqual(test_results['artifacts']['pretty_text_diff'], [
+            'failures/unexpected/no-text-baseline-pretty-diff.html',
+            'retry_1/failures/unexpected/no-text-baseline-pretty-diff.html'])
+        self.assertNotIn('overlay', test_results['artifacts'])
+
+    def test_unexpected_no_text_generated(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/no-text-generated.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['no-text-generated.html']
+        self.assertEqual(test_results['artifacts']['expected_text'], [
+            'failures/unexpected/no-text-generated-expected.txt',
+            'retry_1/failures/unexpected/no-text-generated-expected.txt'])
+        self.assertNotIn('actual_text', test_results['artifacts'])
+        self.assertEqual(test_results['artifacts']['text_diff'], [
+            'failures/unexpected/no-text-generated-diff.txt',
+            'retry_1/failures/unexpected/no-text-generated-diff.txt'])
+        self.assertEqual(test_results['artifacts']['pretty_text_diff'], [
+            'failures/unexpected/no-text-generated-pretty-diff.html',
+            'retry_1/failures/unexpected/no-text-generated-pretty-diff.html'])
+        self.assertNotIn('overlay', test_results['artifacts'])
+
+    def test_reftest_mismatching_image(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/reftest.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['reftest.html']
+        self.assertEqual(test_results['artifacts']['actual_image'], [
+            'failures/unexpected/reftest-actual.png',
+            'retry_1/failures/unexpected/reftest-actual.png'])
+        self.assertEqual(test_results['artifacts']['expected_image'], [
+            'failures/unexpected/reftest-expected.png',
+            'retry_1/failures/unexpected/reftest-expected.png'])
+        self.assertEqual(test_results['artifacts']['image_diff'], [
+            'failures/unexpected/reftest-diff.png',
+            'retry_1/failures/unexpected/reftest-diff.png'])
+        self.assertEqual(test_results['artifacts']['pretty_image_diff'], [
+            'failures/unexpected/reftest-diffs.html',
+            'retry_1/failures/unexpected/reftest-diffs.html'])
+        self.assertEqual(test_results['artifacts']['reference_file_mismatch'],  [
+            'failures/unexpected/reftest-expected.html',
+            'retry_1/failures/unexpected/reftest-expected.html'])
+
+    def test_reftest_failure_matching_image(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['failures/unexpected/mismatch.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['mismatch.html']
+        self.assertIn('reference_file_match', test_results['artifacts'])
+        self.assertEqual(test_results['artifacts']['reference_file_match'],
+                         ['failures/unexpected/mismatch-expected-mismatch.html'])
+
+    def test_unexpected_image_mismatch(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/image-mismatch.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['image-mismatch.html']
+        self.assertEqual(test_results['artifacts']['actual_image'], [
+            'failures/unexpected/image-mismatch-actual.png',
+            'retry_1/failures/unexpected/image-mismatch-actual.png'])
+        self.assertEqual(test_results['artifacts']['expected_image'], [
+            'failures/unexpected/image-mismatch-expected.png',
+            'retry_1/failures/unexpected/image-mismatch-expected.png'])
+        self.assertEqual(test_results['artifacts']['image_diff'], [
+            'failures/unexpected/image-mismatch-diff.png',
+            'retry_1/failures/unexpected/image-mismatch-diff.png'])
+        self.assertEqual(test_results['artifacts']['pretty_image_diff'], [
+            'failures/unexpected/image-mismatch-diffs.html',
+            'retry_1/failures/unexpected/image-mismatch-diffs.html'])
+
+    def test_unexpected_no_image_generated(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/no-image-generated.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['no-image-generated.html']
+        self.assertNotIn('actual_image', test_results['artifacts'])
+        self.assertEqual(test_results['artifacts']['expected_image'], [
+            'failures/unexpected/no-image-generated-expected.png',
+            'retry_1/failures/unexpected/no-image-generated-expected.png'])
+        self.assertNotIn('image_diff', test_results['artifacts'])
+        self.assertNotIn('pretty_image_diff', test_results['artifacts'])
+
+    def test_unexpected_no_image_baseline(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/no-image-baseline.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['no-image-baseline.html']
+        self.assertNotIn('expected_image', test_results['artifacts'])
+        self.assertEqual(test_results['artifacts']['actual_image'], [
+            'failures/unexpected/no-image-baseline-actual.png',
+            'retry_1/failures/unexpected/no-image-baseline-actual.png'])
+        self.assertNotIn('image_diff', test_results['artifacts'])
+        self.assertNotIn('pretty_image_diff', test_results['artifacts'])
+
+    def test_unexpected_audio_mismatch(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/audio-mismatch.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['audio-mismatch.html']
+        self.assertEqual(test_results['artifacts']['actual_audio'], [
+            'failures/unexpected/audio-mismatch-actual.wav',
+            'retry_1/failures/unexpected/audio-mismatch-actual.wav'])
+        self.assertEqual(test_results['artifacts']['expected_audio'], [
+            'failures/unexpected/audio-mismatch-expected.wav',
+            'retry_1/failures/unexpected/audio-mismatch-expected.wav'])
+
+    def test_unexpected_audio_missing_baseline(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/no-audio-baseline.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['no-audio-baseline.html']
+        self.assertEqual(test_results['artifacts']['actual_audio'], [
+            'failures/unexpected/no-audio-baseline-actual.wav',
+            'retry_1/failures/unexpected/no-audio-baseline-actual.wav'])
+
+    def test_unexpected_no_audio_generated(self):
+        host = MockHost()
+        details, _, _ = logging_run(
+            ['--num-retries=1', 'failures/unexpected/no-audio-generated.html'],
+            tests_included=True, host=host)
+        self.assertEqual(details.exit_code, 1)
+        results = json.loads(
+            host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        test_results = results['tests']['failures']['unexpected']['no-audio-generated.html']
+        self.assertEqual(test_results['artifacts']['expected_audio'], [
+            'failures/unexpected/no-audio-generated-expected.wav',
+            'retry_1/failures/unexpected/no-audio-generated-expected.wav'])
 
     def test_retrying_uses_retry_directories(self):
         host = MockHost()
@@ -1009,8 +1332,8 @@
         test_result = run_details.initial_results.all_results[0]
         self.assertEqual(test_result.test_name, test_name)
         self.assertEqual(len(test_result.failures), 2)
-        self.assertTrue(test_failures.has_failure_type(test_failures.FailureTextMismatch, test_result.failures))
-        self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioMismatch, test_result.failures))
+        self.assertTrue(test_failures.has_failure_type(test_failures.FailureTextNotGenerated, test_result.failures))
+        self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioNotGenerated, test_result.failures))
         self.assert_contains(log_stream, 'Please remove %s' % extra_txt)
         self.assert_contains(log_stream, 'Please remove %s' % extra_wav)
 
@@ -1042,7 +1365,7 @@
         test_result = run_details.initial_results.all_results[0]
         self.assertEqual(test_result.test_name, test_name)
         self.assertEqual(len(test_result.failures), 1)
-        self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioMismatch, test_result.failures))
+        self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioNotGenerated, test_result.failures))
         # For now extra png baseline is only reported in an error message.
         self.assert_contains(log_stream, 'Please remove %s' % extra_png)
         self.assert_contains(log_stream, 'Please remove %s' % extra_wav)
@@ -1060,7 +1383,7 @@
         test_result = run_details.initial_results.all_results[0]
         self.assertEqual(test_result.test_name, test_name)
         self.assertEqual(len(test_result.failures), 1)
-        self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioMismatch, test_result.failures))
+        self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioNotGenerated, test_result.failures))
         # For now extra png baseline is only reported in an error message.
         self.assert_contains(log_stream, 'Please remove %s' % extra_png)
         self.assert_contains(log_stream, 'Please remove %s' % extra_wav)
@@ -1092,8 +1415,8 @@
         test_result = run_details.initial_results.all_results[0]
         self.assertEqual(test_result.test_name, test_name)
         self.assertEqual(len(test_result.failures), 2)
-        self.assertTrue(test_failures.has_failure_type(test_failures.FailureImageHashMismatch, test_result.failures))
-        self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioMismatch, test_result.failures))
+        self.assertTrue(test_failures.has_failure_type(test_failures.FailureImageHashNotGenerated, test_result.failures))
+        self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioNotGenerated, test_result.failures))
         # For now extra txt baseline for all-pass testharness test is only reported in an error message.
         self.assert_contains(log_stream, 'Please remove %s' % extra_png)
         self.assert_contains(log_stream, 'Please remove %s' % extra_txt)
@@ -1238,7 +1561,6 @@
         self.assertEqual(json.loads(json_failing_test_results), details.summarized_failing_results)
 
     def test_no_default_expectations(self):
-        self.assertTrue(passing_run(['failures/expected/text.html']))
         self.assertFalse(passing_run(['--ignore-default-expectations', 'failures/expected/text.html']))
 
 
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
index a7b1b4b..3d4ef10 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -16,6 +16,9 @@
 Bug(none) virtual/threaded/printing/ [ Skip ]
 Bug(none) virtual/threaded/http/tests/devtools/tracing/ [ Skip ]
 
+# Filenames are too long on Windows.
+Bug(1014132) virtual/controls-refresh-high-contrast/ [ Skip ]
+
 # Fail before CompositeAfterPaint but pass with it.
 crbug.com/472330 fast/borders/border-image-outset-split-inline-vertical-lr.html [ Pass ]
 crbug.com/736052 compositing/overflow/composited-scroll-with-fractional-translation.html [ Pass ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index e457cdc..192cde9 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -1345,8 +1345,26 @@
 
 # 'writing-mode: sideways-lr' and 'sideways-rl' are not implemented.
 # Note other tests for these properties are skipped in W3CImportExpectations.
-external/wpt/css/css-writing-modes/slr-alongside-vlr-floats.html [ WontFix ]
-external/wpt/css/css-writing-modes/srl-alongside-vrl-floats.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/slr-alongside-vlr-floats.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/srl-alongside-vrl-floats.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-034.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-035.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-038.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-039.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-042.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-043.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-046.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-047.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-048.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-049.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-050.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-051.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-052.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-053.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-054.html [ WontFix ]
+crbug.com/680331 external/wpt/css/css-writing-modes/wm-propagation-body-055.html [ WontFix ]
+crbug.com/680331 external/wpt/css/cssom-view/scrollIntoView-sideways-lr-writing-mode-and-rtl-direction.html [ WontFix ]
+crbug.com/680331 external/wpt/css/cssom-view/scrollIntoView-sideways-rl-writing-mode-and-rtl-direction.html [ WontFix ]
 
 # Requires --use-fake-ui-for-media-stream to run.
 external/wpt/mediacapture-streams/MediaStream-default-feature-policy.https.html [ WontFix ]
@@ -2056,10 +2074,6 @@
 external/wpt/uievents/order-of-events/mouse-events/wheel-scrolling-manual.html [ WontFix ]
 external/wpt/html/webappapis/user-prompts/print-manual.html [ WontFix ]
 
-# WebGPU tests are only run on GPU bots, so they are skipped by default and run
-# separately from other Web Tests.
-external/wpt/webgpu/ [ WontFix ]
-
 # Tests that do not pass with the Blink CORS, but pass with OOR-CORS.
 # We maintain the Blink CORS for a while, and keep it work without regressions.
 # But will not change the existing behavior for Blink CORS when expectations are
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index f777448..42fa21e 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -351,6 +351,10 @@
 crbug.com/981719 [ Linux ] external/wpt/css/css-ui/webkit-appearance-textfield-001.html [ Failure ]
 crbug.com/981719 [ Win ] external/wpt/css/css-ui/webkit-appearance-textfield-001.html [ Failure ]
 
+# WebGPU tests are only run on GPU bots, so they are skipped by default and run
+# separately from other Web Tests.
+Bug(intentional) external/wpt/webgpu/ [ Skip ]
+
 # ====== Paint team owned tests to here ======
 
 crbug.com/922249 virtual/android/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html [ Failure Pass ]
@@ -686,9 +690,6 @@
 
 crbug.com/1003506 external/wpt/css/css-flexbox/percentage-heights-007.html [ Failure ]
 
-crbug.com/680331 external/wpt/css/cssom-view/scrollIntoView-sideways-lr-writing-mode-and-rtl-direction.html [ Failure ]
-crbug.com/680331 external/wpt/css/cssom-view/scrollIntoView-sideways-rl-writing-mode-and-rtl-direction.html [ Failure ]
-
 # ====== Layout team owned tests to here ======
 
 # ====== LayoutNG-only failures from here ======
@@ -1037,6 +1038,7 @@
 crbug.com/714962 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-width-large-002.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-width-small-001.xht [ Failure ]
 crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-zero-height-001.xht [ Failure ]
+crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/nested-with-padding-and-spanner.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/abspos-after-break-after.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/abspos-new-width-rebalance.html [ Crash Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-float-after-forced-break.html [ Failure ]
@@ -2008,23 +2010,7 @@
 # The spec for "Propagation to the Initial Containing Block" was changed.
 # https://drafts.csswg.org/css-writing-modes-4/#icb
 crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-001.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-034.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-035.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-038.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-039.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-042.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-043.html [ Failure ]
 crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-044.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-046.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-047.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-048.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-049.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-050.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-051.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-052.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-053.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-054.html [ Failure ]
-crbug.com/988585 external/wpt/css/css-writing-modes/wm-propagation-body-055.html [ Failure ]
 
 # Printing Layout broken in these tests.
 crbug.com/377696 printing/setPrinting.html [ Skip ]
@@ -5751,6 +5737,10 @@
 crbug.com/1013523 [ Release Linux Mac ] external/wpt/html/cross-origin-embedder-policy/require-corp.https.html [ Failure Pass ]
 crbug.com/1010472 [ Mac Debug ] virtual/disable-deferred-rendering/fast/canvas/color-space/canvas-drawImage-offscreenCanvas.html [ Failure Pass ]
 crbug.com/1010472 [ Mac Debug ] virtual/disable-deferred-rendering/fast/canvas/OffscreenCanvas-placeholder-createImageBitmap.html [ Failure Pass ]
+crbug.com/1013779 virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance.html [ Failure Pass ]
+crbug.com/1013779 [ Mac ] virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance.html [ Failure Pass ]
+crbug.com/1013779 virtual/scalefactor200/fast/hidpi/static/pointerevents/pointerevent_touch-adjustment_click_target.html [ Failure Pass ]
+crbug.com/1013779 virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ Failure Pass ]
 crbug.com/1013779 virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi.html [ Failure Pass ]
 crbug.com/990900 external/wpt/cookie-store/idlharness.tentative.https.any.serviceworker.html [ Pass Timeout ]
 crbug.com/990900 virtual/omt-worker-fetch/external/wpt/fetch/api/idlharness.any.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/compositing/absolute-position-changed-in-composited-layer.html b/third_party/blink/web_tests/compositing/absolute-position-changed-in-composited-layer.html
index edf09cd0..fbd615e5 100644
--- a/third_party/blink/web_tests/compositing/absolute-position-changed-in-composited-layer.html
+++ b/third_party/blink/web_tests/compositing/absolute-position-changed-in-composited-layer.html
@@ -8,7 +8,7 @@
         .absolute { position: absolute; }
         .green { background-color: green; }
         .red { background-color: red; }
-        .composited { transform: translateZ(0); }
+        .composited { will-change: transform; }
     </style>
     <script type="text/javascript">
         function moveAbsoluteDiv()
diff --git a/third_party/blink/web_tests/compositing/absolute-position-changed-with-composited-parent-layer.html b/third_party/blink/web_tests/compositing/absolute-position-changed-with-composited-parent-layer.html
index 5525fb3..cacd504 100644
--- a/third_party/blink/web_tests/compositing/absolute-position-changed-with-composited-parent-layer.html
+++ b/third_party/blink/web_tests/compositing/absolute-position-changed-with-composited-parent-layer.html
@@ -9,7 +9,7 @@
         .absolute { position: absolute; }
         .green { background-color: green; }
         .red { background-color: red; }
-        .composited { transform: translateZ(0); }
+        .composited { will-change: transform; }
     </style>
     <script type="text/javascript">
         function moveAbsoluteDiv()
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-alpha.html b/third_party/blink/web_tests/compositing/background-color/background-color-alpha.html
index ad654f31f..405e311 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-alpha.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-alpha.html
@@ -15,7 +15,7 @@
             }
 
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
     </head>
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-change-to-text.html b/third_party/blink/web_tests/compositing/background-color/background-color-change-to-text.html
index 6a5513ac..74bdc15 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-change-to-text.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-change-to-text.html
@@ -16,7 +16,7 @@
     }
 
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 </style>
 <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-change-to-transparent.html b/third_party/blink/web_tests/compositing/background-color/background-color-change-to-transparent.html
index f175528..db351b1 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-change-to-transparent.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-change-to-transparent.html
@@ -16,7 +16,7 @@
     }
 
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 </style>
 <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-container.html b/third_party/blink/web_tests/compositing/background-color/background-color-container.html
index 6daa687f..5ca4f6ec 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-container.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-container.html
@@ -15,7 +15,7 @@
             }
 
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
     </head>
@@ -25,4 +25,4 @@
             </div>
         </div>
     </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-content-clip.html b/third_party/blink/web_tests/compositing/background-color/background-color-content-clip.html
index e1ef813..ccac2673 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-content-clip.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-content-clip.html
@@ -17,7 +17,7 @@
             }
 
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
     </head>
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-padding-change.html b/third_party/blink/web_tests/compositing/background-color/background-color-padding-change.html
index 186faca..817479a 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-padding-change.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-padding-change.html
@@ -18,7 +18,7 @@
     }
 
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 </style>
 <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-padding-clip.html b/third_party/blink/web_tests/compositing/background-color/background-color-padding-clip.html
index c0fc816..6d7a9ccc 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-padding-clip.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-padding-clip.html
@@ -17,7 +17,7 @@
             }
 
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
     </head>
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-simple.html b/third_party/blink/web_tests/compositing/background-color/background-color-simple.html
index 68708d1c..5271d75e 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-simple.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-simple.html
@@ -9,7 +9,7 @@
             }
 
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
     </head>
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-text-change.html b/third_party/blink/web_tests/compositing/background-color/background-color-text-change.html
index 9754808..835571c 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-text-change.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-text-change.html
@@ -10,7 +10,7 @@
     }
 
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 </style>
 <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/background-color/background-color-text-clip.html b/third_party/blink/web_tests/compositing/background-color/background-color-text-clip.html
index 2b20271..3d992151 100644
--- a/third_party/blink/web_tests/compositing/background-color/background-color-text-clip.html
+++ b/third_party/blink/web_tests/compositing/background-color/background-color-text-clip.html
@@ -17,7 +17,7 @@
             }
 
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
     </head>
diff --git a/third_party/blink/web_tests/compositing/backgrounds/fixed-background-on-descendant.html b/third_party/blink/web_tests/compositing/backgrounds/fixed-background-on-descendant.html
index faaabce..9223c24 100644
--- a/third_party/blink/web_tests/compositing/backgrounds/fixed-background-on-descendant.html
+++ b/third_party/blink/web_tests/compositing/backgrounds/fixed-background-on-descendant.html
@@ -32,7 +32,7 @@
     }
 
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 </style>
 <script>
diff --git a/third_party/blink/web_tests/compositing/backgrounds/fixed-backgrounds.html b/third_party/blink/web_tests/compositing/backgrounds/fixed-backgrounds.html
index 75f1575..02689be 100644
--- a/third_party/blink/web_tests/compositing/backgrounds/fixed-backgrounds.html
+++ b/third_party/blink/web_tests/compositing/backgrounds/fixed-backgrounds.html
@@ -22,7 +22,7 @@
     }
 
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 </style>
 <script>
diff --git a/third_party/blink/web_tests/compositing/backing/no-backing-foreground-layer.html b/third_party/blink/web_tests/compositing/backing/no-backing-foreground-layer.html
index 5a79566..3dc6e25 100644
--- a/third_party/blink/web_tests/compositing/backing/no-backing-foreground-layer.html
+++ b/third_party/blink/web_tests/compositing/backing/no-backing-foreground-layer.html
@@ -28,7 +28,7 @@
     .composited {
       position: absolute;
       top: 50px;
-      transform: translateZ(0);
+      will-change: transform;
       background-color: green;
     }
   </style>
diff --git a/third_party/blink/web_tests/compositing/clip-child-by-non-stacking-ancestor.html b/third_party/blink/web_tests/compositing/clip-child-by-non-stacking-ancestor.html
index 06a6a8f..04a5297 100644
--- a/third_party/blink/web_tests/compositing/clip-child-by-non-stacking-ancestor.html
+++ b/third_party/blink/web_tests/compositing/clip-child-by-non-stacking-ancestor.html
@@ -4,7 +4,7 @@
 <head>
     <style type="text/css" media="screen">
         .container {
-            transform: translateZ(0);
+            will-change: transform;
             background-color: silver;
             width: 100px;
             height: 100px;
diff --git a/third_party/blink/web_tests/compositing/color-matching/image-color-matching.html b/third_party/blink/web_tests/compositing/color-matching/image-color-matching.html
index 97452763..83d90af5 100644
--- a/third_party/blink/web_tests/compositing/color-matching/image-color-matching.html
+++ b/third_party/blink/web_tests/compositing/color-matching/image-color-matching.html
@@ -12,7 +12,7 @@
     }
     
     .composited > img {
-      transform: translateZ(0);
+      will-change: transform;
     }
   </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/composited-scaled-child-with-border-radius-parent-clip.html b/third_party/blink/web_tests/compositing/composited-scaled-child-with-border-radius-parent-clip.html
index 279a3a5..76d0888 100644
--- a/third_party/blink/web_tests/compositing/composited-scaled-child-with-border-radius-parent-clip.html
+++ b/third_party/blink/web_tests/compositing/composited-scaled-child-with-border-radius-parent-clip.html
@@ -11,6 +11,7 @@
 
   #transform {
     transform: scale3d(2, 2, 1);
+    will-change: transform;
     background-color: green;
     width: 150px;
     height: 150px;
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/background-clip.html b/third_party/blink/web_tests/compositing/contents-opaque/background-clip.html
index 2ad0502..00bed065 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/background-clip.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/background-clip.html
@@ -11,7 +11,7 @@
                 background-color: green;
             }
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
             .padding-clip {
                 background-clip: padding-box;
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/background-color.html b/third_party/blink/web_tests/compositing/contents-opaque/background-color.html
index 839399b..bc1dc8e 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/background-color.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/background-color.html
@@ -12,7 +12,7 @@
                 background-color: rgba(0, 255, 0, 0.5);
             }
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
         <script type="text/javascript">
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/body-background-painted.html b/third_party/blink/web_tests/compositing/contents-opaque/body-background-painted.html
index bad5a9d..babae4a 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/body-background-painted.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/body-background-painted.html
@@ -12,7 +12,7 @@
                 width: 200px;
                 height: 200px;
                 background-color: green;
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
         <script type="text/javascript">
@@ -28,7 +28,7 @@
     </head>
     <!-- Composited body over the child div. -->
     <!-- Root <html> element has a background-color. -->
-    <!-- Background for the body element is painted in this case. ->
+    <!-- Background for the body element is painted in this case. -->
     <!-- GraphicsLayer::contentsOpaque for the body layer should be false. -->
     <body>
         <!-- Box under the body. -->
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/body-background-skipped.html b/third_party/blink/web_tests/compositing/contents-opaque/body-background-skipped.html
index e5534e6..ca3bebe 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/body-background-skipped.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/body-background-skipped.html
@@ -12,7 +12,7 @@
                 width: 200px;
                 height: 200px;
                 background-color: green;
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
         <script type="text/javascript">
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/control-layer.html b/third_party/blink/web_tests/compositing/contents-opaque/control-layer.html
index 821f901..4be129bd 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/control-layer.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/control-layer.html
@@ -2,7 +2,7 @@
     <head>
         <style type="text/css">
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
         <script type="text/javascript">
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/filter.html b/third_party/blink/web_tests/compositing/contents-opaque/filter.html
index 2157f10..2df4ed06c 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/filter.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/filter.html
@@ -22,7 +22,7 @@
                 background-color: green;
             }
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
             .filter-blur {
                 -webkit-filter: blur(10px);
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-child.html b/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-child.html
index f2fecb8..b01ba81 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-child.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-child.html
@@ -6,7 +6,7 @@
             width: 200px;
             height: 100px;
             background-color: green;
-            transform: translateZ(0);
+            will-change: transform;
         }
         .inner {
             visibility: visible;
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-text.html b/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-text.html
index 5ed8e28..82e5624 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-text.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-text.html
@@ -6,7 +6,7 @@
             width: 200px;
             height: 100px;
             background-color: green;
-            transform: translateZ(0);
+            will-change: transform;
         }
         .inner {
             visibility: visible;
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/layer-opacity.html b/third_party/blink/web_tests/compositing/contents-opaque/layer-opacity.html
index 469a02d2..d2b9f5c 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/layer-opacity.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/layer-opacity.html
@@ -12,7 +12,7 @@
                 opacity: 0.5;
             }
             .composited {
-                transform: translateZ(0);
+                will-change: transform;
             }
         </style>
         <script type="text/javascript">
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/layer-transform.html b/third_party/blink/web_tests/compositing/contents-opaque/layer-transform.html
index f8b3dc9..ebd9caf 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/layer-transform.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/layer-transform.html
@@ -5,7 +5,8 @@
                 width: 100px;
                 height: 100px;
                 background-color: green;
-                transform: rotate(30deg) translateZ(0);
+                transform: rotate(30deg);
+                will-change: transform;
             }
         </style>
         <script type="text/javascript">
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/overflow-hidden-child-layers.html b/third_party/blink/web_tests/compositing/contents-opaque/overflow-hidden-child-layers.html
index 6153322d..280d0f7c 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/overflow-hidden-child-layers.html
+++ b/third_party/blink/web_tests/compositing/contents-opaque/overflow-hidden-child-layers.html
@@ -9,7 +9,7 @@
             background-color: blue;
             box-shadow: 0 0 20px black;
             overflow: hidden;
-            transform: translateZ(0);
+            will-change: transform;
         }
         .child {
             position: relative;
diff --git a/third_party/blink/web_tests/compositing/culling/clear-fixed-iframe.html b/third_party/blink/web_tests/compositing/culling/clear-fixed-iframe.html
index cf921aa..90e1ea2 100644
--- a/third_party/blink/web_tests/compositing/culling/clear-fixed-iframe.html
+++ b/third_party/blink/web_tests/compositing/culling/clear-fixed-iframe.html
@@ -3,7 +3,7 @@
 <style>
 body { margin: 0; padding: 0; }
 .composited {
-  transform: translateZ(0);
+  will-change: transform;
   background-color: green;
   position:fixed;
   left:0; top:0; right:0; bottom:0;
diff --git a/third_party/blink/web_tests/compositing/culling/filter-occlusion-alpha-large.html b/third_party/blink/web_tests/compositing/culling/filter-occlusion-alpha-large.html
index e830e6d..d29e633c 100644
--- a/third_party/blink/web_tests/compositing/culling/filter-occlusion-alpha-large.html
+++ b/third_party/blink/web_tests/compositing/culling/filter-occlusion-alpha-large.html
@@ -3,7 +3,7 @@
 <title>CSS filter blur occlusion test.</title>
 <style type="text/css">
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   .green-parent {
     width: 800px;
diff --git a/third_party/blink/web_tests/compositing/culling/filter-occlusion-alpha.html b/third_party/blink/web_tests/compositing/culling/filter-occlusion-alpha.html
index 8d3686b..2cffc22b 100644
--- a/third_party/blink/web_tests/compositing/culling/filter-occlusion-alpha.html
+++ b/third_party/blink/web_tests/compositing/culling/filter-occlusion-alpha.html
@@ -3,7 +3,7 @@
 <title>CSS filter blur occlusion test.</title>
 <style type="text/css">
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   .green-parent {
     width: 600px;
diff --git a/third_party/blink/web_tests/compositing/culling/filter-occlusion-blur-large.html b/third_party/blink/web_tests/compositing/culling/filter-occlusion-blur-large.html
index d2071247..55743da 100644
--- a/third_party/blink/web_tests/compositing/culling/filter-occlusion-blur-large.html
+++ b/third_party/blink/web_tests/compositing/culling/filter-occlusion-blur-large.html
@@ -3,11 +3,11 @@
 <title>CSS filter blur occlusion test.</title>
 <style type="text/css">
   ::-webkit-scrollbar {
-      width: 0px;
-      height: 0px;
+    width: 0px;
+    height: 0px;
   }
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   .yellow-parent {
     width: 800px;
diff --git a/third_party/blink/web_tests/compositing/culling/filter-occlusion-blur.html b/third_party/blink/web_tests/compositing/culling/filter-occlusion-blur.html
index 00a2ade..ded27518 100644
--- a/third_party/blink/web_tests/compositing/culling/filter-occlusion-blur.html
+++ b/third_party/blink/web_tests/compositing/culling/filter-occlusion-blur.html
@@ -3,7 +3,7 @@
 <title>CSS filter blur occlusion test.</title>
 <style type="text/css">
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   .yellow-parent {
     width: 600px;
diff --git a/third_party/blink/web_tests/compositing/culling/scrolled-within-boxshadow.html b/third_party/blink/web_tests/compositing/culling/scrolled-within-boxshadow.html
index c2b1594..ea68958 100644
--- a/third_party/blink/web_tests/compositing/culling/scrolled-within-boxshadow.html
+++ b/third_party/blink/web_tests/compositing/culling/scrolled-within-boxshadow.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 .comp {
-  transform: translateZ(0px);
+  will-change: transform;
 }
 body {
   margin:0;
diff --git a/third_party/blink/web_tests/compositing/culling/tile-occlusion-boundaries.html b/third_party/blink/web_tests/compositing/culling/tile-occlusion-boundaries.html
index 95b23907..50f6a13 100644
--- a/third_party/blink/web_tests/compositing/culling/tile-occlusion-boundaries.html
+++ b/third_party/blink/web_tests/compositing/culling/tile-occlusion-boundaries.html
@@ -6,7 +6,8 @@
       left: 128; top: 128;
       width:511px;
       height:511px;
-      transform: translateZ(0px) scale(0.5);
+      transform: scale(0.5);
+      will-change: transform;
     }
     body { position:relative; }
   </style>
diff --git a/third_party/blink/web_tests/compositing/culling/translated-boxshadow.html b/third_party/blink/web_tests/compositing/culling/translated-boxshadow.html
index c2bbac7..eec884e 100644
--- a/third_party/blink/web_tests/compositing/culling/translated-boxshadow.html
+++ b/third_party/blink/web_tests/compositing/culling/translated-boxshadow.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 .comp {
-  transform: translateZ(0px);
+  will-change: transform;
 }
 body {
   margin:0;
diff --git a/third_party/blink/web_tests/compositing/culling/unscrolled-within-boxshadow.html b/third_party/blink/web_tests/compositing/culling/unscrolled-within-boxshadow.html
index 9d69951b..ef67d10 100644
--- a/third_party/blink/web_tests/compositing/culling/unscrolled-within-boxshadow.html
+++ b/third_party/blink/web_tests/compositing/culling/unscrolled-within-boxshadow.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 .comp {
-  transform: translateZ(0px);
+  will-change: transform;
 }
 body {
   margin:0;
diff --git a/third_party/blink/web_tests/compositing/direct-image-compositing.html b/third_party/blink/web_tests/compositing/direct-image-compositing.html
index bfa6bb0..3c82799e 100644
--- a/third_party/blink/web_tests/compositing/direct-image-compositing.html
+++ b/third_party/blink/web_tests/compositing/direct-image-compositing.html
@@ -4,7 +4,7 @@
 <html lang="en">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-  <title>Testing direct image layer optimisation</title>
+  <title>Testing direct image layer optimization</title>
   <style type="text/css" media="screen">
     img {
       float: left;
@@ -12,7 +12,7 @@
       height: 150px;
     }
     img {
-      transform: rotate3d(0, 0, 1, 0);
+      will-change: transform;
     }
     .test {
       float: left;
diff --git a/third_party/blink/web_tests/compositing/filters/sw-layer-overlaps-hw-shadow.html b/third_party/blink/web_tests/compositing/filters/sw-layer-overlaps-hw-shadow.html
index 04f82b3..80e4c27 100644
--- a/third_party/blink/web_tests/compositing/filters/sw-layer-overlaps-hw-shadow.html
+++ b/third_party/blink/web_tests/compositing/filters/sw-layer-overlaps-hw-shadow.html
@@ -25,7 +25,7 @@
             left: 105px;
             width: 100px;
             height: 100px;
-            transform: translate3d(0, 0, 0);
+            will-change: transform;
         }
     </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html b/third_party/blink/web_tests/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html
index 08dd8c8..e4bf892 100644
--- a/third_party/blink/web_tests/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html
+++ b/third_party/blink/web_tests/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html
@@ -36,7 +36,7 @@
             left: 330px;
             width: 100px;
             height: 100px;
-            transform: translate3d(0, 0, 0);
+            will-change: transform;
         }
         #composited-child {
             background-color: blue;
diff --git a/third_party/blink/web_tests/compositing/filters/sw-shadow-overlaps-hw-layer.html b/third_party/blink/web_tests/compositing/filters/sw-shadow-overlaps-hw-layer.html
index 06c650a..e6d902c 100644
--- a/third_party/blink/web_tests/compositing/filters/sw-shadow-overlaps-hw-layer.html
+++ b/third_party/blink/web_tests/compositing/filters/sw-shadow-overlaps-hw-layer.html
@@ -25,7 +25,7 @@
             left: 105px;
             width: 100px;
             height: 100px;
-            transform: translate3d(0, 0, 0);
+            will-change: transform;
         }
     </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/filters/sw-shadow-overlaps-hw-shadow.html b/third_party/blink/web_tests/compositing/filters/sw-shadow-overlaps-hw-shadow.html
index 9714c83..7b4dce3 100644
--- a/third_party/blink/web_tests/compositing/filters/sw-shadow-overlaps-hw-shadow.html
+++ b/third_party/blink/web_tests/compositing/filters/sw-shadow-overlaps-hw-shadow.html
@@ -26,7 +26,7 @@
             left: 130px;
             width: 100px;
             height: 100px;
-            transform: translate3d(0, 0, 0);
+            will-change: transform;
         }
     </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/fixed-position-changed-in-composited-layer.html b/third_party/blink/web_tests/compositing/fixed-position-changed-in-composited-layer.html
index 2e93ab7..2887520 100644
--- a/third_party/blink/web_tests/compositing/fixed-position-changed-in-composited-layer.html
+++ b/third_party/blink/web_tests/compositing/fixed-position-changed-in-composited-layer.html
@@ -7,7 +7,7 @@
         .fixed { position: fixed; }
         .green { background-color: green; }
         .red { background-color: red; }
-        .composited { transform: translateZ(0); }
+        .composited { will-change: transform; }
     </style>
     <script src="../resources/run-after-layout-and-paint.js"></script>
     <script type="text/javascript">
diff --git a/third_party/blink/web_tests/compositing/fixed-position-changed-to-absolute.html b/third_party/blink/web_tests/compositing/fixed-position-changed-to-absolute.html
index 6329b621..89948ba9 100644
--- a/third_party/blink/web_tests/compositing/fixed-position-changed-to-absolute.html
+++ b/third_party/blink/web_tests/compositing/fixed-position-changed-to-absolute.html
@@ -2,7 +2,7 @@
 <style>
 .composited {
   position: absolute;
-  transform: translateZ(0);
+  will-change: transform;
   width: 150px;
   height: 150px;
   background: #D9CCA7;
diff --git a/third_party/blink/web_tests/compositing/fixed-position-changed-within-composited-parent-layer.html b/third_party/blink/web_tests/compositing/fixed-position-changed-within-composited-parent-layer.html
index 7c606c9..85d22ff 100644
--- a/third_party/blink/web_tests/compositing/fixed-position-changed-within-composited-parent-layer.html
+++ b/third_party/blink/web_tests/compositing/fixed-position-changed-within-composited-parent-layer.html
@@ -8,7 +8,7 @@
         .fixed { position: fixed; }
         .green { background-color: green; }
         .red { background-color: red; }
-        .composited { transform: translateZ(0); }
+        .composited { will-change: transform; }
     </style>
     <script type="text/javascript">
         function moveFixedDiv()
diff --git a/third_party/blink/web_tests/compositing/framesets/resources/composited-subframe.html b/third_party/blink/web_tests/compositing/framesets/resources/composited-subframe.html
index 3e3dd224..3558d06 100644
--- a/third_party/blink/web_tests/compositing/framesets/resources/composited-subframe.html
+++ b/third_party/blink/web_tests/compositing/framesets/resources/composited-subframe.html
@@ -14,7 +14,7 @@
         margin: 10px;
         padding: 5px;
         background-color: green;
-        transform: translateZ(0);
+        will-change: transform;
         overflow:hidden;
     }
     .box:hover {
diff --git a/third_party/blink/web_tests/compositing/geometry/abs-position-inside-opacity.html b/third_party/blink/web_tests/compositing/geometry/abs-position-inside-opacity.html
index 5603890a..0c3b9ff 100644
--- a/third_party/blink/web_tests/compositing/geometry/abs-position-inside-opacity.html
+++ b/third_party/blink/web_tests/compositing/geometry/abs-position-inside-opacity.html
@@ -28,7 +28,7 @@
     }
     
     .compositing {
-      transform: translateZ(0);
+      will-change: transform;
     }
   </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/geometry/bounds-clipped-composited-child.html b/third_party/blink/web_tests/compositing/geometry/bounds-clipped-composited-child.html
index f2a518b..357ef39 100644
--- a/third_party/blink/web_tests/compositing/geometry/bounds-clipped-composited-child.html
+++ b/third_party/blink/web_tests/compositing/geometry/bounds-clipped-composited-child.html
@@ -10,6 +10,7 @@
       margin-left: 50px;
       height: 100px;
       width: 100px;
+      will-change: transform;
       transform: translate3d(-50%, 0, 0);
     }
     
diff --git a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-composited-descendant.html b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-composited-descendant.html
index 75a25e1..63186ea 100644
--- a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-composited-descendant.html
+++ b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-composited-descendant.html
@@ -1,6 +1,6 @@
 <style>
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   
   img {
diff --git a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
index fd6f110..76b1699 100644
--- a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
+++ b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
@@ -3,7 +3,7 @@
         overflow: hidden;
     }
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 
     .box {
diff --git a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic.html b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic.html
index e4d3fff..9c19b61 100644
--- a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic.html
+++ b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic.html
@@ -1,6 +1,6 @@
 <style>
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   
   .box {
diff --git a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden.html b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden.html
index c65d49f..dd18dbc1 100644
--- a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden.html
+++ b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden.html
@@ -1,6 +1,6 @@
 <style>
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   
   img {
diff --git a/third_party/blink/web_tests/compositing/geometry/clipping-foreground.html b/third_party/blink/web_tests/compositing/geometry/clipping-foreground.html
index b15b423..30a50ea 100644
--- a/third_party/blink/web_tests/compositing/geometry/clipping-foreground.html
+++ b/third_party/blink/web_tests/compositing/geometry/clipping-foreground.html
@@ -17,7 +17,7 @@
       background-color:rgba(255, 255, 255, 0.8);
       font-size: 220%;
       font-weight: bold;
-      transform: translateZ(0);
+      will-change: transform;
     }
 
     .child {
@@ -28,7 +28,7 @@
       padding: 20px;
       color: gray;
       -webkit-box-sizing: border-box;
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     .child > .child {
diff --git a/third_party/blink/web_tests/compositing/geometry/composited-html-size.html b/third_party/blink/web_tests/compositing/geometry/composited-html-size.html
index 30137ce..4d967680 100644
--- a/third_party/blink/web_tests/compositing/geometry/composited-html-size.html
+++ b/third_party/blink/web_tests/compositing/geometry/composited-html-size.html
@@ -18,9 +18,9 @@
      z-index: -1;
      background-color: blue;
    }
- 
+
    .compositing {
-     transform: translateZ(0);
+     will-change: transform;
    }
   </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/geometry/composited-in-columns.html b/third_party/blink/web_tests/compositing/geometry/composited-in-columns.html
index f583347..66c95b8 100644
--- a/third_party/blink/web_tests/compositing/geometry/composited-in-columns.html
+++ b/third_party/blink/web_tests/compositing/geometry/composited-in-columns.html
@@ -13,7 +13,7 @@
       column-fill: auto;
       border: 1px solid black;
     }
-    
+
     .block {
       display: inline-block;
       width: 200px;
@@ -22,12 +22,13 @@
       background-color: silver;
       outline: 5px solid transparent; /* increases compositing layer bounds to test bounds math */
     }
-    
+
     .composited {
+      will-change: transform;
       transform: translateZ(0);
       background-color: blue;
     }
-    
+
     .box {
       height: 50px;
       width: 50px;
diff --git a/third_party/blink/web_tests/compositing/geometry/fixed-in-composited.html b/third_party/blink/web_tests/compositing/geometry/fixed-in-composited.html
index f0e3b2c..14b9422c 100644
--- a/third_party/blink/web_tests/compositing/geometry/fixed-in-composited.html
+++ b/third_party/blink/web_tests/compositing/geometry/fixed-in-composited.html
@@ -28,7 +28,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     .container.two {
diff --git a/third_party/blink/web_tests/compositing/geometry/fixed-position.html b/third_party/blink/web_tests/compositing/geometry/fixed-position.html
index 60a86e4..41e36ac 100644
--- a/third_party/blink/web_tests/compositing/geometry/fixed-position.html
+++ b/third_party/blink/web_tests/compositing/geometry/fixed-position.html
@@ -32,7 +32,7 @@
     }
     
     .compositing {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     p {
diff --git a/third_party/blink/web_tests/compositing/geometry/flipped-writing-mode.html b/third_party/blink/web_tests/compositing/geometry/flipped-writing-mode.html
index 504c941..32df3ea3 100644
--- a/third_party/blink/web_tests/compositing/geometry/flipped-writing-mode.html
+++ b/third_party/blink/web_tests/compositing/geometry/flipped-writing-mode.html
@@ -22,7 +22,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     .block {
diff --git a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-opacity-transition.html b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-opacity-transition.html
index f786eb9..94a4c91 100644
--- a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-opacity-transition.html
+++ b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-opacity-transition.html
@@ -14,7 +14,7 @@
     .compositing {
       width: 1px;
       height: 1px;
-      transform: translateZ(0);
+      will-change: transform;
     }
 
     #fading {
diff --git a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-overflow-root.html b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-overflow-root.html
index 17499c01..2df1fb36 100644
--- a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-overflow-root.html
+++ b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-overflow-root.html
@@ -23,7 +23,7 @@
       left: 21px;
       width: 100px;
       height: 100px;
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     .test {
diff --git a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned-transition.html b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned-transition.html
index 3d60204..e6e5cf5 100644
--- a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned-transition.html
+++ b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned-transition.html
@@ -22,6 +22,7 @@
       width: 100px;
       height: 100px;
       transform: translateZ(0);
+      will-change: transform;
     }
     
     #far-left {
diff --git a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned.html b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned.html
index 443f8983..5d7c81e7 100644
--- a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned.html
+++ b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned.html
@@ -21,7 +21,7 @@
       left: 21px;
       width: 100px;
       height: 100px;
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     .far-left {
diff --git a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-transformed.html b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-transformed.html
index a8d4d6b4..d86ce9c 100644
--- a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-transformed.html
+++ b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-transformed.html
@@ -22,7 +22,7 @@
       left: 121px;
       width: 100px;
       height: 100px;
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     .far-left {
diff --git a/third_party/blink/web_tests/compositing/geometry/root-layer-update.html b/third_party/blink/web_tests/compositing/geometry/root-layer-update.html
index bfda1253..8adef68 100644
--- a/third_party/blink/web_tests/compositing/geometry/root-layer-update.html
+++ b/third_party/blink/web_tests/compositing/geometry/root-layer-update.html
@@ -27,7 +27,7 @@
       width: 100px;
       background-color: green;
       margin: 0 auto;
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     #tester {
diff --git a/third_party/blink/web_tests/compositing/geometry/vertical-scroll-composited.html b/third_party/blink/web_tests/compositing/geometry/vertical-scroll-composited.html
index ee1ff72..6b58ca8 100644
--- a/third_party/blink/web_tests/compositing/geometry/vertical-scroll-composited.html
+++ b/third_party/blink/web_tests/compositing/geometry/vertical-scroll-composited.html
@@ -13,7 +13,7 @@
     </style>
 </head>
 <body style="height: 600px">
-<div style="transform: rotate3d(0,0,1,20deg); width: 800px; height: 1000px; border-style: solid; border-color: Red; border-width: 3px; background-image: url(../resources/apple.jpg); background-repeat:repeat"></div>
+<div style="transform: rotate3d(0,0,1,20deg); will-change: transform; width: 800px; height: 1000px; border-style: solid; border-color: Red; border-width: 3px; background-image: url(../resources/apple.jpg); background-repeat:repeat"></div>
 <script type="text/javascript" charset="utf-8">
       window.scrollBy(0, 200);
       if (window.testRunner)
diff --git a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-1-overflow-div-composited-scroll-clip-expected.html b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-1-overflow-div-composited-scroll-clip-expected.html
index 42a1d2c7..34f3939a 100644
--- a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-1-overflow-div-composited-scroll-clip-expected.html
+++ b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-1-overflow-div-composited-scroll-clip-expected.html
@@ -6,7 +6,7 @@
 <body onload="runTest();">
 <div style="position: relative; left: 10px; top: 10px"></div>
 <div id="targetDiv" style="position: relative; left: 10px; top: 40px; width: 200px; height: 100px; overflow-y: scroll; overflow-x: scroll;">
-<div style="transform: translateZ(0)">
+<div style="will-change: transform;">
 <a href="" id="targetLink">Target Link.</a><br>
 <a href="">Link 1</a><br>
 <a href="">Link 2</a><br>
diff --git a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-1-overflow-div-composited-scroll-clip.html b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-1-overflow-div-composited-scroll-clip.html
index 52d0c7e..e8a839a 100644
--- a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-1-overflow-div-composited-scroll-clip.html
+++ b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-1-overflow-div-composited-scroll-clip.html
@@ -7,7 +7,7 @@
 <body onload="runTest();">
 <div style="position: relative; left: 10px; top: 10px"></div>
 <div id="targetDiv" style="position: relative; left: 10px; top: 40px; width: 200px; height: 100px; overflow-y: scroll; overflow-x: scroll;">
-<div style="transform: translateZ(0)">
+<div style="will-change: transform">
 <a href="" id="targetLink" style="-webkit-tap-highlight-color: rgba(0, 255, 0, 0.5)">Target Link.</a><br>
 <a href="">Link 1</a><br>
 <a href="">Link 2</a><br>
diff --git a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-rotated-div.html b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-rotated-div.html
index e26b131..f72f7c4 100644
--- a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-rotated-div.html
+++ b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-rotated-div.html
@@ -7,7 +7,7 @@
 <div id="targetDiv" onclick="doNothing();" style="position: absolute; left: 40px; top: 40px; width: 50px; height: 50px; transform: rotate(22.5deg); border-style: solid; border-width: 2px; -webkit-tap-highlight-color: rgba(0, 255, 0, 0.5); cursor: Pointer">
 <br><center>Target</center><br>
 </div>
-<div style="position: absolute; left: 10px; top: 110px; transform: translateZ(0);">
+<div style="position: absolute; left: 10px; top: 110px; will-change: transform;">
 This test is successful if the rotated box labelled "Target" is covered in a green rectangle.
 </div>
 <script>
diff --git a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-rotated-link.html b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-rotated-link.html
index 5edba67..a470918 100644
--- a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-rotated-link.html
+++ b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-rotated-link.html
@@ -11,7 +11,7 @@
   <a href="" id="link2">Link 2</a>
 </div>
 </div>
-<div style="position: absolute; left: 10px; top: 110px; transform: translateZ(0);">
+<div style="position: absolute; left: 10px; top: 110px; will-change: transform;">
 This test is successful if "Target Link" above is covered in a green rectangle with rounded corners.
 </div>
 <script>
diff --git a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-transparent.html b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-transparent.html
index 0803342..f83a8bd5d 100644
--- a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-transparent.html
+++ b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-pixel-transparent.html
@@ -8,7 +8,7 @@
 <a href="" id="link1">Link 1</a><br>
 <a href="" id="targetLink" class="transparentHighlight">Target Link.</a><br>
 <a href="" id="link2">Link 2</a>
-<div style="position: relative; left: 0px; top: 200px; transform: translateZ(0);">
+<div style="position: relative; left: 0px; top: 200px; will-change: transform;">
 This test is successful if "Target Link" above is covered in a transparent green rectangle with rounded corners.
 </div>
 <script>
diff --git a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-simple-scaledX.html b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-simple-scaledX.html
index aa3579b8..115ad7b 100644
--- a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-simple-scaledX.html
+++ b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-simple-scaledX.html
@@ -11,7 +11,7 @@
 <a href="" id="link2">Link 2</a>
 </div>
 </div>
-<div style="position: relative; left: 10px; top: 200px; transform: translateZ(0);">
+<div style="position: relative; left: 10px; top: 200px; will-change: transform;">
 This test is successful if "Target Link" above is covered in a green rectangle with square corners.
 </div>
 <script>
diff --git a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-with-squashing.html b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-with-squashing.html
index 16f6a86..72f6adb 100644
--- a/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-with-squashing.html
+++ b/third_party/blink/web_tests/compositing/gestures/gesture-tapHighlight-with-squashing.html
@@ -6,7 +6,7 @@
   }
 
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
 
   .fixed {
diff --git a/third_party/blink/web_tests/compositing/gestures/resources/1-frame-composited.html b/third_party/blink/web_tests/compositing/gestures/resources/1-frame-composited.html
index 9ba39061..a299f31 100644
--- a/third_party/blink/web_tests/compositing/gestures/resources/1-frame-composited.html
+++ b/third_party/blink/web_tests/compositing/gestures/resources/1-frame-composited.html
@@ -6,7 +6,7 @@
 </style>
 </head>
 <body>
-<div id="divToControlCompositing" style="transform: translateZ(0);">
+<div id="divToControlCompositing" style="will-change: transform;">
 <a href="">Link 1</a><br>
 <a href="">Link 2</a><br>
 <a href="">Link 3</a><br>
diff --git a/third_party/blink/web_tests/compositing/gestures/resources/link-highlight-style.css b/third_party/blink/web_tests/compositing/gestures/resources/link-highlight-style.css
index e28883f1..b7ec5fb 100644
--- a/third_party/blink/web_tests/compositing/gestures/resources/link-highlight-style.css
+++ b/third_party/blink/web_tests/compositing/gestures/resources/link-highlight-style.css
@@ -41,5 +41,6 @@
 }
 
 .composited {
+  will-change: transform;
   transform: translateZ(0);
 }
diff --git a/third_party/blink/web_tests/compositing/iframes/become-composited-nested-iframes.html b/third_party/blink/web_tests/compositing/iframes/become-composited-nested-iframes.html
index f01e628f8..e63cb3f 100644
--- a/third_party/blink/web_tests/compositing/iframes/become-composited-nested-iframes.html
+++ b/third_party/blink/web_tests/compositing/iframes/become-composited-nested-iframes.html
@@ -16,7 +16,7 @@
     }
     
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
    
     iframe {
diff --git a/third_party/blink/web_tests/compositing/iframes/composited-parent-iframe.html b/third_party/blink/web_tests/compositing/iframes/composited-parent-iframe.html
index 607ba5a..b17c8b7 100644
--- a/third_party/blink/web_tests/compositing/iframes/composited-parent-iframe.html
+++ b/third_party/blink/web_tests/compositing/iframes/composited-parent-iframe.html
@@ -9,7 +9,7 @@
         height: 150px;
         width: 300px;
         -webkit-box-shadow: 0 0 20px black;
-        transform: translateZ(0);
+        will-change: transform;
     }
   </style>
   <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe-delayed.html b/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe-delayed.html
index dfc7e8b..4c0f381d 100644
--- a/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe-delayed.html
+++ b/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe-delayed.html
@@ -20,7 +20,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
   </style>
diff --git a/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe2.html b/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe2.html
index 85331a6..777ab586 100644
--- a/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe2.html
+++ b/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe2.html
@@ -11,7 +11,7 @@
         height: 150px;
         width: 300px;
         -webkit-box-shadow: 0 0 20px black;
-        transform: translateZ(0);
+        will-change: transform;
     }
     
     .overlay {
diff --git a/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe3.html b/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe3.html
index 13a17dc5..3fc0475 100644
--- a/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe3.html
+++ b/third_party/blink/web_tests/compositing/iframes/connect-compositing-iframe3.html
@@ -14,7 +14,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
   </style>
diff --git a/third_party/blink/web_tests/compositing/iframes/iframe-content-flipping.html b/third_party/blink/web_tests/compositing/iframes/iframe-content-flipping.html
index d2f20c06..3dbdd70 100644
--- a/third_party/blink/web_tests/compositing/iframes/iframe-content-flipping.html
+++ b/third_party/blink/web_tests/compositing/iframes/iframe-content-flipping.html
@@ -11,7 +11,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
   </style>
diff --git a/third_party/blink/web_tests/compositing/iframes/iframe-copy-on-scroll.html b/third_party/blink/web_tests/compositing/iframes/iframe-copy-on-scroll.html
index 59350cc2..8bc20818 100644
--- a/third_party/blink/web_tests/compositing/iframes/iframe-copy-on-scroll.html
+++ b/third_party/blink/web_tests/compositing/iframes/iframe-copy-on-scroll.html
@@ -9,7 +9,7 @@
     }
     .composited {
       position: absolute;
-      transform: translateZ(0);
+      will-change: transform;
     }
   </style>
   <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/iframes/invisible-nested-iframe-hide.html b/third_party/blink/web_tests/compositing/iframes/invisible-nested-iframe-hide.html
index b43f235..0d6366b 100644
--- a/third_party/blink/web_tests/compositing/iframes/invisible-nested-iframe-hide.html
+++ b/third_party/blink/web_tests/compositing/iframes/invisible-nested-iframe-hide.html
@@ -17,7 +17,7 @@
         margin: 10px;
         padding: 5px;
         background-color: blue;
-        transform: translateZ(0);
+        will-change: transform;
         overflow:hidden;
     }
     .box:hover {
diff --git a/third_party/blink/web_tests/compositing/iframes/resizer.html b/third_party/blink/web_tests/compositing/iframes/resizer.html
index 74b4485..596fcd6 100644
--- a/third_party/blink/web_tests/compositing/iframes/resizer.html
+++ b/third_party/blink/web_tests/compositing/iframes/resizer.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <style>
 .container {
-     transform: translateZ(0);
+     will-change: transform;
      resize: both;
 }
 </style>
diff --git a/third_party/blink/web_tests/compositing/iframes/resources/ancestor-clipping-layer-subframe.html b/third_party/blink/web_tests/compositing/iframes/resources/ancestor-clipping-layer-subframe.html
index 276eb36..80d5302 100644
--- a/third_party/blink/web_tests/compositing/iframes/resources/ancestor-clipping-layer-subframe.html
+++ b/third_party/blink/web_tests/compositing/iframes/resources/ancestor-clipping-layer-subframe.html
@@ -4,7 +4,7 @@
   width: 300px;
   height: 150px;
   background: blue;
-  transform: translateZ(0);
+  will-change: transform;
 }
 </style>
 <div class="composited"></div>
diff --git a/third_party/blink/web_tests/compositing/iframes/resources/composited-subframe.html b/third_party/blink/web_tests/compositing/iframes/resources/composited-subframe.html
index 92b3b7f..be73930 100644
--- a/third_party/blink/web_tests/compositing/iframes/resources/composited-subframe.html
+++ b/third_party/blink/web_tests/compositing/iframes/resources/composited-subframe.html
@@ -11,7 +11,7 @@
         margin: 10px;
         padding: 5px;
         background-color: blue;
-        transform: translateZ(0);
+        will-change: transform;
         overflow:hidden;
     }
     .box:hover {
diff --git a/third_party/blink/web_tests/compositing/iframes/resources/enter-compositing-subframe.html b/third_party/blink/web_tests/compositing/iframes/resources/enter-compositing-subframe.html
index 74a6932..d28255f 100644
--- a/third_party/blink/web_tests/compositing/iframes/resources/enter-compositing-subframe.html
+++ b/third_party/blink/web_tests/compositing/iframes/resources/enter-compositing-subframe.html
@@ -14,7 +14,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
 
   </style>
diff --git a/third_party/blink/web_tests/compositing/iframes/resources/large-composited-subframe.html b/third_party/blink/web_tests/compositing/iframes/resources/large-composited-subframe.html
index 17d3b18..b180740 100644
--- a/third_party/blink/web_tests/compositing/iframes/resources/large-composited-subframe.html
+++ b/third_party/blink/web_tests/compositing/iframes/resources/large-composited-subframe.html
@@ -14,7 +14,7 @@
       width: 200px;
       margin: 100px;
       background-color: blue;
-      transform: translateZ(0);
+      will-change: transform;
     }
     .box:hover {
       transform: none;
diff --git a/third_party/blink/web_tests/compositing/iframes/resources/leave-compositing-subframe-click.html b/third_party/blink/web_tests/compositing/iframes/resources/leave-compositing-subframe-click.html
index 904977d8..33b80924 100644
--- a/third_party/blink/web_tests/compositing/iframes/resources/leave-compositing-subframe-click.html
+++ b/third_party/blink/web_tests/compositing/iframes/resources/leave-compositing-subframe-click.html
@@ -15,7 +15,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
 
   </style>
diff --git a/third_party/blink/web_tests/compositing/images/clip-on-directly-composited-image.html b/third_party/blink/web_tests/compositing/images/clip-on-directly-composited-image.html
index 798f3ec..bc3a2de 100644
--- a/third_party/blink/web_tests/compositing/images/clip-on-directly-composited-image.html
+++ b/third_party/blink/web_tests/compositing/images/clip-on-directly-composited-image.html
@@ -12,7 +12,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
       left: 200px;
     }
     
diff --git a/third_party/blink/web_tests/compositing/images/direct-image-background-color.html b/third_party/blink/web_tests/compositing/images/direct-image-background-color.html
index e0e8dc2..620b4d2 100644
--- a/third_party/blink/web_tests/compositing/images/direct-image-background-color.html
+++ b/third_party/blink/web_tests/compositing/images/direct-image-background-color.html
@@ -18,7 +18,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
   </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/images/direct-image-clip-path.html b/third_party/blink/web_tests/compositing/images/direct-image-clip-path.html
index 33347a34..390cf72d 100644
--- a/third_party/blink/web_tests/compositing/images/direct-image-clip-path.html
+++ b/third_party/blink/web_tests/compositing/images/direct-image-clip-path.html
@@ -2,7 +2,7 @@
 <html>
 <style>
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
     -webkit-clip-path: circle(45%);
   }
 </style>
diff --git a/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-draws-content.html b/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-draws-content.html
index e032a57ac..f014494f 100644
--- a/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-draws-content.html
+++ b/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-draws-content.html
@@ -3,7 +3,7 @@
 <head>
   <style>
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
     .border {
       border: 2px solid blue;
diff --git a/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-radius-expected.html b/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-radius-expected.html
index e6561f1e..b08e0e7a 100644
--- a/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-radius-expected.html
+++ b/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-radius-expected.html
@@ -2,7 +2,7 @@
 <html>
 <style>
   .border {
-    transform: translateZ(0);
+    will-change: transform;
     border-radius: 50%;
   }
 </style>
diff --git a/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-radius.html b/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-radius.html
index bd2c60f..121625ce 100644
--- a/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-radius.html
+++ b/third_party/blink/web_tests/compositing/images/direct-image-dynamic-border-radius.html
@@ -2,7 +2,7 @@
 <html>
 <style>
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   .border-radius {
     border-radius: 50%;
diff --git a/third_party/blink/web_tests/compositing/images/direct-image-dynamic-clip-path.html b/third_party/blink/web_tests/compositing/images/direct-image-dynamic-clip-path.html
index dd9f0f2..734f162 100644
--- a/third_party/blink/web_tests/compositing/images/direct-image-dynamic-clip-path.html
+++ b/third_party/blink/web_tests/compositing/images/direct-image-dynamic-clip-path.html
@@ -2,7 +2,7 @@
 <html>
 <style>
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   .clip-path {
     -webkit-clip-path: circle(45%);
diff --git a/third_party/blink/web_tests/compositing/images/direct-svg-image.html b/third_party/blink/web_tests/compositing/images/direct-svg-image.html
index 028a3b8..4b4b2d1 100644
--- a/third_party/blink/web_tests/compositing/images/direct-svg-image.html
+++ b/third_party/blink/web_tests/compositing/images/direct-svg-image.html
@@ -15,7 +15,7 @@
     }
     
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
     
     #indicator {
diff --git a/third_party/blink/web_tests/compositing/img-layer-object-fit.html b/third_party/blink/web_tests/compositing/img-layer-object-fit.html
index 33d5ca84..7a81b350 100644
--- a/third_party/blink/web_tests/compositing/img-layer-object-fit.html
+++ b/third_party/blink/web_tests/compositing/img-layer-object-fit.html
@@ -3,7 +3,7 @@
   img {
     width: 100px;
     height: 30px;
-    transform: translateZ(0);
+    will-change: transform;
   }
 </style>
 <img src="resources/simple_image.png" style="object-fit: contain"/><br/>
diff --git a/third_party/blink/web_tests/compositing/layer-creation/animation-overlap-with-children.html b/third_party/blink/web_tests/compositing/layer-creation/animation-overlap-with-children.html
index da9eed2..c1f2e9e7 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/animation-overlap-with-children.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/animation-overlap-with-children.html
@@ -44,7 +44,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     @keyframes slide {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers.html b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers.html
index 8b0ff4bb..4075b45b 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers.html
@@ -38,7 +38,7 @@
     }
 
     .composited {
-        transform: translatez(0);
+        will-change: transform;
     }
 
     .scrollable {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body-overlap.html b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body-overlap.html
index 72f38fa..f9ffd39 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body-overlap.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body-overlap.html
@@ -33,7 +33,7 @@
     }
 
     .composited {
-        transform: translatez(0);
+        will-change: transform;
     }
   </style>
 
diff --git a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body.html b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body.html
index e8cb2560..4300b83 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-body.html
@@ -33,7 +33,7 @@
     }
 
     .composited {
-        transform: translatez(0);
+        will-change: transform;
     }
   </style>
 
diff --git a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page.html b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page.html
index 873c66b..c066aa4 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page.html
@@ -3,7 +3,7 @@
 <head>
   <style>
     .composited {
-      transform: translatez(0);
+      will-change: transform;
     }
 
     .box {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-under-transform.html b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-under-transform.html
index 044c20bc..0c3e5b9 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-under-transform.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-under-transform.html
@@ -10,7 +10,8 @@
     #transform {
         z-index: 0;
         /* transform establishes a fixed pos container, so translate to make up for scroll offset so indicator is still underneath overlap */
-        transform:translate3d(0px, 1000px, 0px);
+        transform: translate3d(0px, 1000px, 0px);
+        will-change: transform;
     }
 
     #indicator {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/no-compositing-for-fixed-position-under-transform.html b/third_party/blink/web_tests/compositing/layer-creation/no-compositing-for-fixed-position-under-transform.html
index 088ae6f1..2921bbc3 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/no-compositing-for-fixed-position-under-transform.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/no-compositing-for-fixed-position-under-transform.html
@@ -6,7 +6,7 @@
       width: 100px;
       height: 30px;
       background: blue;
-      transform: translateZ(0);
+      will-change: transform;
     }
     .fixed {
       position: fixed;
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap.html b/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap.html
index 6943814f..9290561 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap.html
@@ -6,7 +6,7 @@
     .composited {
       height: 30px;
       width: 30px;
-      transform:translateZ(0);
+      will-change: transform;
     }
 
     .overflow {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-child-layer.html b/third_party/blink/web_tests/compositing/layer-creation/overlap-child-layer.html
index c9d0970..9742dc023 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overlap-child-layer.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-child-layer.html
@@ -5,7 +5,7 @@
         position: absolute;
         top: 0px;
         left: 400px;
-        transform: translateZ(0);
+        will-change: transform;
     }
 
     #red {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping.html b/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping.html
index f97e03d..caddaac 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping.html
@@ -15,7 +15,7 @@
         width: 500px;
         height: 100px;
         background-color: green;
-        transform:translateZ(0);
+        will-change: transform;
     }
 
     #overlap {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-3d.html b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-3d.html
index f356164..726d128d 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-3d.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-3d.html
@@ -86,4 +86,4 @@
   </div>
   <pre id="layers">Layer tree goes here in DRT</pre>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped.html b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped.html
index adbc180..c465fc4 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped.html
@@ -8,7 +8,7 @@
     }
 
     .composited {
-        transform: translateZ(0px);
+        will-change: transform;
     }
 
     .clips {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-layer-with-transform-body.html b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-layer-with-transform-body.html
index ec57ba5..cefa2685 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-layer-with-transform-body.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-layer-with-transform-body.html
@@ -26,7 +26,7 @@
     #composited {
         position: absolute;
         left: 400px;
-        transform:translateZ(0);
+        will-change: transform;
     }
 
     #layertree {
@@ -36,7 +36,7 @@
     }
 
     body {
-        transform:translateZ(0);
+        will-change: transform;
         overflow: hidden;
     }
 
diff --git a/third_party/blink/web_tests/compositing/layer-creation/remove-clipping-layer-with-no-children.html b/third_party/blink/web_tests/compositing/layer-creation/remove-clipping-layer-with-no-children.html
index 63cc8686..bdbaadc 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/remove-clipping-layer-with-no-children.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/remove-clipping-layer-with-no-children.html
@@ -5,7 +5,7 @@
   width: 400px;
   height: 400px;
   background-color: pink;
-  transform: translateZ(0)
+  will-change: transform
 }
 
 #child {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/resources/fixed-position-nonscrollable-body.html b/third_party/blink/web_tests/compositing/layer-creation/resources/fixed-position-nonscrollable-body.html
index 433feab..17a8d365 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/resources/fixed-position-nonscrollable-body.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/resources/fixed-position-nonscrollable-body.html
@@ -33,7 +33,7 @@
     }
 
     .composited {
-        transform: translatez(0);
+        will-change: transform;
     }
   </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/layer-creation/rotate3d-overlap.html b/third_party/blink/web_tests/compositing/layer-creation/rotate3d-overlap.html
index 12d99ff..c378384 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/rotate3d-overlap.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/rotate3d-overlap.html
@@ -16,15 +16,17 @@
     }
 
     .translateZ {
-      transform: translateZ(0);
+      will-change: transform;
     }
 
     .rotate15 {
       transform: rotate3d(0, 0, 1, 15deg);
+      will-change: transform;
     }
 
     .rotate45 {
       transform: rotate3d(0, 0, 1, 45deg);
+      will-change: transform;
     }
   </style>
   <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/layer-creation/scroll-partial-update.html b/third_party/blink/web_tests/compositing/layer-creation/scroll-partial-update.html
index 06d3354..ed56af34 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/scroll-partial-update.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/scroll-partial-update.html
@@ -22,7 +22,7 @@
       }
 
       #composited {
-        transform: translateZ(0);
+        will-change: transform;
         width: 20px;
         height: 20px;
       }
diff --git a/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change.html b/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change.html
index 4d1705a..d4dcbec 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change.html
@@ -23,7 +23,7 @@
   top: 50px;
   width: 100px;
   height: 100px;
-  transform: translateZ(0);
+  will-change: transform;
   background-color: salmon;
 }
 
diff --git a/third_party/blink/web_tests/compositing/layer-creation/stacking-context-overlap-nested.html b/third_party/blink/web_tests/compositing/layer-creation/stacking-context-overlap-nested.html
index caefa7a..1241488 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/stacking-context-overlap-nested.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/stacking-context-overlap-nested.html
@@ -14,6 +14,7 @@
 
     .composited {
       transform: translateZ(0);
+      will-change: transform;
       background-color: green;
       outline: 10px solid transparent; /* inflate compositing layer bounds */
     }
diff --git a/third_party/blink/web_tests/compositing/layer-creation/stacking-context-overlap.html b/third_party/blink/web_tests/compositing/layer-creation/stacking-context-overlap.html
index 00b38094..e238170 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/stacking-context-overlap.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/stacking-context-overlap.html
@@ -7,7 +7,7 @@
             width: 20px;
             height: 20px;
             background-color: blue;
-            transform: translateZ(0);
+            will-change: transform;
         }
 
         .container {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/translatez-added.html b/third_party/blink/web_tests/compositing/layer-creation/translatez-added.html
index 2fd98e0..4b84b896 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/translatez-added.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/translatez-added.html
@@ -12,7 +12,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
 
   </style>
diff --git a/third_party/blink/web_tests/compositing/layer-creation/translatez-overlap.html b/third_party/blink/web_tests/compositing/layer-creation/translatez-overlap.html
index dd56b867..407bfa0 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/translatez-overlap.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/translatez-overlap.html
@@ -11,7 +11,7 @@
     }
     
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
   </style>
   <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/layer-creation/translatez-removed.html b/third_party/blink/web_tests/compositing/layer-creation/translatez-removed.html
index e20f430..ce1004d 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/translatez-removed.html
+++ b/third_party/blink/web_tests/compositing/layer-creation/translatez-removed.html
@@ -9,7 +9,7 @@
 }
 
 .composited {
-    transform: translateZ(0);
+    will-change: transform;
 }
 
 #trigger {
diff --git a/third_party/blink/web_tests/compositing/layers-inside-overflow-scroll.html b/third_party/blink/web_tests/compositing/layers-inside-overflow-scroll.html
index 16191b6..d2be34b 100644
--- a/third_party/blink/web_tests/compositing/layers-inside-overflow-scroll.html
+++ b/third_party/blink/web_tests/compositing/layers-inside-overflow-scroll.html
@@ -30,7 +30,7 @@
       height: 100px;
       width: 100px;
       background-color: red;
-      transform: translateZ(0);
+      will-change: transform;
     }
     </style>
     <script src="resources/media-testing.js"></script>
diff --git a/third_party/blink/web_tests/compositing/layout-width-change.html b/third_party/blink/web_tests/compositing/layout-width-change.html
index 30e8ed4..f1317c04 100644
--- a/third_party/blink/web_tests/compositing/layout-width-change.html
+++ b/third_party/blink/web_tests/compositing/layout-width-change.html
@@ -20,7 +20,7 @@
   }
 
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   </style>
   <script src="../resources/run-after-layout-and-paint.js"></script>
diff --git a/third_party/blink/web_tests/compositing/lots-of-img-layers-with-opacity.html b/third_party/blink/web_tests/compositing/lots-of-img-layers-with-opacity.html
index 1744689..0de4cf8 100644
--- a/third_party/blink/web_tests/compositing/lots-of-img-layers-with-opacity.html
+++ b/third_party/blink/web_tests/compositing/lots-of-img-layers-with-opacity.html
@@ -3,8 +3,9 @@
 <script>
 for (var i=0; i<350; ++i) {
     var img = document.createElement("img");
-    img.style.webkitTransform = "rotate("+(i/2)+"deg) translateZ(0)";
-    img.style.webkitTransformOrigin = "300px 300px";
+    img.style.transform = "rotate("+(i/2)+"deg)";
+    img.style.willChange = "transform";
+    img.style.transformOrigin = "300px 300px";
     img.style.position = "absolute";
     img.style.opacity = 0.2;
     document.body.appendChild(img);
diff --git a/third_party/blink/web_tests/compositing/lots-of-img-layers.html b/third_party/blink/web_tests/compositing/lots-of-img-layers.html
index f22389e..05c919b 100644
--- a/third_party/blink/web_tests/compositing/lots-of-img-layers.html
+++ b/third_party/blink/web_tests/compositing/lots-of-img-layers.html
@@ -3,8 +3,9 @@
 <script>
 for (var i=0; i<350; ++i) {
     var img = document.createElement("img");
-    img.style.webkitTransform = "rotate("+i+"deg) translateZ(0)";
-    img.style.webkitTransformOrigin = "300px 300px";
+    img.style.transform = "rotate("+i+"deg)";
+    img.style.willChange = "transform";
+    img.style.transformOrigin = "300px 300px";
     img.style.position = "absolute";
     document.body.appendChild(img);
     img.src = "resources/apple.jpg";
diff --git a/third_party/blink/web_tests/compositing/masks/direct-image-mask.html b/third_party/blink/web_tests/compositing/masks/direct-image-mask.html
index 6288b47..722cc3e 100644
--- a/third_party/blink/web_tests/compositing/masks/direct-image-mask.html
+++ b/third_party/blink/web_tests/compositing/masks/direct-image-mask.html
@@ -10,7 +10,7 @@
       }
 
       .compositing {
-        transform: translateZ(0);
+        will-change: transform;
       }
 
       .masked {
diff --git a/third_party/blink/web_tests/compositing/masks/mask-layer-size.html b/third_party/blink/web_tests/compositing/masks/mask-layer-size.html
index faa47d4..03541f6 100644
--- a/third_party/blink/web_tests/compositing/masks/mask-layer-size.html
+++ b/third_party/blink/web_tests/compositing/masks/mask-layer-size.html
@@ -17,7 +17,7 @@
         -webkit-mask-position: 0px 0px;
         -webkit-mask-size: 200px 200px;
         -webkit-mask-repeat: no-repeat;
-        transform: translateZ(0);
+        will-change: transform;
     }
 
     #layers {
diff --git a/third_party/blink/web_tests/compositing/masks/mask-of-clipped-layer.html b/third_party/blink/web_tests/compositing/masks/mask-of-clipped-layer.html
index 2f7b258..3a41f772 100644
--- a/third_party/blink/web_tests/compositing/masks/mask-of-clipped-layer.html
+++ b/third_party/blink/web_tests/compositing/masks/mask-of-clipped-layer.html
@@ -16,7 +16,7 @@
       }
 
       .composited {
-        transform: translatez(0);
+        will-change: transform;
       }
 
       .masked {
diff --git a/third_party/blink/web_tests/compositing/masks/mask-with-removed-filters.html b/third_party/blink/web_tests/compositing/masks/mask-with-removed-filters.html
index 03ca93a..a833c93 100644
--- a/third_party/blink/web_tests/compositing/masks/mask-with-removed-filters.html
+++ b/third_party/blink/web_tests/compositing/masks/mask-with-removed-filters.html
@@ -13,7 +13,7 @@
 }
 
 .composited {
-  transform: translateZ(0px);
+  will-change: transform;
 }
 
 .alpha-color {
diff --git a/third_party/blink/web_tests/compositing/masks/masked-ancestor.html b/third_party/blink/web_tests/compositing/masks/masked-ancestor.html
index 545f0a21..4d9260f3 100644
--- a/third_party/blink/web_tests/compositing/masks/masked-ancestor.html
+++ b/third_party/blink/web_tests/compositing/masks/masked-ancestor.html
@@ -16,7 +16,7 @@
       }
 
       .compositing {
-        transform: translateZ(0);
+        will-change: transform;
       }
 
       .masked {
diff --git a/third_party/blink/web_tests/compositing/masks/multiple-masks.html b/third_party/blink/web_tests/compositing/masks/multiple-masks.html
index 2d1f46c..07336ba 100644
--- a/third_party/blink/web_tests/compositing/masks/multiple-masks.html
+++ b/third_party/blink/web_tests/compositing/masks/multiple-masks.html
@@ -22,7 +22,7 @@
       }
 
       .compositing {
-        transform: translateZ(0);
+        will-change: transform;
       }
 
       #container .masked {
diff --git a/third_party/blink/web_tests/compositing/masks/simple-composited-mask.html b/third_party/blink/web_tests/compositing/masks/simple-composited-mask.html
index 44901db..f2b9ff7 100644
--- a/third_party/blink/web_tests/compositing/masks/simple-composited-mask.html
+++ b/third_party/blink/web_tests/compositing/masks/simple-composited-mask.html
@@ -22,7 +22,7 @@
       }
 
       .compositing {
-        transform: translateZ(0);
+        will-change: transform;
       }
 
       #container .masked {
diff --git a/third_party/blink/web_tests/compositing/objects/resources/composited-subframe.html b/third_party/blink/web_tests/compositing/objects/resources/composited-subframe.html
index 81ff6195..54c6f8b 100644
--- a/third_party/blink/web_tests/compositing/objects/resources/composited-subframe.html
+++ b/third_party/blink/web_tests/compositing/objects/resources/composited-subframe.html
@@ -8,7 +8,7 @@
         width: 200px;
         margin: 10px;
         background-color: green;
-        transform: translateZ(0);
+        will-change: transform;
     }
   </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/overflow/clip-content-under-overflow-controls.html b/third_party/blink/web_tests/compositing/overflow/clip-content-under-overflow-controls.html
index 9e9a791..d102251d 100644
--- a/third_party/blink/web_tests/compositing/overflow/clip-content-under-overflow-controls.html
+++ b/third_party/blink/web_tests/compositing/overflow/clip-content-under-overflow-controls.html
@@ -2,7 +2,7 @@
 <!DOCTYPE html>
 <style>
 .composited {
-  transform: translateZ(0);
+  will-change: transform;
 }
 
 .container {
diff --git a/third_party/blink/web_tests/compositing/overflow/clip-parent-of-non-scrolled-expected.html b/third_party/blink/web_tests/compositing/overflow/clip-parent-of-non-scrolled-expected.html
index 3b589993..cbbb1f5 100644
--- a/third_party/blink/web_tests/compositing/overflow/clip-parent-of-non-scrolled-expected.html
+++ b/third_party/blink/web_tests/compositing/overflow/clip-parent-of-non-scrolled-expected.html
@@ -12,6 +12,7 @@
     height: 100px;
     background: green;
     transform: translate3d(50px, 50px, 0);
+    will-change: transform;
 }
 </style>
 <div id="escaped-clip">
diff --git a/third_party/blink/web_tests/compositing/overflow/clip-parent-of-non-scrolled.html b/third_party/blink/web_tests/compositing/overflow/clip-parent-of-non-scrolled.html
index 83d69811..2b9ffc7 100644
--- a/third_party/blink/web_tests/compositing/overflow/clip-parent-of-non-scrolled.html
+++ b/third_party/blink/web_tests/compositing/overflow/clip-parent-of-non-scrolled.html
@@ -13,6 +13,7 @@
     height: 100px;
     background: green;
     transform: translate3d(50px, 50px, 0);
+    will-change: transform;
 }
 </style>
 <div id="escaped-clip">
diff --git a/third_party/blink/web_tests/compositing/overflow/clip-parent-reset.html b/third_party/blink/web_tests/compositing/overflow/clip-parent-reset.html
index 53cde661..ae85de3d 100644
--- a/third_party/blink/web_tests/compositing/overflow/clip-parent-reset.html
+++ b/third_party/blink/web_tests/compositing/overflow/clip-parent-reset.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <div style="width:150px; height:150px; overflow:hidden; opacity:0.8; background:red;">
     <div style="width:100px; height:100px; overflow:hidden;">
-        <div id="bug" style="width:200px; height:200px; position:absolute; transform:translateZ(0); background:green;">
+        <div id="bug" style="width:200px; height:200px; position:absolute; will-change:transform; background:green;">
         </div>
     </div>
 </div>
diff --git a/third_party/blink/web_tests/compositing/overflow/composited-scrolling-paint-phases.html b/third_party/blink/web_tests/compositing/overflow/composited-scrolling-paint-phases.html
index 3005951..140ec3a 100644
--- a/third_party/blink/web_tests/compositing/overflow/composited-scrolling-paint-phases.html
+++ b/third_party/blink/web_tests/compositing/overflow/composited-scrolling-paint-phases.html
@@ -17,7 +17,7 @@
       height: 10px;
       position: relative;
       top: 10px;
-      transform: translateZ(0);
+      will-change: transform;
       background-color: green;
       z-index: -1;
     }
diff --git a/third_party/blink/web_tests/compositing/overflow/content-gains-scrollbars.html b/third_party/blink/web_tests/compositing/overflow/content-gains-scrollbars.html
index 407cdcbf6..dc40e2d 100644
--- a/third_party/blink/web_tests/compositing/overflow/content-gains-scrollbars.html
+++ b/third_party/blink/web_tests/compositing/overflow/content-gains-scrollbars.html
@@ -5,12 +5,12 @@
 width: 100px;
 height:100px;
 position:absolute;
-transform:translateZ(0);
+will-change: transform;
 overflow:auto;
 }
 
 .content {
-transform: translateZ(0);
+will-change:transform;
 position:absolute;
 width:10px;
 height:10px;
diff --git a/third_party/blink/web_tests/compositing/overflow/nested-render-surfaces-with-rotation.html b/third_party/blink/web_tests/compositing/overflow/nested-render-surfaces-with-rotation.html
index d409788..bd1e356 100644
--- a/third_party/blink/web_tests/compositing/overflow/nested-render-surfaces-with-rotation.html
+++ b/third_party/blink/web_tests/compositing/overflow/nested-render-surfaces-with-rotation.html
@@ -42,11 +42,13 @@
     }
 
     .rotated {
-      transform: translateZ(0) rotate(5deg);
+      transform: rotate(5deg);
+      will-change: transform;
     }
 
     .counter-rotated {
-      transform: translateZ(0) rotate(-9deg);
+      transform: rotate(-9deg);
+      will-change: transform;
     }
 </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/overflow/opt-in-if-composited.html b/third_party/blink/web_tests/compositing/overflow/opt-in-if-composited.html
index da18928..a25883c 100644
--- a/third_party/blink/web_tests/compositing/overflow/opt-in-if-composited.html
+++ b/third_party/blink/web_tests/compositing/overflow/opt-in-if-composited.html
@@ -20,7 +20,7 @@
             result += "Fail.\n"
     }
 
-    document.getElementById("scroller").style.webkitTransform = "translateZ(0)";
+    document.getElementById("scroller").style.willChange = "transform";
     requestAnimationFrame(function() {
         if (window.internals) {
             result += "Should be using composited scrolling (since we're compositing anyhow): ";
@@ -30,7 +30,7 @@
                 result += "Fail.\n"
         }
 
-        document.getElementById("scroller").style.webkitTransform = "";
+        document.getElementById("scroller").style.willChange = "";
         requestAnimationFrame(function() {
             if (window.internals) {
                 result += "Should not be using composited scrolling (since we've lost our direct reason): ";
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-pointer-events-toggle.html b/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-pointer-events-toggle.html
index 9552d526..e0c1533 100644
--- a/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-pointer-events-toggle.html
+++ b/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-pointer-events-toggle.html
@@ -2,7 +2,7 @@
 <script src="resources/composited-scroll.js"></script>
 <style>
 .composited {
-  transform: translateZ(0);
+  will-change: transform;
 }
 .scroller {
   width: 300px;
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-scrollbar-layers.html b/third_party/blink/web_tests/compositing/overflow/overflow-scrollbar-layers.html
index f510a23..4cadbc9c 100644
--- a/third_party/blink/web_tests/compositing/overflow/overflow-scrollbar-layers.html
+++ b/third_party/blink/web_tests/compositing/overflow/overflow-scrollbar-layers.html
@@ -4,12 +4,12 @@
 width: 100px;
 height:100px;
 position:absolute;
-transform:translateZ(0);
+will-change:transform;
 overflow:auto;
 }
 
 .content {
-transform: translateZ(0);
+will-change:transform;
 position:absolute;
 width:10px;
 height:10px;
diff --git a/third_party/blink/web_tests/compositing/overflow/resize-painting.html b/third_party/blink/web_tests/compositing/overflow/resize-painting.html
index 2b79b21d..c89a5b3a 100644
--- a/third_party/blink/web_tests/compositing/overflow/resize-painting.html
+++ b/third_party/blink/web_tests/compositing/overflow/resize-painting.html
@@ -3,7 +3,7 @@
 <head>
   <style>
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   
   .box {
diff --git a/third_party/blink/web_tests/compositing/overflow/resources/composited-subframe.html b/third_party/blink/web_tests/compositing/overflow/resources/composited-subframe.html
index 92b3b7f..be73930 100644
--- a/third_party/blink/web_tests/compositing/overflow/resources/composited-subframe.html
+++ b/third_party/blink/web_tests/compositing/overflow/resources/composited-subframe.html
@@ -11,7 +11,7 @@
         margin: 10px;
         padding: 5px;
         background-color: blue;
-        transform: translateZ(0);
+        will-change: transform;
         overflow:hidden;
     }
     .box:hover {
diff --git a/third_party/blink/web_tests/compositing/overflow/scrollbar-painting.html b/third_party/blink/web_tests/compositing/overflow/scrollbar-painting.html
index 7dbe2e0..7cdeaa0 100644
--- a/third_party/blink/web_tests/compositing/overflow/scrollbar-painting.html
+++ b/third_party/blink/web_tests/compositing/overflow/scrollbar-painting.html
@@ -3,7 +3,7 @@
 <head>
   <style>
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   
   .box {
diff --git a/third_party/blink/web_tests/compositing/overflow/theme-affects-visual-overflow.html b/third_party/blink/web_tests/compositing/overflow/theme-affects-visual-overflow.html
index 63e6606..04b05dc 100644
--- a/third_party/blink/web_tests/compositing/overflow/theme-affects-visual-overflow.html
+++ b/third_party/blink/web_tests/compositing/overflow/theme-affects-visual-overflow.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 .composited {
-    transform: translatez(0);
+    will-change: transform;
 }
 input {
     position:relative;
diff --git a/third_party/blink/web_tests/compositing/overflow/transform-in-empty-container.html b/third_party/blink/web_tests/compositing/overflow/transform-in-empty-container.html
index e25845f..7d990d5 100644
--- a/third_party/blink/web_tests/compositing/overflow/transform-in-empty-container.html
+++ b/third_party/blink/web_tests/compositing/overflow/transform-in-empty-container.html
@@ -3,7 +3,7 @@
 <title>Transform in an empty container test.</title>
 <style type="text/css">
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   .abs {
     position: absolute;
diff --git a/third_party/blink/web_tests/compositing/overlap-blending/children-opacity-huge.html b/third_party/blink/web_tests/compositing/overlap-blending/children-opacity-huge.html
index 749550d..94c7602 100644
--- a/third_party/blink/web_tests/compositing/overlap-blending/children-opacity-huge.html
+++ b/third_party/blink/web_tests/compositing/overlap-blending/children-opacity-huge.html
@@ -19,7 +19,7 @@
       .b { top: 100px; left: 0px;}
       
       .composited {
-        transform: translateZ(0);
+        will-change: transform;
       }
 
       * { margin: 0; padding: 0; }
diff --git a/third_party/blink/web_tests/compositing/overlap-blending/children-opacity-no-overlap.html b/third_party/blink/web_tests/compositing/overlap-blending/children-opacity-no-overlap.html
index be8b234..3a496d3 100644
--- a/third_party/blink/web_tests/compositing/overlap-blending/children-opacity-no-overlap.html
+++ b/third_party/blink/web_tests/compositing/overlap-blending/children-opacity-no-overlap.html
@@ -21,7 +21,7 @@
       .d { top: 0px; left: 200px;}
       
       .composited {
-        transform: translateZ(0);
+        will-change: transform;
       }
       * { margin: 0; padding: 0; }
 
diff --git a/third_party/blink/web_tests/compositing/overlap-blending/reflection-opacity-huge.html b/third_party/blink/web_tests/compositing/overlap-blending/reflection-opacity-huge.html
index 0b908a3..561e37c 100644
--- a/third_party/blink/web_tests/compositing/overlap-blending/reflection-opacity-huge.html
+++ b/third_party/blink/web_tests/compositing/overlap-blending/reflection-opacity-huge.html
@@ -12,7 +12,7 @@
         -webkit-box-reflect: below -50px;
       }
       
-      .composited { transform: translateZ(0);}
+      .composited { will-change: transform;}
       * { margin: 0; padding: 0; }
 
     </style>
diff --git a/third_party/blink/web_tests/compositing/reflections/animation-inside-reflection.html b/third_party/blink/web_tests/compositing/reflections/animation-inside-reflection.html
index 07c63edf..9654dbe 100644
--- a/third_party/blink/web_tests/compositing/reflections/animation-inside-reflection.html
+++ b/third_party/blink/web_tests/compositing/reflections/animation-inside-reflection.html
@@ -40,7 +40,7 @@
   }
 
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
 
   @keyframes swing {
diff --git a/third_party/blink/web_tests/compositing/reflections/compositing-change-inside-reflection.html b/third_party/blink/web_tests/compositing/reflections/compositing-change-inside-reflection.html
index cb9a25e..e435441c 100644
--- a/third_party/blink/web_tests/compositing/reflections/compositing-change-inside-reflection.html
+++ b/third_party/blink/web_tests/compositing/reflections/compositing-change-inside-reflection.html
@@ -22,7 +22,7 @@
       background-color: green;
     }
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     .container {
diff --git a/third_party/blink/web_tests/compositing/reflections/deeply-nested-reflections.html b/third_party/blink/web_tests/compositing/reflections/deeply-nested-reflections.html
index 5d07ac2..c40caf3b 100644
--- a/third_party/blink/web_tests/compositing/reflections/deeply-nested-reflections.html
+++ b/third_party/blink/web_tests/compositing/reflections/deeply-nested-reflections.html
@@ -49,7 +49,7 @@
       background-color: green;
     }
     .compositing {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
   </style>
diff --git a/third_party/blink/web_tests/compositing/reflections/masked-reflection-on-composited-huge.html b/third_party/blink/web_tests/compositing/reflections/masked-reflection-on-composited-huge.html
index 4f855f9e..2778080 100644
--- a/third_party/blink/web_tests/compositing/reflections/masked-reflection-on-composited-huge.html
+++ b/third_party/blink/web_tests/compositing/reflections/masked-reflection-on-composited-huge.html
@@ -13,7 +13,7 @@
   }
 
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
 </style>
 <p>Reflection should be masked with gradient.</p>
diff --git a/third_party/blink/web_tests/compositing/reflections/masked-reflection-on-composited.html b/third_party/blink/web_tests/compositing/reflections/masked-reflection-on-composited.html
index 1cc63105..74ea302 100644
--- a/third_party/blink/web_tests/compositing/reflections/masked-reflection-on-composited.html
+++ b/third_party/blink/web_tests/compositing/reflections/masked-reflection-on-composited.html
@@ -16,7 +16,7 @@
     }
 
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
   </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/reflections/nested-reflection-anchor-point.html b/third_party/blink/web_tests/compositing/reflections/nested-reflection-anchor-point.html
index d5530ed..dc8c527 100644
--- a/third_party/blink/web_tests/compositing/reflections/nested-reflection-anchor-point.html
+++ b/third_party/blink/web_tests/compositing/reflections/nested-reflection-anchor-point.html
@@ -21,6 +21,7 @@
     font-size: 50pt;
     -webkit-box-reflect: below 10px;
     transform: rotate3d(0, 0, 1, 20deg);
+    will-change: transform;
   }
   
   .changed {
diff --git a/third_party/blink/web_tests/compositing/reflections/nested-reflection-animated.html b/third_party/blink/web_tests/compositing/reflections/nested-reflection-animated.html
index ce58291e..aac67ed 100644
--- a/third_party/blink/web_tests/compositing/reflections/nested-reflection-animated.html
+++ b/third_party/blink/web_tests/compositing/reflections/nested-reflection-animated.html
@@ -30,7 +30,7 @@
   }
   
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   
   @-webkit-keyframes swing {
diff --git a/third_party/blink/web_tests/compositing/reflections/nested-reflection-mask-change.html b/third_party/blink/web_tests/compositing/reflections/nested-reflection-mask-change.html
index ec19e55..31d04ed 100644
--- a/third_party/blink/web_tests/compositing/reflections/nested-reflection-mask-change.html
+++ b/third_party/blink/web_tests/compositing/reflections/nested-reflection-mask-change.html
@@ -22,7 +22,7 @@
   }
   
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   
   .masked {
diff --git a/third_party/blink/web_tests/compositing/reflections/nested-reflection-on-overflow.html b/third_party/blink/web_tests/compositing/reflections/nested-reflection-on-overflow.html
index 5cbcd40c..24eb451 100644
--- a/third_party/blink/web_tests/compositing/reflections/nested-reflection-on-overflow.html
+++ b/third_party/blink/web_tests/compositing/reflections/nested-reflection-on-overflow.html
@@ -20,7 +20,7 @@
   }
   
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
 
   .overflow {
diff --git a/third_party/blink/web_tests/compositing/reflections/nested-reflection-opacity.html b/third_party/blink/web_tests/compositing/reflections/nested-reflection-opacity.html
index f089f6e..c2f8fcd 100644
--- a/third_party/blink/web_tests/compositing/reflections/nested-reflection-opacity.html
+++ b/third_party/blink/web_tests/compositing/reflections/nested-reflection-opacity.html
@@ -22,7 +22,7 @@
   }
   
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   </style>
   <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/reflections/nested-reflection-transformed.html b/third_party/blink/web_tests/compositing/reflections/nested-reflection-transformed.html
index 475e1dc..e9ad8bc7 100644
--- a/third_party/blink/web_tests/compositing/reflections/nested-reflection-transformed.html
+++ b/third_party/blink/web_tests/compositing/reflections/nested-reflection-transformed.html
@@ -9,6 +9,8 @@
     margin: 20px;
     border: 1px solid black;
     -webkit-box-reflect: right 10px;
+    will-change: transform;
+    transform: translateZ(0);
   }
   
   .inner {
@@ -19,9 +21,6 @@
     text-align: center;
     font-size: 50pt;
     -webkit-box-reflect: below 10px;
-  }
-  
-  .composited {
     transform: translateZ(0);
   }
   </style>
@@ -35,8 +34,8 @@
   </head>
 <body>
   <p>Test transform change on reflected elements. Left and right side should be symmetrical.</p>
-  <div class="outer composited">
-    <div id="inner" class="inner composited">
+  <div class="outer">
+    <div id="inner" class="inner">
       1
     </div>
   </div>
diff --git a/third_party/blink/web_tests/compositing/reflections/nested-reflection-transformed2.html b/third_party/blink/web_tests/compositing/reflections/nested-reflection-transformed2.html
index 162a215..fb5fe7f 100644
--- a/third_party/blink/web_tests/compositing/reflections/nested-reflection-transformed2.html
+++ b/third_party/blink/web_tests/compositing/reflections/nested-reflection-transformed2.html
@@ -10,6 +10,8 @@
     border: 1px solid black;
     -webkit-box-reflect: right 10px;
     outline: 10px solid transparent; /* affects layer sizes */
+    will-change: transform;
+    transform: translateZ(0);
   }
   
   .inner {
@@ -20,9 +22,6 @@
     text-align: center;
     font-size: 50pt;
     -webkit-box-reflect: below 10px;
-  }
-  
-  .composited {
     transform: translateZ(0);
   }
   </style>
@@ -36,8 +35,8 @@
   </head>
 <body>
   <p>Test transform change on reflected elements, with compositing layers larger than render layers. Left and right side should be symmetrical.</p>
-  <div class="outer composited">
-    <div id="inner" class="inner composited">
+  <div class="outer">
+    <div id="inner" class="inner">
       1
     </div>
   </div>
diff --git a/third_party/blink/web_tests/compositing/reflections/nested-reflection-transition.html b/third_party/blink/web_tests/compositing/reflections/nested-reflection-transition.html
index f4321414..2a6cd963 100644
--- a/third_party/blink/web_tests/compositing/reflections/nested-reflection-transition.html
+++ b/third_party/blink/web_tests/compositing/reflections/nested-reflection-transition.html
@@ -31,7 +31,7 @@
     transform: rotate(90deg);
   }
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   </style>
   <script src="../../animations/resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script>
diff --git a/third_party/blink/web_tests/compositing/reflections/nested-reflection.html b/third_party/blink/web_tests/compositing/reflections/nested-reflection.html
index 61530a7..5e5b08e 100644
--- a/third_party/blink/web_tests/compositing/reflections/nested-reflection.html
+++ b/third_party/blink/web_tests/compositing/reflections/nested-reflection.html
@@ -22,7 +22,7 @@
   }
   
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
 
   </style>
diff --git a/third_party/blink/web_tests/compositing/reflections/reflection-in-composited.html b/third_party/blink/web_tests/compositing/reflections/reflection-in-composited.html
index 73a7717..95883ee 100644
--- a/third_party/blink/web_tests/compositing/reflections/reflection-in-composited.html
+++ b/third_party/blink/web_tests/compositing/reflections/reflection-in-composited.html
@@ -9,7 +9,7 @@
         height: 150px;
         padding: 10px 20px;
         border: 1px solid black;
-        transform: translateZ(0);
+        will-change: transform;
       }
       
       .positioned {
diff --git a/third_party/blink/web_tests/compositing/reflections/reflection-opacity.html b/third_party/blink/web_tests/compositing/reflections/reflection-opacity.html
index 485867f..5400b10 100644
--- a/third_party/blink/web_tests/compositing/reflections/reflection-opacity.html
+++ b/third_party/blink/web_tests/compositing/reflections/reflection-opacity.html
@@ -17,7 +17,7 @@
       }
       
       .composited {
-        transform: translateZ(0);
+        will-change: transform;
       }
 
     </style>
diff --git a/third_party/blink/web_tests/compositing/reflections/reflection-ordering.html b/third_party/blink/web_tests/compositing/reflections/reflection-ordering.html
index 7df00f3..d4e9af73 100644
--- a/third_party/blink/web_tests/compositing/reflections/reflection-ordering.html
+++ b/third_party/blink/web_tests/compositing/reflections/reflection-ordering.html
@@ -14,12 +14,12 @@
       font-size: 18pt;
       text-align: center;
       background-color: white;
-      transform: translateZ(0);
+      will-change: transform;
       -webkit-box-reflect: below -80px;
     }
 
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
   </style>
 </head>
diff --git a/third_party/blink/web_tests/compositing/reflections/reflection-positioning.html b/third_party/blink/web_tests/compositing/reflections/reflection-positioning.html
index f54aa136..d2bee00 100644
--- a/third_party/blink/web_tests/compositing/reflections/reflection-positioning.html
+++ b/third_party/blink/web_tests/compositing/reflections/reflection-positioning.html
@@ -33,7 +33,7 @@
       }
 
       .composited {
-        transform: translateZ(0);
+        will-change: transform;
       }
 
       .inner.moved {
diff --git a/third_party/blink/web_tests/compositing/reflections/reflection-positioning2.html b/third_party/blink/web_tests/compositing/reflections/reflection-positioning2.html
index b272786..5f9fb127 100644
--- a/third_party/blink/web_tests/compositing/reflections/reflection-positioning2.html
+++ b/third_party/blink/web_tests/compositing/reflections/reflection-positioning2.html
@@ -34,7 +34,7 @@
       }
 
       .composited {
-        transform: translateZ(0);
+        will-change: transform;
       }
 
       .inner.moved {
diff --git a/third_party/blink/web_tests/compositing/reflections/simple-composited-reflections.html b/third_party/blink/web_tests/compositing/reflections/simple-composited-reflections.html
index 2692d1ca..0833320 100644
--- a/third_party/blink/web_tests/compositing/reflections/simple-composited-reflections.html
+++ b/third_party/blink/web_tests/compositing/reflections/simple-composited-reflections.html
@@ -10,7 +10,7 @@
       }
 
       .compositing {
-        transform: translateZ(0);
+        will-change: transform;
       }
 
       .reflected {
diff --git a/third_party/blink/web_tests/compositing/reflections/transform-inside-reflection.html b/third_party/blink/web_tests/compositing/reflections/transform-inside-reflection.html
index d4e9547..6f97679e2 100644
--- a/third_party/blink/web_tests/compositing/reflections/transform-inside-reflection.html
+++ b/third_party/blink/web_tests/compositing/reflections/transform-inside-reflection.html
@@ -26,6 +26,7 @@
     background-color: green;
     text-align: center;
     font-size: 50pt;
+    will-change: transform;
   }
   
   </style>
diff --git a/third_party/blink/web_tests/compositing/rendering-contexts.html b/third_party/blink/web_tests/compositing/rendering-contexts.html
index 3504d20..d954fa02 100644
--- a/third_party/blink/web_tests/compositing/rendering-contexts.html
+++ b/third_party/blink/web_tests/compositing/rendering-contexts.html
@@ -7,7 +7,7 @@
   <head>
     <style>
       .composited {
-        transform: translateZ(0);
+        will-change: transform;
         width: 100px;
         height: 100px;
         background-color: green;
diff --git a/third_party/blink/web_tests/compositing/rounded-corners.html b/third_party/blink/web_tests/compositing/rounded-corners.html
index 3905e2f..8616058 100644
--- a/third_party/blink/web_tests/compositing/rounded-corners.html
+++ b/third_party/blink/web_tests/compositing/rounded-corners.html
@@ -2,6 +2,6 @@
 <html>
 <body>
     <!-- Test for https://bugs.webkit.org/show_bug.cgi?id=106898 -->
-    <div style="width: 200px; height: 200px; background: green; border-radius: 25%; transform: translateZ(0);"></div>
+    <div style="width: 200px; height: 200px; background: green; border-radius: 25%; will-change: transform;"></div>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-scrolled.html b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-scrolled.html
index 5617768..e4ccc501 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-scrolled.html
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-scrolled.html
@@ -20,7 +20,7 @@
     }
 
     #layer {
-        transform:translateZ(0);
+        will-change: transform;
         background-color: green;
     }
 
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow.html b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow.html
index e237ae1..abb8fe1 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow.html
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow.html
@@ -20,7 +20,7 @@
     }
 
     .layer {
-        transform:translateZ(0);
+        will-change: transform;
         background-color: green;
     }
 
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-absolute.html b/third_party/blink/web_tests/compositing/rtl/rtl-absolute.html
index ed638f3..11237e7 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-absolute.html
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-absolute.html
@@ -20,7 +20,7 @@
     }
 
     .layer {
-        transform:translateZ(0);
+        will-change: transform;
         background-color: green;
     }
 
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-fixed.html b/third_party/blink/web_tests/compositing/rtl/rtl-fixed.html
index 2af0fce0..5f4d914 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-fixed.html
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-fixed.html
@@ -20,7 +20,7 @@
     }
 
     .layer {
-        transform:translateZ(0);
+        will-change: transform;
         background-color: green;
     }
 
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-relative.html b/third_party/blink/web_tests/compositing/rtl/rtl-relative.html
index 483011e..4832401 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-relative.html
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-relative.html
@@ -16,7 +16,7 @@
     }
 
     #layer {
-        transform:translateZ(0);
+        will-change: transform;
         position: relative;
         top: 50px;
         right: 50px;
diff --git a/third_party/blink/web_tests/compositing/scaling/tiled-layer-recursion.html b/third_party/blink/web_tests/compositing/scaling/tiled-layer-recursion.html
index 76743de..d13cf60 100644
--- a/third_party/blink/web_tests/compositing/scaling/tiled-layer-recursion.html
+++ b/third_party/blink/web_tests/compositing/scaling/tiled-layer-recursion.html
@@ -11,7 +11,7 @@
       background-color: green;
       width: 200px;
       height: 1333px;
-      transform: translateZ(0);
+      will-change: transform;
     }
   </style>
   <script>
diff --git a/third_party/blink/web_tests/compositing/scrollbar-painting.html b/third_party/blink/web_tests/compositing/scrollbar-painting.html
index d941c05..8ea44b4e 100644
--- a/third_party/blink/web_tests/compositing/scrollbar-painting.html
+++ b/third_party/blink/web_tests/compositing/scrollbar-painting.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <style>
 .composited {
-  transform: translateZ(0);
+  will-change: transform;
 }
 
 .container {
diff --git a/third_party/blink/web_tests/compositing/shadows/shadow-drawing.html b/third_party/blink/web_tests/compositing/shadows/shadow-drawing.html
index adb240a..0fad6bd 100644
--- a/third_party/blink/web_tests/compositing/shadows/shadow-drawing.html
+++ b/third_party/blink/web_tests/compositing/shadows/shadow-drawing.html
@@ -14,7 +14,7 @@
      }
 
      .compositing {
-       transform: translateZ(0);
+       will-change: transform;
      }
      
      .shadowed {
diff --git a/third_party/blink/web_tests/compositing/squashing/add-remove-squashed-layers.html b/third_party/blink/web_tests/compositing/squashing/add-remove-squashed-layers.html
index dc02673..9051b81 100644
--- a/third_party/blink/web_tests/compositing/squashing/add-remove-squashed-layers.html
+++ b/third_party/blink/web_tests/compositing/squashing/add-remove-squashed-layers.html
@@ -10,7 +10,7 @@
 }
 
 .composited {
-  transform: translatez(0);
+  will-change: transform;
   top: 60px;
   left: 60px;
   width: 400px;
diff --git a/third_party/blink/web_tests/compositing/squashing/clipping-ancestor.html b/third_party/blink/web_tests/compositing/squashing/clipping-ancestor.html
index 86a5b67..eb50606 100644
--- a/third_party/blink/web_tests/compositing/squashing/clipping-ancestor.html
+++ b/third_party/blink/web_tests/compositing/squashing/clipping-ancestor.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <style>
 .hoverable:hover {
-    transform: translateZ(0);
+    will-change: transform;
 }
 </style>
 <script>
@@ -17,7 +17,7 @@
   window.addEventListener('load', dumpLayers, false)
 </script>
   <div style="overflow: hidden; height: 10px; width: 200px; background-color: lightblue">
-    <div id="inner" style="transform: translateZ(0); height: 10px; background-color: whitesmoke"></div>
+    <div id="inner" style="will-change: transform; height: 10px; background-color: whitesmoke"></div>
   </div>
   <!-- This div should not sqaush into the inner div, because it is inside an overflow:hidden div which therefore clips differently than this div's parent -->
   <div class="hoverable" style="position:absolute; top: 0px; height:100px; width:100px; background-color: lightgreen"></div>
diff --git a/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z.html b/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z.html
index 818f56d..2a02a00 100644
--- a/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z.html
+++ b/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<div style="transform: translateZ(0);
+<div style="will-change: transform;
             height: 10px;
             width: 10px;
             position: absolute;
diff --git a/third_party/blink/web_tests/compositing/squashing/dont-squash-into-iframes.html b/third_party/blink/web_tests/compositing/squashing/dont-squash-into-iframes.html
index 05dc822..76aa47f 100644
--- a/third_party/blink/web_tests/compositing/squashing/dont-squash-into-iframes.html
+++ b/third_party/blink/web_tests/compositing/squashing/dont-squash-into-iframes.html
@@ -1,4 +1,4 @@
-<iframe style="transform: translateZ(0); position: absolute; top: 0px; left: 0px; height: 100px; width: 100px; background: lightblue"></iframe>
+<iframe style="will-change: transform; position: absolute; top: 0px; left: 0px; height: 100px; width: 100px; background: lightblue"></iframe>
 
 <div style="position: absolute; top: 50px; left: 50px; width: 200px; height: 200px; background: lightgray;"></div>
 <script src="../../resources/run-after-layout-and-paint.js"></script>
@@ -13,4 +13,4 @@
     });
 }
 
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/blink/web_tests/compositing/squashing/dont-squash-into-videos.html b/third_party/blink/web_tests/compositing/squashing/dont-squash-into-videos.html
index 2aa89cab..ea418e9 100644
--- a/third_party/blink/web_tests/compositing/squashing/dont-squash-into-videos.html
+++ b/third_party/blink/web_tests/compositing/squashing/dont-squash-into-videos.html
@@ -1,4 +1,4 @@
-<video style="transform: translateZ(0); position: absolute; top: 0px; left: 0px; height: 100px; width: 100px; background: lightblue"></video>
+<video style="will-change: transform; transform: translateZ(0); position: absolute; top: 0px; left: 0px; height: 100px; width: 100px; background: lightblue"></video>
 
 <div style="position: absolute; top: 50px; left: 50px; width: 200px; height: 200px; background: lightgray;"></div>
 <script src="../../resources/run-after-layout-and-paint.js"></script>
diff --git a/third_party/blink/web_tests/compositing/squashing/iframes-are-never-squashed.html b/third_party/blink/web_tests/compositing/squashing/iframes-are-never-squashed.html
index 1ca862a..44bf8338 100644
--- a/third_party/blink/web_tests/compositing/squashing/iframes-are-never-squashed.html
+++ b/third_party/blink/web_tests/compositing/squashing/iframes-are-never-squashed.html
@@ -1,6 +1,6 @@
 <!doctype html>
 
-<div style="width: 200px; height: 200px; background: lightgray; transform: translateZ(0)"></div>
+<div style="width: 200px; height: 200px; background: lightgray; will-change: transform"></div>
 <iframe style="position: absolute; top: 0px; left: 0px; height: 100px; width: 100px; background: lightblue">
 </iframe>
 <script src="../../resources/run-after-layout-and-paint.js"></script>
diff --git a/third_party/blink/web_tests/compositing/squashing/invisible-layers-should-not-affect-geometry.html b/third_party/blink/web_tests/compositing/squashing/invisible-layers-should-not-affect-geometry.html
index 88762852..85b74e4 100644
--- a/third_party/blink/web_tests/compositing/squashing/invisible-layers-should-not-affect-geometry.html
+++ b/third_party/blink/web_tests/compositing/squashing/invisible-layers-should-not-affect-geometry.html
@@ -18,7 +18,7 @@
       background-color: red;
     }
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
   </style>
   <script>
diff --git a/third_party/blink/web_tests/compositing/squashing/move-squashing-layer.html b/third_party/blink/web_tests/compositing/squashing/move-squashing-layer.html
index 8b27a2c..b51fa23 100644
--- a/third_party/blink/web_tests/compositing/squashing/move-squashing-layer.html
+++ b/third_party/blink/web_tests/compositing/squashing/move-squashing-layer.html
@@ -19,11 +19,11 @@
         background-color: green;
         top: 100px;
         z-index: 1;
-        transform:translateZ(0);
+        will-change: transform;
       }
 
       #background {
-        transform:translateZ(0);
+        will-change: transform;
         z-index: 0;
         position: absolute;
         top: 50px;
diff --git a/third_party/blink/web_tests/compositing/squashing/no-squashing-for-filters.html b/third_party/blink/web_tests/compositing/squashing/no-squashing-for-filters.html
index 0f42a457..7c6a278 100644
--- a/third_party/blink/web_tests/compositing/squashing/no-squashing-for-filters.html
+++ b/third_party/blink/web_tests/compositing/squashing/no-squashing-for-filters.html
@@ -4,7 +4,7 @@
     width: 50px; height: 50px; background: lightgray
 }
 </style>
-<div style="width: 100px; height: 100px; transform: translateZ(0); background: lightblue"></div>
+<div style="width: 100px; height: 100px; will-change: transform; background: lightblue"></div>
 <div class="trysquashed" style="position: absolute; top: 0px; left: 0px; -webkit-filter: drop-shadow(1px 1px 2px #000)"></div>
 <div class="trysquashed" style="position: absolute; top: 50px; left: 50px;"></div>
 
@@ -16,4 +16,4 @@
 var layersResult = document.getElementById('layers');
 if (window.internals)
     layersResult.innerText = internals.layerTreeAsText(document);
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/blink/web_tests/compositing/squashing/no-squashing-into-another-clip-layer.html b/third_party/blink/web_tests/compositing/squashing/no-squashing-into-another-clip-layer.html
index c0a0fd2..689c7aa8 100644
--- a/third_party/blink/web_tests/compositing/squashing/no-squashing-into-another-clip-layer.html
+++ b/third_party/blink/web_tests/compositing/squashing/no-squashing-into-another-clip-layer.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <style>
 .hoverable:hover {
-    transform: translateZ(0);
+    will-change: transform;
 }
 </style>
 <script>
@@ -16,8 +16,8 @@
     }
   window.addEventListener('load', dumpLayers, false)
 </script>
-<div style="transform: translateZ(0); overflow: hidden; height: 10px; background-color: lightblue">
-  <div id="inner" style="transform: translateZ(0); height: 10px; background-color: whitesmoke">
+<div style="will-change: transform; overflow: hidden; height: 10px; background-color: lightblue">
+  <div id="inner" style="will-change: transform; height: 10px; background-color: whitesmoke">
   </div>
 </div>
 <!-- This div should not sqaush into the inner div, because it is inside an overflow:hidden div which therefore clips differently than this div's parent -->
diff --git a/third_party/blink/web_tests/compositing/squashing/no-squashing-into-fixed-position-that-clips.html b/third_party/blink/web_tests/compositing/squashing/no-squashing-into-fixed-position-that-clips.html
index 54aa29f..62b9ca8 100644
--- a/third_party/blink/web_tests/compositing/squashing/no-squashing-into-fixed-position-that-clips.html
+++ b/third_party/blink/web_tests/compositing/squashing/no-squashing-into-fixed-position-that-clips.html
@@ -27,7 +27,7 @@
   width: 24px;
   height: 100px;
   background: lightgray;
-  transform: translateZ(0);
+  will-change: transform;
 }
 </style>
 <div class="notsquashedelement"></div>
diff --git a/third_party/blink/web_tests/compositing/squashing/opacity-squashed-owner.html b/third_party/blink/web_tests/compositing/squashing/opacity-squashed-owner.html
index 90ca0b0..9702d86 100644
--- a/third_party/blink/web_tests/compositing/squashing/opacity-squashed-owner.html
+++ b/third_party/blink/web_tests/compositing/squashing/opacity-squashed-owner.html
@@ -17,7 +17,7 @@
     left: 16px;
   }
   .composited {
-    transform: translateZ(0px);
+    will-change: transform;
   }
   .opaque {
     opacity: 0.5;
diff --git a/third_party/blink/web_tests/compositing/squashing/repaint-child-of-squashed.html b/third_party/blink/web_tests/compositing/squashing/repaint-child-of-squashed.html
index f48e2e2..4e4d794 100644
--- a/third_party/blink/web_tests/compositing/squashing/repaint-child-of-squashed.html
+++ b/third_party/blink/web_tests/compositing/squashing/repaint-child-of-squashed.html
@@ -3,7 +3,7 @@
 <script src="../../resources/run-after-layout-and-paint.js"></script>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/selection-repaint-with-gaps.html b/third_party/blink/web_tests/compositing/squashing/selection-repaint-with-gaps.html
index 4f49ef81..2778e19a 100644
--- a/third_party/blink/web_tests/compositing/squashing/selection-repaint-with-gaps.html
+++ b/third_party/blink/web_tests/compositing/squashing/selection-repaint-with-gaps.html
@@ -3,7 +3,7 @@
    .overlap {
      height: 500px;
      width: 300px;
-     transform: translateZ(0);
+     will-change: transform;
    }
  
    .item {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-1.html b/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-1.html
index 2f06722..86f719f 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-1.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-1.html
@@ -4,7 +4,7 @@
 <script src="../../resources/run-after-layout-and-paint.js"></script>
 <style>
 .composited {
-  transform: translatez(0);
+  will-change: transform;
 }
 
 .background {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-subpixel-1.html b/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-subpixel-1.html
index 052c0bd..b7f9021 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-subpixel-1.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-subpixel-1.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 .composited {
-  transform: translateZ(0);
+  will-change: transform;
 }
 
 .background {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-subpixel-2.html b/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-subpixel-2.html
index 51aa536a..4594020 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-subpixel-2.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-above-fixed-subpixel-2.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 .composited {
-  transform: translateZ(0);
+  will-change: transform;
 }
 
 .background {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-clipped.html b/third_party/blink/web_tests/compositing/squashing/squash-clipped.html
index 2645c7a..b68ed27a 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-clipped.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-clipped.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-  transform: translatez(0);
+  will-change: transform;
 }
 
 .box {
@@ -43,7 +43,7 @@
 }
 
 .clipper {
-  transform: translatez(0);
+  will-change: transform;
   width: 400px;
   height: 400px;
   background-color: gray;
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-compositing-hover.html b/third_party/blink/web_tests/compositing/squashing/squash-compositing-hover.html
index 3086997..11f24c4 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-compositing-hover.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-compositing-hover.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
@@ -44,7 +44,7 @@
 
 div:hover {
   background-color: green;
-  transform:translatez(0);
+  will-change: transform;
 }
 
 </style>
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-onto-distant-relative.html b/third_party/blink/web_tests/compositing/squashing/squash-onto-distant-relative.html
index 271338ac..43740f9 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-onto-distant-relative.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-onto-distant-relative.html
@@ -18,7 +18,7 @@
     overflow: hidden;
 }
 </style>
-<div id="squashing" style="transform:translateZ(0);"></div>
+<div id="squashing" style="will-change: transform;"></div>
 <div id="squashed">
 This box will be squashed by an offscreen box that is distant from the viewport.
 It should still be positioned correctly without having numerical issue.
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-1.html b/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-1.html
index f19cf687..6233e62 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-1.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-1.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-2.html b/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-2.html
index 47148ec..a1ead49b 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-2.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-2.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-3.html b/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-3.html
index 57ad01d..e22d394 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-3.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew-subpixel-3.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew.html b/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew.html
index cad23de..97283d0 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-onto-nephew.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-onto-transform-backing.html b/third_party/blink/web_tests/compositing/squashing/squash-onto-transform-backing.html
index 6a06611..eb318dc4 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-onto-transform-backing.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-onto-transform-backing.html
@@ -3,7 +3,8 @@
 <style>
 
 .compositedAndRotated {
-transform: translatez(0) rotate(45deg);
+  transform: rotate(45deg);
+  will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-overflow-hidden-contents.html b/third_party/blink/web_tests/compositing/squashing/squash-overflow-hidden-contents.html
index ead8519..19ada848 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-overflow-hidden-contents.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-overflow-hidden-contents.html
@@ -21,7 +21,7 @@
     left: 20px;
     width: 100px;
     height: 100px;
-    transform: translateZ(0);
+    will-change: transform;
   }
 </style>
 <!-- Go into compositing. -->
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-overflow-hidden-scrolltop.html b/third_party/blink/web_tests/compositing/squashing/squash-overflow-hidden-scrolltop.html
index f8543a2..39f0c66 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-overflow-hidden-scrolltop.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-overflow-hidden-scrolltop.html
@@ -22,7 +22,7 @@
     left: 20px;
     width: 100px;
     height: 100px;
-    transform: translateZ(0);
+    will-change: transform;
   }
   
   .top {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-paint-invalidation-fixed-position.html b/third_party/blink/web_tests/compositing/squashing/squash-paint-invalidation-fixed-position.html
index 529afaa..3bd59ae 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-paint-invalidation-fixed-position.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-paint-invalidation-fixed-position.html
@@ -1,5 +1,5 @@
 <!doctype html>
-<div style="position: fixed; height: 5000px; width: 100px; background: lightblue; transform: translateZ(0)"></div>
+<div style="position: fixed; height: 5000px; width: 100px; background: lightblue; will-change: transform"></div>
 <div style="position: fixed; top: 25px; height: 100px; width: 100px; background: lightgray"></div>
 <div id="foo" style="position: fixed; top: 50px; height: 100px; width: 100px; background: lightgray"></div>
 <script src="../../resources/run-after-layout-and-paint.js"></script>
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-same-transform-ancestor.html b/third_party/blink/web_tests/compositing/squashing/squash-same-transform-ancestor.html
index 1fcda5d..d8bbe29 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-same-transform-ancestor.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-same-transform-ancestor.html
@@ -26,7 +26,7 @@
 }
 </style>
 <div id="transform-parent">
-<div id="squashing" style="transform:translateZ(0);"></div>
+<div id="squashing" style="will-change: transform;"></div>
 <div id="squashed">
 The purpose of the test is to make sure when squashing, the compositing ancestor of the squashing
 host, the squashing host itself, and the squashed layers all share the same transform ancestor,
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-simple.html b/third_party/blink/web_tests/compositing/squashing/squash-simple.html
index 41e28cb..bbcea48 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-simple.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-simple.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-three-layers.html b/third_party/blink/web_tests/compositing/squashing/squash-three-layers.html
index 66bf7f8..26d9635 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-three-layers.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-three-layers.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-child.html b/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-child.html
index daeb14b..a318c0a 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-child.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-child.html
@@ -3,7 +3,7 @@
 <script src="../../resources/run-after-layout-and-paint.js"></script>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-transformed-child.html b/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-transformed-child.html
index 5af7b2ab..1b54a53 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-transformed-child.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-transformed-child.html
@@ -3,7 +3,7 @@
 <script src="../../resources/run-after-layout-and-paint.js"></script>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-transform.html b/third_party/blink/web_tests/compositing/squashing/squash-transform.html
index f62b4e0..3218f934 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-transform.html
+++ b/third_party/blink/web_tests/compositing/squashing/squash-transform.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/compositing/squashing/squashed-layer-loses-graphicslayer.html b/third_party/blink/web_tests/compositing/squashing/squashed-layer-loses-graphicslayer.html
index 44d3ed4..cc14866 100644
--- a/third_party/blink/web_tests/compositing/squashing/squashed-layer-loses-graphicslayer.html
+++ b/third_party/blink/web_tests/compositing/squashing/squashed-layer-loses-graphicslayer.html
@@ -11,7 +11,7 @@
 }
 
 .composited {
-  transform: translatez(0);
+  will-change: transform;
 }
 
 .underneath {
diff --git a/third_party/blink/web_tests/compositing/squashing/squashed-repaints.html b/third_party/blink/web_tests/compositing/squashing/squashed-repaints.html
index 2165cb3..4236642 100644
--- a/third_party/blink/web_tests/compositing/squashing/squashed-repaints.html
+++ b/third_party/blink/web_tests/compositing/squashing/squashed-repaints.html
@@ -11,7 +11,7 @@
 }
 
 .composited {
-  transform: translatez(0);
+  will-change: transform;
   top: 60px;
   left: 60px;
   background-color: gray;
diff --git a/third_party/blink/web_tests/compositing/squashing/squashing-sparsity-heuristic.html b/third_party/blink/web_tests/compositing/squashing/squashing-sparsity-heuristic.html
index 14c9bae..eab8624 100644
--- a/third_party/blink/web_tests/compositing/squashing/squashing-sparsity-heuristic.html
+++ b/third_party/blink/web_tests/compositing/squashing/squashing-sparsity-heuristic.html
@@ -10,7 +10,7 @@
 }
 
 .composited {
-  transform: translatez(0);
+  will-change: transform;
   top: 60px;
   left: 60px;
   width: 400px;
diff --git a/third_party/blink/web_tests/compositing/sub-layer-focus-ring-expected.html b/third_party/blink/web_tests/compositing/sub-layer-focus-ring-expected.html
index dbc6806..9ad6a72 100644
--- a/third_party/blink/web_tests/compositing/sub-layer-focus-ring-expected.html
+++ b/third_party/blink/web_tests/compositing/sub-layer-focus-ring-expected.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 .composited {
-  transform: translateZ(0);
+  will-change: transform;
 }
 
 .outer {
diff --git a/third_party/blink/web_tests/compositing/sub-layer-focus-ring.html b/third_party/blink/web_tests/compositing/sub-layer-focus-ring.html
index d814513..aca610f 100644
--- a/third_party/blink/web_tests/compositing/sub-layer-focus-ring.html
+++ b/third_party/blink/web_tests/compositing/sub-layer-focus-ring.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 .composited {
-  transform: translateZ(0);
+  will-change: transform;
 }
 
 .outer {
diff --git a/third_party/blink/web_tests/compositing/text-on-large-layer.html b/third_party/blink/web_tests/compositing/text-on-large-layer.html
index 97c4ff3..365c6f4a 100644
--- a/third_party/blink/web_tests/compositing/text-on-large-layer.html
+++ b/third_party/blink/web_tests/compositing/text-on-large-layer.html
@@ -10,7 +10,7 @@
 }
 </script>
 <body style="overflow:hidden">
-<div style="transform:translateZ(0); width: 2000px; height: 10000px; top:1px; left:3px; position:absolute">
+<div style="will-change: transform; width: 2000px; height: 10000px; top:1px; left:3px; position:absolute">
 This is some text inside a very large composited layer to test that it is rendered sharply.<br>
 The test passes if this text is crisp.
 </div>
diff --git a/third_party/blink/web_tests/compositing/tiled-layers-hidpi.html b/third_party/blink/web_tests/compositing/tiled-layers-hidpi.html
index a3db404..4f247ef 100644
--- a/third_party/blink/web_tests/compositing/tiled-layers-hidpi.html
+++ b/third_party/blink/web_tests/compositing/tiled-layers-hidpi.html
@@ -1,12 +1,12 @@
 <html>
-	<style>
-		#composited {
-			width: 1800px;
-			height: 10px;
-			transform: translateZ(0);
-			background-color: blue;
-		}
-	</style>
+    <style>
+        #composited {
+            width: 1800px;
+            height: 10px;
+            will-change: transform;
+            background-color: blue;
+        }
+    </style>
     <script>
         function startTest() {
             if (window.testRunner) {
@@ -18,9 +18,9 @@
         
         function finishTest() {
             setTimeout(function() {
-				document.getElementById('layer-tree').innerText = internals.layerTreeAsText(document);
-				testRunner.notifyDone();
-			}, 0);
+                document.getElementById('layer-tree').innerText = internals.layerTreeAsText(document);
+                testRunner.notifyDone();
+            }, 0);
         }
         </script>
     </head>
diff --git a/third_party/blink/web_tests/compositing/video/video-controls-layer-creation.html b/third_party/blink/web_tests/compositing/video/video-controls-layer-creation.html
index 5c36a97..8905a35 100644
--- a/third_party/blink/web_tests/compositing/video/video-controls-layer-creation.html
+++ b/third_party/blink/web_tests/compositing/video/video-controls-layer-creation.html
@@ -3,7 +3,7 @@
 <head>
 <style>
     div {
-        transform:translateZ(0);
+        will-change: transform;
         position: absolute;
         top: 100px;
         left: 0px;
diff --git a/third_party/blink/web_tests/compositing/visibility/layer-visible-content.html b/third_party/blink/web_tests/compositing/visibility/layer-visible-content.html
index 33960e6..56c1177 100644
--- a/third_party/blink/web_tests/compositing/visibility/layer-visible-content.html
+++ b/third_party/blink/web_tests/compositing/visibility/layer-visible-content.html
@@ -31,7 +31,7 @@
         background-color:green;
     }
     .composited {
-        transform:translateZ(0);
+        will-change: transform;
         height: 10px;
         width: 10px;
     }
diff --git a/third_party/blink/web_tests/compositing/visibility/visibility-image-layers-dynamic.html b/third_party/blink/web_tests/compositing/visibility/visibility-image-layers-dynamic.html
index d769c27..7b042dc4 100644
--- a/third_party/blink/web_tests/compositing/visibility/visibility-image-layers-dynamic.html
+++ b/third_party/blink/web_tests/compositing/visibility/visibility-image-layers-dynamic.html
@@ -34,7 +34,7 @@
       background-color: green !important;
     }
     .composited {
-      transform: translateZ(0);
+      will-change: transform;
     }
     
     .visible-indicator {
diff --git a/third_party/blink/web_tests/compositing/visibility/visibility-on-distant-descendant.html b/third_party/blink/web_tests/compositing/visibility/visibility-on-distant-descendant.html
index 2cd9259..d3ee4ed4 100644
--- a/third_party/blink/web_tests/compositing/visibility/visibility-on-distant-descendant.html
+++ b/third_party/blink/web_tests/compositing/visibility/visibility-on-distant-descendant.html
@@ -17,7 +17,7 @@
     }
 
     .composited {
-        transform: translatez(0);
+        will-change: transform;
     }
 
     .topLeft {
diff --git a/third_party/blink/web_tests/compositing/visibility/visibility-simple-canvas2d-layer.html b/third_party/blink/web_tests/compositing/visibility/visibility-simple-canvas2d-layer.html
index b0442a2..604eec5 100644
--- a/third_party/blink/web_tests/compositing/visibility/visibility-simple-canvas2d-layer.html
+++ b/third_party/blink/web_tests/compositing/visibility/visibility-simple-canvas2d-layer.html
@@ -15,7 +15,7 @@
       }
 
       .composited {
-        transform: translatez(0);
+        will-change: transform;
       }
     </style>
 
diff --git a/third_party/blink/web_tests/compositing/webgl/webgl-with-accelerated-background-color.html b/third_party/blink/web_tests/compositing/webgl/webgl-with-accelerated-background-color.html
index 41bf32f..4151961 100644
--- a/third_party/blink/web_tests/compositing/webgl/webgl-with-accelerated-background-color.html
+++ b/third_party/blink/web_tests/compositing/webgl/webgl-with-accelerated-background-color.html
@@ -23,7 +23,7 @@
         position: relative;
     }
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 </style>
 <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/compositing/z-order/negative-z-index.html b/third_party/blink/web_tests/compositing/z-order/negative-z-index.html
index 0dfe976..7838d6e 100644
--- a/third_party/blink/web_tests/compositing/z-order/negative-z-index.html
+++ b/third_party/blink/web_tests/compositing/z-order/negative-z-index.html
@@ -17,7 +17,7 @@
     }
 
     .compositing {
-      transform: translateZ(0);
+      will-change: transform;
     }
 
     .foreground {
diff --git a/third_party/blink/web_tests/css3/blending/mix-blend-mode-2nd-stacking-context-composited.html b/third_party/blink/web_tests/css3/blending/mix-blend-mode-2nd-stacking-context-composited.html
index cb92402..c3808a65 100644
--- a/third_party/blink/web_tests/css3/blending/mix-blend-mode-2nd-stacking-context-composited.html
+++ b/third_party/blink/web_tests/css3/blending/mix-blend-mode-2nd-stacking-context-composited.html
@@ -16,6 +16,7 @@
 }
 .accelerated {
   transform: rotateX(0deg);
+  will-change: transform;
 }
 .blended {
   mix-blend-mode: multiply;
diff --git a/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-layers.html b/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-layers.html
index db05abd..9f08bac 100644
--- a/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-layers.html
+++ b/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-layers.html
@@ -18,7 +18,7 @@
 <!-- Mix-blend-mode should create a composited layer when having composited descendants-->
 <div style="background-color: green">
     <div style="background-color: blue; mix-blend-mode: multiply">
-        <div style="background-color: yellow; transform: translatez(0);"></div>
+        <div style="background-color: yellow; transform: translatez(0); will-change: transform;"></div>
     </div>
 </div>
 
diff --git a/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-reason-children.html b/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-reason-children.html
index 48b0596..5295a7c7 100644
--- a/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-reason-children.html
+++ b/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-reason-children.html
@@ -16,6 +16,7 @@
 }
 .accelerated {
   transform: rotateX(0deg);
+  will-change: transform;
 }
 .blended {
   mix-blend-mode: multiply;
diff --git a/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-2-stacking-contexts.html b/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-2-stacking-contexts.html
index 010d255d..35dd4a1 100644
--- a/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-2-stacking-contexts.html
+++ b/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-2-stacking-contexts.html
@@ -16,6 +16,7 @@
 }
 .accelerated {
   transform: rotateX(0deg);
+  will-change: transform;
 }
 .blended {
   mix-blend-mode: multiply;
diff --git a/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-layer.html b/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-layer.html
index 475e984..530907bf 100644
--- a/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-layer.html
+++ b/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-layer.html
@@ -16,6 +16,7 @@
 }
 .accelerated {
   transform: rotateX(0deg);
+  will-change: transform;
 }
 .blended {
   mix-blend-mode: multiply;
diff --git a/third_party/blink/web_tests/css3/filters/composited-layer-bounds-after-sw-blur-animation.html b/third_party/blink/web_tests/css3/filters/composited-layer-bounds-after-sw-blur-animation.html
index 4b4abb2..111bc29 100644
--- a/third_party/blink/web_tests/css3/filters/composited-layer-bounds-after-sw-blur-animation.html
+++ b/third_party/blink/web_tests/css3/filters/composited-layer-bounds-after-sw-blur-animation.html
@@ -11,7 +11,7 @@
     <style>
         #composited-layer {
             background-color: green;
-            transform: translateZ(0);
+            will-change: transform;
             position: absolute;
             top: 100px;
             left: 100px;
diff --git a/third_party/blink/web_tests/css3/filters/composited-layer-bounds-with-composited-blur.html b/third_party/blink/web_tests/css3/filters/composited-layer-bounds-with-composited-blur.html
index 077bbdd..16959ec 100644
--- a/third_party/blink/web_tests/css3/filters/composited-layer-bounds-with-composited-blur.html
+++ b/third_party/blink/web_tests/css3/filters/composited-layer-bounds-with-composited-blur.html
@@ -11,7 +11,7 @@
     <style>
         #composited {
             background-color: green;
-            transform: translateZ(0);
+            will-change: transform;
             filter: blur(25px);
             position: absolute;
             top: 100px;
diff --git a/third_party/blink/web_tests/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html b/third_party/blink/web_tests/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html
index 6246f128..1e598eb9 100644
--- a/third_party/blink/web_tests/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html
+++ b/third_party/blink/web_tests/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html
@@ -15,7 +15,7 @@
     <style>
         #composited-parent {
             background-color: red;
-            transform: translateZ(0);
+            will-change: transform;
             position: absolute;
             top: 100px;
             left: 100px;
@@ -24,7 +24,7 @@
         }
         #absolutely-positioned-composited-child {
             background-color: green;
-            transform: translateZ(0);
+            will-change: transform;
             position: absolute;
             top: 0;
             left: 0;
diff --git a/third_party/blink/web_tests/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow.html b/third_party/blink/web_tests/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow.html
index 4d128f8..c5cf0a5b 100644
--- a/third_party/blink/web_tests/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow.html
+++ b/third_party/blink/web_tests/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow.html
@@ -24,7 +24,7 @@
         }
         #composited-layer-to-overlap {
             background-color: blue;
-            transform: translateZ(0);
+            will-change: transform;
             position: absolute;
             top: 250px;
             left: 250px;
diff --git a/third_party/blink/web_tests/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow.html b/third_party/blink/web_tests/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow.html
index 547d8c2a..f2660bf 100644
--- a/third_party/blink/web_tests/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow.html
+++ b/third_party/blink/web_tests/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow.html
@@ -28,7 +28,7 @@
         }
         #composited-layer-to-overlap {
             background-color: blue;
-            transform: translateZ(0);
+            will-change: transform;
             position: absolute;
             top: 250px;
             left: 250px;
diff --git a/third_party/blink/web_tests/css3/filters/direct-image-dynamic-filter.html b/third_party/blink/web_tests/css3/filters/direct-image-dynamic-filter.html
index aaaff69..1d1f210 100644
--- a/third_party/blink/web_tests/css3/filters/direct-image-dynamic-filter.html
+++ b/third_party/blink/web_tests/css3/filters/direct-image-dynamic-filter.html
@@ -2,7 +2,7 @@
 <html>
 <style>
   .composited {
-    transform: translateZ(0);
+    will-change: transform;
   }
   .filter {
     filter: invert(100%);
diff --git a/third_party/blink/web_tests/css3/filters/effect-brightness-hw.html b/third_party/blink/web_tests/css3/filters/effect-brightness-hw.html
index 29d55ef..f29fdcc0 100644
--- a/third_party/blink/web_tests/css3/filters/effect-brightness-hw.html
+++ b/third_party/blink/web_tests/css3/filters/effect-brightness-hw.html
@@ -1,7 +1,7 @@
 <!-- This test uses a particular image size to avoid hitting flakiness in mesa texture sampling.  See http://crbug.com/621892 for more details. -->
 <style>
 img {
-    transform:translateZ(0);
+    will-change: transform;
 }
 div {
     width: 160px;
diff --git a/third_party/blink/web_tests/css3/filters/effect-combined-hw.html b/third_party/blink/web_tests/css3/filters/effect-combined-hw.html
index 0e70483a..1e493cb9 100644
--- a/third_party/blink/web_tests/css3/filters/effect-combined-hw.html
+++ b/third_party/blink/web_tests/css3/filters/effect-combined-hw.html
@@ -1,7 +1,7 @@
 <style>
 img {
     margin: 10px;
-    transform:translateZ(0);
+    will-change: transform;
 }
 </style>
 <img style="filter: sepia() saturate(3) hue-rotate(180deg)" src="resources/reference.png">
diff --git a/third_party/blink/web_tests/css3/filters/effect-contrast-hw.html b/third_party/blink/web_tests/css3/filters/effect-contrast-hw.html
index e82814e..58f9bdb 100644
--- a/third_party/blink/web_tests/css3/filters/effect-contrast-hw.html
+++ b/third_party/blink/web_tests/css3/filters/effect-contrast-hw.html
@@ -1,6 +1,6 @@
 <style>
 img {
-    transform:translateZ(0);
+    will-change: transform;
 }
 </style>
 <img style="filter: contrast(0)" src="resources/reference.png">
diff --git a/third_party/blink/web_tests/css3/filters/effect-grayscale-hw.html b/third_party/blink/web_tests/css3/filters/effect-grayscale-hw.html
index 8f3a0b4..0c66301 100644
--- a/third_party/blink/web_tests/css3/filters/effect-grayscale-hw.html
+++ b/third_party/blink/web_tests/css3/filters/effect-grayscale-hw.html
@@ -1,7 +1,7 @@
 <!-- This test uses a particular image size to avoid hitting flakiness in mesa texture sampling.  See http://crbug.com/621892 for more details. -->
 <style>
 img {
-    transform:translateZ(0);
+    will-change: transform;
 }
 div {
     width: 160px;
diff --git a/third_party/blink/web_tests/css3/filters/effect-hue-rotate-hw.html b/third_party/blink/web_tests/css3/filters/effect-hue-rotate-hw.html
index ea5a7eff5..cfd33732 100644
--- a/third_party/blink/web_tests/css3/filters/effect-hue-rotate-hw.html
+++ b/third_party/blink/web_tests/css3/filters/effect-hue-rotate-hw.html
@@ -1,7 +1,7 @@
 <!-- This test uses a particular image size to avoid hitting flakiness in mesa texture sampling.  See http://crbug.com/621892 for more details. -->
 <style>
 img {
-    transform:translateZ(0);
+    will-change: transform;
 }
 div {
     width: 160px;
diff --git a/third_party/blink/web_tests/css3/filters/effect-saturate-hw.html b/third_party/blink/web_tests/css3/filters/effect-saturate-hw.html
index fb91e5d..4384847 100644
--- a/third_party/blink/web_tests/css3/filters/effect-saturate-hw.html
+++ b/third_party/blink/web_tests/css3/filters/effect-saturate-hw.html
@@ -1,7 +1,7 @@
 <!-- This test uses a particular image size to avoid hitting flakiness in mesa texture sampling.  See http://crbug.com/621892 for more details. -->
 <style>
 img {
-    transform:translateZ(0);
+    will-change: transform;
 }
 div {
     width: 160px;
diff --git a/third_party/blink/web_tests/css3/filters/effect-sepia-hw.html b/third_party/blink/web_tests/css3/filters/effect-sepia-hw.html
index b7034e0..a6aed408 100644
--- a/third_party/blink/web_tests/css3/filters/effect-sepia-hw.html
+++ b/third_party/blink/web_tests/css3/filters/effect-sepia-hw.html
@@ -1,7 +1,7 @@
 <!-- This test uses a particular image size to avoid hitting flakiness in mesa texture sampling.  See http://crbug.com/621892 for more details. -->
 <style>
 img {
-    transform:translateZ(0);
+    will-change: transform;
 }
 div {
     width: 160px;
diff --git a/third_party/blink/web_tests/css3/filters/filter-change-repaint-composited.html b/third_party/blink/web_tests/css3/filters/filter-change-repaint-composited.html
index ba3e79b..52c3db4 100644
--- a/third_party/blink/web_tests/css3/filters/filter-change-repaint-composited.html
+++ b/third_party/blink/web_tests/css3/filters/filter-change-repaint-composited.html
@@ -8,7 +8,7 @@
     <style>
         .box {
             /* force a composited layer */
-            transform: translate3d(0, 0, 0);
+            will-change: transform;
             float: left;
             height: 50px;
             width: 50px;
diff --git a/third_party/blink/web_tests/css3/filters/filter-change-repaint.html b/third_party/blink/web_tests/css3/filters/filter-change-repaint.html
index 5ac0f8e..5a9cb60 100644
--- a/third_party/blink/web_tests/css3/filters/filter-change-repaint.html
+++ b/third_party/blink/web_tests/css3/filters/filter-change-repaint.html
@@ -32,7 +32,7 @@
 
         .composited_from_software {
             /* force a composited layer */
-            transform: translate3d(0, 0, 0);
+            will-change: transform;
             filter: drop-shadow(0px 0px 10px blue);
         }
 
@@ -48,7 +48,7 @@
 
         .software_from_composited.before {
             /* force a composited layer */
-            transform: translate3d(0, 0, 0);
+            will-change: transform;
             filter: drop-shadow(0px 0px 10px red);
         }
 
diff --git a/third_party/blink/web_tests/css3/filters/filter-repaint-composited-fallback-crash.html b/third_party/blink/web_tests/css3/filters/filter-repaint-composited-fallback-crash.html
index e17db23..f9e98df 100644
--- a/third_party/blink/web_tests/css3/filters/filter-repaint-composited-fallback-crash.html
+++ b/third_party/blink/web_tests/css3/filters/filter-repaint-composited-fallback-crash.html
@@ -19,7 +19,7 @@
         
         .blur {
             /* force a composited layer */
-            transform: translate3d(0, 0, 0);
+            will-change: transform;
             background: red;
             margin: 50px;
             filter: drop-shadow(0px 0px 1px blue) blur(5px);
diff --git a/third_party/blink/web_tests/css3/filters/filter-repaint-composited-fallback.html b/third_party/blink/web_tests/css3/filters/filter-repaint-composited-fallback.html
index 31a6362..bf7c2e33 100644
--- a/third_party/blink/web_tests/css3/filters/filter-repaint-composited-fallback.html
+++ b/third_party/blink/web_tests/css3/filters/filter-repaint-composited-fallback.html
@@ -22,7 +22,7 @@
 
         .blur {
             /* force a composited layer */
-            transform: translate3d(0, 0, 0);
+            will-change: transform;
             background: red;
             margin: 50px;
             filter: drop-shadow(0px 0px 1px blue) blur(5px);
diff --git a/third_party/blink/web_tests/css3/filters/remove-filter-repaint-expected.html b/third_party/blink/web_tests/css3/filters/remove-filter-repaint-expected.html
index 4ff1163..46fd1a3 100644
--- a/third_party/blink/web_tests/css3/filters/remove-filter-repaint-expected.html
+++ b/third_party/blink/web_tests/css3/filters/remove-filter-repaint-expected.html
@@ -28,7 +28,7 @@
         color: white;
     }
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
     </style>
 </head>
diff --git a/third_party/blink/web_tests/css3/filters/remove-filter-repaint.html b/third_party/blink/web_tests/css3/filters/remove-filter-repaint.html
index 0dbd478..29aa711 100644
--- a/third_party/blink/web_tests/css3/filters/remove-filter-repaint.html
+++ b/third_party/blink/web_tests/css3/filters/remove-filter-repaint.html
@@ -31,7 +31,7 @@
         filter: drop-shadow(black 0 0 5px);
     }
     .composited {
-        transform: translateZ(0);
+        will-change: transform;
     }
 
     </style>
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 78c2740..1926f892 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
@@ -171343,9 +171343,6 @@
    "tools/docker/Dockerfile": [
     []
    ],
-   "tools/docker/Dockerfile.webkitgtk": [
-    []
-   ],
    "tools/docker/README.md": [
     []
    ],
@@ -171361,9 +171358,6 @@
    "tools/docker/frontend.py": [
     []
    ],
-   "tools/docker/github/Dockerfile": [
-    []
-   ],
    "tools/docker/retry.py": [
     []
    ],
@@ -207226,6 +207220,12 @@
      {}
     ]
    ],
+   "css/css-grid/alignment/grid-align-content.html": [
+    [
+     "css/css-grid/alignment/grid-align-content.html",
+     {}
+    ]
+   ],
    "css/css-grid/alignment/grid-alignment-implies-size-change-001.html": [
     [
      "css/css-grid/alignment/grid-alignment-implies-size-change-001.html",
@@ -239507,6 +239507,20 @@
      {}
     ]
    ],
+   "fetch/metadata/sec-fetch-dest/frame.tentative.https.sub.html": [
+    [
+     "fetch/metadata/sec-fetch-dest/frame.tentative.https.sub.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
+   "fetch/metadata/sec-fetch-dest/frame.tentative.sub.html": [
+    [
+     "fetch/metadata/sec-fetch-dest/frame.tentative.sub.html",
+     {}
+    ]
+   ],
    "fetch/metadata/sec-fetch-dest/history.tentative.https.sub.html": [
     [
      "fetch/metadata/sec-fetch-dest/history.tentative.https.sub.html",
@@ -380207,6 +380221,10 @@
    "d45df4bc2231cbda5dee1bafc3f386f008024d79",
    "support"
   ],
+  "css/css-grid/alignment/grid-align-content.html": [
+   "fb3f7007ee19189a09de9c1f786176c317b7ee14",
+   "testharness"
+  ],
   "css/css-grid/alignment/grid-alignment-implies-size-change-001.html": [
    "865027325afc3d003b5b237041ea6163de8f2c25",
    "testharness"
@@ -438588,7 +438606,7 @@
    "testharness"
   ],
   "fetch/metadata/embed.tentative.https.sub.html": [
-   "aae61e0ff426494ec4f824aea1ae553ec0d18258",
+   "77042e85de9f26655fc31085074e2401a8202efc",
    "testharness"
   ],
   "fetch/metadata/fetch-preflight.tentative.https.sub.html": [
@@ -438728,7 +438746,7 @@
    "support"
   ],
   "fetch/metadata/resources/helper.js": [
-   "eac176a49871c9a08ce1358c03543ccabee5aaa4",
+   "d9b00ed8b94b595a4d4c1a50396355d3518c6496",
    "support"
   ],
   "fetch/metadata/resources/post-to-owner.py": [
@@ -438795,16 +438813,24 @@
    "bc892db320c29b2979060b4ed29aaf5f507798d8",
    "testharness"
   ],
+  "fetch/metadata/sec-fetch-dest/frame.tentative.https.sub.html": [
+   "d80b727469851c131df6226f20fff03377b4a9c6",
+   "testharness"
+  ],
+  "fetch/metadata/sec-fetch-dest/frame.tentative.sub.html": [
+   "61b6d1f446beb918cbaff18d4cbecbab7143aa32",
+   "testharness"
+  ],
   "fetch/metadata/sec-fetch-dest/history.tentative.https.sub.html": [
    "55e03a23660bc13d98763ffbe0ba8b077914cbcd",
    "testharness"
   ],
   "fetch/metadata/sec-fetch-dest/iframe.tentative.https.sub.html": [
-   "ed9cfa0c76a45e1871a6759c5d71932556fbc931",
+   "356805d190024230dc691b584c03cb4e6f16951c",
    "testharness"
   ],
   "fetch/metadata/sec-fetch-dest/iframe.tentative.sub.html": [
-   "d90a4147d06dda07a21525a4fbf9afd6a161397c",
+   "e126e3c0a89147a5d878992f211b19be08e7089c",
    "testharness"
   ],
   "fetch/metadata/sec-fetch-dest/img.tentative.https.sub.html": [
@@ -462684,7 +462710,7 @@
    "support"
   ],
   "interfaces/web-nfc.idl": [
-   "c3e53350901c7b1e1c608ff4ee07be475c97cd9a",
+   "4e0dc0725163e42455fb3418ed9757ddc1d8f632",
    "support"
   ],
   "interfaces/web-share.idl": [
@@ -500628,23 +500654,23 @@
    "support"
   ],
   "tools/certs/README.md": [
-   "62c9d24685af8c00151b8fc804e6edca6d6c36d5",
+   "fd75c22ddffed2e700f5f44c2b552cc3526d460f",
    "support"
   ],
   "tools/certs/cacert.key": [
-   "907b8650808e8ae858a98b48f4322dd92e140d91",
+   "1a121dfac952dfe8886b1b5e41e7c7311d5f0b32",
    "support"
   ],
   "tools/certs/cacert.pem": [
-   "49b343ac6476338576cb2487812eabe2653f30c4",
+   "e1b5add54e797db1c6c1d3eda961af3e54bc7a77",
    "support"
   ],
   "tools/certs/web-platform.test.key": [
-   "6d60e8912a6400a217d963d87a653645385e881e",
+   "b62af208c34cb3167ae64038cdff696f047893eb",
    "support"
   ],
   "tools/certs/web-platform.test.pem": [
-   "c9f7f57dc663e0b26925c29d0c4bcdf4d52713f7",
+   "5959316bb5b4825e640bb1f7cab08bc9f405a63a",
    "support"
   ],
   "tools/ci/__init__.py": [
@@ -500756,7 +500782,7 @@
    "support"
   ],
   "tools/ci/run_tc.py": [
-   "3201ff3a9d309719da2fe038c73d1b144ffdb5d2",
+   "956d1c353e54b2179316ad56ff85823bc5009ea6",
    "support"
   ],
   "tools/ci/taskcluster-run.py": [
@@ -500779,12 +500805,8 @@
    "3d41834cfb41430b4a9aa05fa8c6d6b6f2010b51",
    "support"
   ],
-  "tools/docker/Dockerfile.webkitgtk": [
-   "58080def60ff4f26277c96015a8c2968254907f3",
-   "support"
-  ],
   "tools/docker/README.md": [
-   "6bcc47c7744e4cc8be96b1c9590878955080da27",
+   "450981f686bface2d9243e5628040bb6b2f6c4e0",
    "support"
   ],
   "tools/docker/__init__.py": [
@@ -500803,10 +500825,6 @@
    "c4a207345820d534df5cc092c8b46838a5b8ce1f",
    "support"
   ],
-  "tools/docker/github/Dockerfile": [
-   "22d47f3e5fa9032e5f016f6f15720fa98e1ba625",
-   "support"
-  ],
   "tools/docker/retry.py": [
    "6126b781bfadd15e82b8a3a3b9494050939eab6c",
    "support"
@@ -505056,7 +505074,7 @@
    "support"
   ],
   "tools/wpt/browser.py": [
-   "c04162fe2a15ecb0cbebf1e0c57672b24f2efc56",
+   "233778f25657cdc20582a39f7524d6fde8aab546",
    "support"
   ],
   "tools/wpt/commands.json": [
@@ -505088,7 +505106,7 @@
    "support"
   ],
   "tools/wpt/run.py": [
-   "077d4a7eb87f850017298a0bb971ed74ff7ff694",
+   "de20e2916ad30244ef3635d1fce562cebbd26052",
    "support"
   ],
   "tools/wpt/testfiles.py": [
@@ -505124,7 +505142,7 @@
    "support"
   ],
   "tools/wptrunner/README.rst": [
-   "d4f976dfca1a18c3b1c8b90c4175bf974f6169e2",
+   "0adf0a94b15d224ab7970e81ae7f432df34bb3d7",
    "support"
   ],
   "tools/wptrunner/requirements.txt": [
@@ -505212,7 +505230,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/base.py": [
-   "d17229da4686548e05c228a7345194e0d8f4d8dd",
+   "8607f776b98c220e621b6274cc0bc28c8192414a",
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/chrome.py": [
@@ -505288,7 +505306,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/environment.py": [
-   "924409216411050b038b61c7402eab687b122429",
+   "e79ae3750647f88bba44703181c208229800f658",
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/__init__.py": [
@@ -505296,7 +505314,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/base.py": [
-   "f581c5cedb74e58ff415c19faf19f53ce50c7a9a",
+   "6305563dc69625f115c37dd07f5734b7cb4cf9ea",
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/executorchrome.py": [
@@ -505468,11 +505486,11 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/testloader.py": [
-   "1ffdda6003fad3fe6c770ad7d1bce9a20f10ccda",
+   "fa54ca361576318cb35ec716a1a159bdb532e6c8",
    "support"
   ],
   "tools/wptrunner/wptrunner/testrunner.py": [
-   "5c0c60a07a9613d70ac2f2166de753dc0a007a56",
+   "c2cb5c4d26b2866c069537ceb5a96da623d11bb6",
    "support"
   ],
   "tools/wptrunner/wptrunner/update/__init__.py": [
@@ -505576,7 +505594,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/wptrunner.py": [
-   "8dcdcdebe154fc09087624f20f802a8b2e0717d7",
+   "88b51d0fd6a970316ae382f9efa3d8b9c463ace9",
    "support"
   ],
   "tools/wptrunner/wptrunner/wpttest.py": [
@@ -505656,7 +505674,7 @@
    "support"
   ],
   "tools/wptserve/wptserve/sslutils/openssl.py": [
-   "3c5c1dc23787095b1a67cae7c011b8ad5c785949",
+   "aea1c7380b179ced1366b6617057578b35d9e14b",
    "support"
   ],
   "tools/wptserve/wptserve/sslutils/pregenerated.py": [
@@ -511192,11 +511210,11 @@
    "support"
   ],
   "web-nfc/NDEFMessage_constructor.https.html": [
-   "6515a7fdd0246c23d8193f06593687a4d9bdc658",
+   "19122112f59bbbbb15f4988e841ab7b18042c4e6",
    "testharness"
   ],
   "web-nfc/NDEFRecord_constructor.https.html": [
-   "7a0da33a54370dda699546553c0b18ced937a91c",
+   "849a6ae336ea4026888e9835e89db64fd03eb555",
    "testharness"
   ],
   "web-nfc/NFCErrorEvent_constructor.https.html": [
@@ -511228,7 +511246,7 @@
    "support"
   ],
   "web-nfc/idlharness.https.window-expected.txt": [
-   "46bc91e8e2166e771181a461a2fe75698f7fc959",
+   "7a3c06bce4de289ad8fc39843e7ab19863e4a345",
    "support"
   ],
   "web-nfc/idlharness.https.window.js": [
@@ -511240,7 +511258,7 @@
    "testharness"
   ],
   "web-nfc/resources/nfc-helpers.js": [
-   "bace1b3752faea77e800493ec8c4385ee9aa851c",
+   "ed5cc9c9718d01580460535ea14405c2817c0986",
    "support"
   ],
   "web-share/META.yml": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-align-content.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-align-content.html
new file mode 100644
index 0000000..fb3f700
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-align-content.html
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout test: align-content property</title>
+<link rel="author" title="Rossana Monteriso" href="mailto:rmonteriso@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-align">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#content-distribution">
+<meta name="assert" content="This test checks that the align-content property is applied correctly in both directions RTL and LTR.">
+<meta name="flags" content="ahem">
+<link rel="stylesheet" href="/css/support/grid.css">
+<link rel="stylesheet" href="/css/support/alignment.css">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+
+<style>
+body {
+    margin: 0;
+}
+
+.grid {
+    grid: 100px 100px / 50px 50px;
+    position: relative;
+    width: 200px;
+    height: 300px;
+}
+
+.verticalGrid {
+    width: 300px;
+    height: 200px;
+}
+
+.cell {
+    width: 20px;
+    height: 40px;
+}
+</style>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div style="position: relative">
+    <p>direction: LTR | align-content: 'center'</p>
+    <div class="grid alignContentCenter" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="50" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="150" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="150" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: LTR | align-content: 'left'</p>
+    <div class="grid alignContentLeft" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: LTR | align-content: 'right'</p>
+    <div class="grid alignContentRight" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: LTR | align-content: 'start'</p>
+    <div class="grid alignContentStart" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: LTR | align-content: 'end'</p>
+    <div class="grid alignContentEnd" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: LTR | align-content: 'flex-start'</p>
+    <div class="grid alignContentFlexStart" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: LTR | align-content: 'flex-end</p>
+    <div class="grid alignContentFlexEnd" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<!-- Default alignment and initial values. -->
+<div style="position: relative">
+    <p>direction: LTR | align-content: 'auto' (resolved to 'start')</p>
+    <div class="grid" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<!-- RTL direction. -->
+<div style="position: relative">
+    <p>direction: RTL | align-content: 'center'</p>
+    <div class="grid directionRTL alignContentCenter" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="50" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="150" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="150" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: RTL | align-content: 'left'</p>
+    <div class="grid directionRTL alignContentLeft" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: RTL | align-content: 'right'</p>
+    <div class="grid directionRTL alignContentRight" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: RTL | align-content: 'start'</p>
+    <div class="grid directionRTL alignContentStart" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <p>direction: RTL | align-content: 'end'</p>
+    <div class="grid directionRTL alignContentEnd" data-expected-width="200" data-expected-height="300">
+        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
+        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="200" data-expected-width="50" data-expected-height="100"></div>
+        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/nested-with-padding-and-spanner.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/nested-with-padding-and-spanner.html
new file mode 100644
index 0000000..bea27a9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/nested-with-padding-and-spanner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1006249">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="columns:2; column-fill:auto; width:500px; height:500px; margin-top:-1px;">
+  <div style="columns:2; column-fill:auto; height:400px; padding-top:1px;">
+    <div></div>
+    <div style="width:100px; column-span:all; background:red;">
+      <div style="height:50px; break-inside:avoid; background:green;"></div>
+      <div style="height:50px; break-inside:avoid; background:green;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-wakelock.html b/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-wakelock.html
index 24fe7a5..fac421c 100644
--- a/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-wakelock.html
+++ b/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-wakelock.html
@@ -2,24 +2,12 @@
 "use strict";
 
 Promise.resolve().then(async () => {
-  // On success, WakeLock.request() returns a promise that never resolves. To
-  // prevent a timeout, abort it with an AbortController and use the different
-  // DOMExceptions we get to determine if this worked or not.
-  const controller = new AbortController();
-  const wakeLock = WakeLock.request("screen", { signal: controller.signal });
-  wakeLock.catch(e => {
-    if (e.name == "AbortError") {
-      // We stopped due to the call to AbortController.abort(), so we did manage
-      // to get the lock.
-      window.parent.postMessage({ enabled: true }, "*");
-    } else if (e.name == "NotAllowedError") {
-      // This means requesting the lock failed.
-      window.parent.postMessage({ enabled: false }, "*");
-    } else {
-      // We should not really hit this branch.
-      window.parent.postMessage({ enabled: false }, "*");
-    }
-  });
-  controller.abort();
+  try {
+    const wakeLock = await navigator.wakeLock.request("screen");
+    await wakeLock.release();
+    window.parent.postMessage({ enabled: true }, "*");
+  } catch (e) {
+    window.parent.postMessage({ enabled: false }, "*");
+  }
 });
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/svg/animations/slider-switch.html b/third_party/blink/web_tests/external/wpt/svg/animations/slider-switch.html
index 1e14ae5..59aa8f29 100644
--- a/third_party/blink/web_tests/external/wpt/svg/animations/slider-switch.html
+++ b/third_party/blink/web_tests/external/wpt/svg/animations/slider-switch.html
@@ -1,13 +1,10 @@
 <!doctype html>
-
 <title>Check correct event bases for onclick</title>
 <meta charset="utf-8">
 <link rel="help" href="https://svgwg.org/svg2-draft/single-page.html#interact-EventAttributes">
 <link rel="author" title="Edvard Thörnros" href="mailto:edvardt@opera.com">
-
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-
 <svg width="200" height="100">
   <rect x="0" y="0" width="100" height="100" id="a" fill="#0AA">
     <set begin="a.click" attributeName="display" to="none" fill="freeze"/>
@@ -18,24 +15,33 @@
     <set begin="b.click" attributeName="display" to="none" fill="freeze"/>
   </rect>
 </svg>
-
 <script>
-  let retries = 3;
+  let clicks_remaining = 2;
   let a = document.querySelector("#a");
   let b = document.querySelector("#b");
-  let t = async_test();
-  let interval = setInterval(t.step_func(function() {
-    retries--;
-    if (retries == 0) {
-      clearInterval(interval);
-      assert_equals(window.getComputedStyle(a).display, "block");
-      assert_equals(window.getComputedStyle(b).display, "none");
-      t.done();
-      return;
-    }
-    a.dispatchEvent(new Event("click"));
+  function perform_clicks(t) {
     t.step_timeout(function() {
-      b.dispatchEvent(new Event("click"));
+      a.dispatchEvent(new Event("click"));
+      t.step_timeout(function() {
+        b.dispatchEvent(new Event("click"));
+      }, 20);
     }, 20);
-  }), 20 * 2);
+  }
+  async_test(t => {
+    let observer = document.querySelector("#b > set + set");
+    observer.addEventListener('beginEvent', t.step_func(function() {
+      if (clicks_remaining == 0) {
+        assert_equals(window.getComputedStyle(a).display, "block");
+        assert_equals(window.getComputedStyle(b).display, "none");
+        t.done();
+        return;
+      }
+      perform_clicks(t);
+      clicks_remaining--;
+    }));
+    window.onload = t.step_func(() => {
+      perform_clicks(t);
+      clicks_remaining--;
+    });
+  });
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/tools/certs/README.md b/third_party/blink/web_tests/external/wpt/tools/certs/README.md
index 62c9d24..fd75c22 100644
--- a/third_party/blink/web_tests/external/wpt/tools/certs/README.md
+++ b/third_party/blink/web_tests/external/wpt/tools/certs/README.md
@@ -74,3 +74,8 @@
   },
 }
 ```
+
+### Regenerating the pregenerated certificates
+
+From the root, run `./wpt serve --config tools/certs/config.json` and terminate
+it after it has started up.
diff --git a/third_party/blink/web_tests/external/wpt/tools/certs/cacert.key b/third_party/blink/web_tests/external/wpt/tools/certs/cacert.key
index 907b865..1a121df 100644
--- a/third_party/blink/web_tests/external/wpt/tools/certs/cacert.key
+++ b/third_party/blink/web_tests/external/wpt/tools/certs/cacert.key
@@ -1,30 +1,30 @@
 -----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQILCSlhTzkRTICAggA
-MB0GCWCGSAFlAwQBKgQQgcOfWGRpzftycTbFVXO4mgSCBNDv5/+mh+AabEQwzjk/
-RIVjff2flwV0TooLISvRZYPEi60EsqsDhBpJ5iC6N8GFYXgoz06BaMQsuMGA8cRe
-qcL6uGNdwexoReO7SGD2p3jBQU+r6SpDdVicMDUzYWt8P+kYemFVoCoFrhCiCx2k
-p9ylcERn4JlUP3fW/FZslN77Nyx/M+hPowGmSBsCyFz9FiENeCRLMlyQpyG8Zp9Q
-hNbWmXp5HL/Yato/wySxtDFwC/93sus1TbgSpmmp3csiDE1TIZ2FtlDCjqd0puY8
-UVhhq+0ce01vZgOT4SWXaiMfXOt9tZ6vqsgTakQzQDXKPbPlM3ppFtTMUyNUPmol
-Fj36DxrVEArb7CT/tgbNfd/cdVonDtJJF7vxrAWWKzbhXpLfKAx4j54gdDz/ng0D
-LDvJwlCtMqS5qz30kOJLvSQu+ifG9ib+GBkiihG5VeYKjfvjxWl/3bHamIrwV8Lp
-ijHF2rsSSdzlKksSga+84jmDgAlqCsFdEAzGL8Dg4zk55Wlkr6+EshOQJN8vQz+f
-7O7fyLCS6hjjskmYTTXlHvtLiro870jd+nRXmwNlZ9DDayJCfUMayoihHqeIX4u6
-ZQhjk+54Ln9vEMUlhkiGL/1rE6APVCBnlPzJfX/K2BXHWdu/NRT4rHG6zGQLViJr
-yaaLV6F2bxCACjyjQmYzdGb238ApG5ubY50Eu4UfuB8N1zGDxqU7KQpRXLECmfKw
-qa7lHHpuakC5gFddKHI62rQc9Tw5jLRohFTFA2e54d+rN5axiSBoeYY0Ky+Y6Id4
-xGLkJoNeleyrXKj09ercxcUhg2EL/B4wHiyBLKikZiA4gUaCnCZ7WRPsGpJ5wo/K
-TXiAj1W0QQELGo+k8xmXP9y6Qb4ZcJsnWJ35Spn5CeuI/y/Bms/o2klqbhn9h+gz
-4w4Zo4PoKEfjnFublCoCa7F9jvxSM7GTeaRPf8E6/wYBV8Xdu/rAd3ypCXBRULR1
-xqXvhp6u/k8XmAyd62mAwHRG1RDHZ2Kg1pspV8YGnYYE0pXRSsVKT1+Yu6pQ65n8
-SG0YmZRN2/In0cyTkNwWwl9Bpdd7mghwiZ8uTed00Q7UvxBZxRe8I1VOwBrvA8Jo
-HZ25f0fuzNYkGmLq80jVE6k4dPowOQVp7dKcH8EvGJunUJKeAZrh0B9At52XzqJX
-9uibQrDyJvFKTepH7Gm/NuUQK1XG0tkJbysnvUk3Ezj6nihxL903IfyLhNI/R22P
-45nQeqRzrxLq4pfjW/KY+7IkX8tdabfPDHmtjLi3DhpYlDQ8JTDMn6dElN6wNIpe
-w8wh6c9srD5zbaguaMRy+5R46zyLkDIY/SOMDgXqg6rTsSSnEXc5RD1F2amBXRJF
-g8evdUJ7klx6pDh91Sspn9B/RJs1se5H37Wq9AFvrSHvktNVS0kqim+dimNKRFQr
-kJ8eqxoqJ268wTlnppn14LSig9iwE8a/+yEhfXfoZ12mYCVjT9Y8+ZtrzI+TqIDh
-ThfExeBYbPe+KTcsmuaYHw4Dbf4j8EMh7TJZlVx0o3Aqiw5MOAti5nIYt4kqJx/T
-+pNPJPhMEq0nGyE/iInxrYgH6JdNJqctexhxj5ZdfmrwpFPpDq5ZZ49HT1XFP5jE
-WgiOtgAhQ01A0xiCr0EZbFczHg==
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIminHTzkXhrsCAggA
+MB0GCWCGSAFlAwQBKgQQXVwJcqWze6A3VYuAS0BPgwSCBNCRtvroB6qroQlF58HE
+5SJHF/jQRJRxf051lrq+jfUxM7kZucNN+myV2ziLoga6OQM579D8vy8tqkrLpnsT
+cXkgHuwtBJF47w1YAPGGARe3Ksv/2C9sUVcPvmnVrzSMX86EserffqM3zfwZ2H3S
+jxTDSyIvJUU+4XfxrWegTiQQPNqDyLfO5dBfatT2ztXCmu3BFipuhGFpwwCJirKr
+1xb6XPEuT0PCzTNpeSURpXFKHMDMkcjOkNAUygIEw+Lg7etVfLcsgBuzEA3RWwf3
+OMY1mTBJlvx6zZxdX7a0QmxerUDkDS9YYAEGSFa+Fx6cGW5Pyeef9xtlHxZHi+pm
+TxCwcvJyXqeD4gWm3s1gwOji5WmXvo2EircxfSKk8TUwapxfCYQbOjQIPaHnEGoa
+CQhSEgDX5ufwsXJ9/pSP6kjW+y+f0gnhHVuKJKsOBmjg6iqwnqEhw+uNFWKKl/Mo
+TFT7CrayJTvo+9UdQTJV9MBAsMUQS7d+HH9kNOAn/hfmEzzGUKVTZ0zId0fKH13p
+TnoYgMYbm2Urn0NXBFO8RvzY3KpKyRhMcOLKxkPVUjKUA5BuAv6rcvMflI6Hn5wU
+qPM+uECSgdOnNeImi1Ff+cW8dTGGRb+iha+EnABoX3wR5OvzgCYHeENJb32FUoVs
+ID2T5MZtQNArkis/xWZ7JyPbmsQo2wyiFLasX8Wgh+8MgFxolpvjlX3/QdTTJqEc
+rofVGOPOmfoHo3eYNJOlLbaJTDIe8OrK49PIeu1gm8zqB2WYqmF/3AYy4IAIwUYu
+rbPwUC9HyceRPSYePM9Wf1xM2proK3nmp6apdHCRNjbd4689ELmB90b2aw6NFiam
+3taKPmFLb/vt2YxgqOtagPrTlc1QLHBKrsnpg/BhcBjupqRKGFmXCJziPIaDKvAs
+jtg4KDo8jNIxmwQAwEV4+aH0hhMumxa8yaXoC/3G6JxD2sdoraOp+vrTzjUMkIoc
+xLqWl8GHVLF09fZJ4StJfIWIOmmpicSxW1vDICaZuU+iPwlNOzF7sePRkixbarHr
+iqTlLG//+Huq/n9IRxhzmSOur63WMXFRy0sKW5W+uQ9xsnV8SdjwRmAGLtnZHq4Y
+NOCQ/+yORl4yxkPvV01HykAl4CRtPBGR+4ZC5NKhpyhJbu6WcqwiXyAehU/cPgL+
+h8NwEoyP+OHrvEYdy4ocBnJq/436WwzfWis8nIG4bSlD3DSEgJF/QUmq4i/EUq/A
+D6SfzbFpPGtTj3KZ6D8DPrwWG68OCFsqRW9YEvUIK8JT265BN3MzI5i0/+k4CdAg
+aSaiC97qg7qJaVM9b9EHscUXR/feFxvO5QkkkY5CTU3Bxb0s1I4Rw2MYoAdMGtbA
+6mdzmRVYoRv9NMdzL6zOToPU6oOg6mbjHgZQgNd7w8GtTFW+sfslLOXXC8erzbHl
+ByQJGcFGtKTBUD+7VHZhpwM7bPObtzyA2r0UbS1Qx0IznvubdFVcXyE7dIjW7cAg
+IbBzKeiERwpu3rMq2bYVW3DA33VlrTfpjXujhHv1iX15i6qsWd7OtZw6x7TccH1Z
+jdmh9XB9xDydnss3u9DwGREMYC9TdPZY/nui6lgCjjOhaTaunMuigFBMWUBkDlIb
+uju+Atv+PSBT9DmTyTQGhPZRIw==
 -----END ENCRYPTED PRIVATE KEY-----
diff --git a/third_party/blink/web_tests/external/wpt/tools/certs/cacert.pem b/third_party/blink/web_tests/external/wpt/tools/certs/cacert.pem
index 49b343a..e1b5add 100644
--- a/third_party/blink/web_tests/external/wpt/tools/certs/cacert.pem
+++ b/third_party/blink/web_tests/external/wpt/tools/certs/cacert.pem
@@ -1,116 +1,125 @@
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number: 372738 (0x5b002)
-    Signature Algorithm: sha256WithRSAEncryption
-        Issuer: CN=web-platform-tests
-        Validity
-            Not Before: Dec 20 12:20:35 2018 GMT
-            Not After : Dec 17 12:20:35 2028 GMT
-        Subject: CN=web-platform-tests
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-                Public-Key: (2048 bit)
-                Modulus:
-                    00:a5:c0:b9:6d:f2:13:01:17:f3:ec:bf:91:db:4f:
-                    cd:4a:73:c7:d1:6a:b8:0d:c0:1e:7a:06:df:f2:f6:
-                    08:c1:36:a2:11:da:fb:0a:7a:2a:4f:a9:c0:6f:19:
-                    0b:e2:6d:26:3a:f9:3e:71:29:45:a4:4f:27:1d:6d:
-                    ef:40:98:dc:01:7f:2c:4f:e2:35:4d:2b:8e:97:c5:
-                    41:9e:cd:f4:0e:60:fc:65:a4:39:5c:88:36:05:60:
-                    e8:7f:b4:b4:32:9c:70:47:08:15:51:c8:cb:d8:21:
-                    ba:54:48:73:72:e3:8a:95:61:e6:00:ef:e3:5f:f6:
-                    18:b6:4e:24:b5:41:7f:ce:b2:d7:28:33:ee:06:21:
-                    4f:cb:d6:4f:55:3a:bb:4f:74:e9:b6:e8:3b:cc:a7:
-                    bb:f3:86:7a:c8:71:e1:f4:f2:2b:fe:1f:71:5e:1f:
-                    49:12:f9:c3:8a:7e:dc:5f:75:38:4d:7b:4a:a2:e5:
-                    6e:bf:ce:d9:9c:99:af:a7:6e:38:97:3c:b5:3f:13:
-                    0c:63:7e:78:ee:e4:ad:d8:18:c7:ec:da:38:44:49:
-                    af:fb:44:8d:79:29:db:cf:4c:0a:6a:fd:5a:54:15:
-                    e0:cd:ac:4d:17:5d:ef:58:c8:3d:84:fd:20:79:55:
-                    9f:14:c7:c8:5f:c8:98:5c:3c:ff:53:89:c5:1f:e7:
-                    83:a3
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Basic Constraints: 
-                CA:TRUE
-            X509v3 Subject Key Identifier: 
-                7A:EA:6A:75:AA:23:78:B5:5E:06:61:4A:56:CF:56:A9:6D:B0:54:02
-            X509v3 Authority Key Identifier: 
-                keyid:7A:EA:6A:75:AA:23:78:B5:5E:06:61:4A:56:CF:56:A9:6D:B0:54:02
-                DirName:/CN=web-platform-tests
-                serial:05:B0:02
-
-            X509v3 Key Usage: 
-                Certificate Sign
-            X509v3 Name Constraints: 
-                Permitted:
-                  DNS:web-platform.test
-                  DNS:not-web-platform.test
-                  DNS:www.web-platform.test
-                  DNS:www1.web-platform.test
-                  DNS:www2.web-platform.test
-                  DNS:www.not-web-platform.test
-                  DNS:www2.not-web-platform.test
-                  DNS:www1.not-web-platform.test
-                  DNS:xn--lve-6lad.web-platform.test
-                  DNS:xn--lve-6lad.not-web-platform.test
-                  DNS:xn--n8j6ds53lwwkrqhv28a.web-platform.test
-                  DNS:xn--n8j6ds53lwwkrqhv28a.not-web-platform.test
-
-            X509v3 Extended Key Usage: 
-                TLS Web Server Authentication
-            X509v3 Subject Alternative Name: 
-                DNS:web-platform.test, DNS:not-web-platform.test, DNS:www.web-platform.test, DNS:www1.web-platform.test, DNS:www2.web-platform.test, DNS:www.not-web-platform.test, DNS:www2.not-web-platform.test, DNS:www1.not-web-platform.test, DNS:xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.not-web-platform.test
-    Signature Algorithm: sha256WithRSAEncryption
-         57:8e:97:2b:a5:3f:82:be:c9:80:b3:ef:0f:c8:b9:4c:f2:a6:
-         91:40:ab:1f:70:0e:31:fb:74:ae:17:23:ea:b1:c8:19:f7:29:
-         13:da:59:aa:61:7f:24:17:24:84:22:81:4c:23:b1:e6:a8:d8:
-         65:95:b0:a9:2e:2d:b8:8f:86:67:69:b8:d2:7a:87:d3:75:67:
-         6a:24:2a:a9:af:31:a6:33:2a:50:46:c4:2e:37:f0:e0:e0:a1:
-         e0:fe:bb:2f:6a:8d:9c:a6:45:cd:3f:8f:cd:fd:95:b1:70:24:
-         b8:2b:39:56:3f:81:0d:42:59:0a:8e:b2:c4:a7:1b:8a:73:98:
-         51:4d:f5:14:ab:8b:95:dc:5e:6a:bc:30:57:79:16:3e:6c:73:
-         09:f9:be:1b:4b:bf:cb:f4:ae:3a:ad:0e:57:20:e7:2f:f5:1f:
-         b3:7b:cf:1a:77:73:94:c6:f5:08:d5:24:29:12:9c:f1:0a:75:
-         99:43:7b:91:c7:69:6f:ff:86:10:54:94:22:73:f9:00:c2:91:
-         3d:6d:52:e5:5a:c6:43:e2:37:84:4c:59:02:b7:59:6c:b0:c5:
-         18:72:03:61:94:00:11:e6:a3:cb:18:99:3e:8e:a2:00:82:4a:
-         65:c3:08:3b:c9:10:19:c3:09:44:3c:a9:b0:2a:c3:84:2c:46:
-         43:ba:dc:bf
 -----BEGIN CERTIFICATE-----
-MIIGVzCCBT+gAwIBAgIDBbACMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
-Yi1wbGF0Zm9ybS10ZXN0czAeFw0xODEyMjAxMjIwMzVaFw0yODEyMTcxMjIwMzVa
+MIIW5zCCFc+gAwIBAgIDBbFHMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
+Yi1wbGF0Zm9ybS10ZXN0czAeFw0xOTEwMTQxMzQ5MjlaFw0yOTEwMTExMzQ5Mjla
 MB0xGzAZBgNVBAMMEndlYi1wbGF0Zm9ybS10ZXN0czCCASIwDQYJKoZIhvcNAQEB
-BQADggEPADCCAQoCggEBAKXAuW3yEwEX8+y/kdtPzUpzx9FquA3AHnoG3/L2CME2
-ohHa+wp6Kk+pwG8ZC+JtJjr5PnEpRaRPJx1t70CY3AF/LE/iNU0rjpfFQZ7N9A5g
-/GWkOVyINgVg6H+0tDKccEcIFVHIy9ghulRIc3LjipVh5gDv41/2GLZOJLVBf86y
-1ygz7gYhT8vWT1U6u0906bboO8ynu/OGeshx4fTyK/4fcV4fSRL5w4p+3F91OE17
-SqLlbr/O2ZyZr6duOJc8tT8TDGN+eO7krdgYx+zaOERJr/tEjXkp289MCmr9WlQV
-4M2sTRdd71jIPYT9IHlVnxTHyF/ImFw8/1OJxR/ng6MCAwEAAaOCA54wggOaMAwG
-A1UdEwQFMAMBAf8wHQYDVR0OBBYEFHrqanWqI3i1XgZhSlbPVqltsFQCMEcGA1Ud
-IwRAMD6AFHrqanWqI3i1XgZhSlbPVqltsFQCoSGkHzAdMRswGQYDVQQDDBJ3ZWIt
-cGxhdGZvcm0tdGVzdHOCAwWwAjALBgNVHQ8EBAMCAgQwggGLBgNVHR4EggGCMIIB
-fqCCAXowE4IRd2ViLXBsYXRmb3JtLnRlc3QwF4IVbm90LXdlYi1wbGF0Zm9ybS50
+BQADggEPADCCAQoCggEBANQI10vytPN5G8m6cWePZLHYgBIJsWfjx2NWk/WFELoc
+DnUv2zRp5E27AhxEJJ6c6JGu+3WjT7l+fGykoK1RwOn4Oi/KNJnDE2XeSjQH/awP
+Mi2j0hAivTvCXnomTXn3cqcTkrapcDXV1+WUSaebJw+8wHLoJUWIbeU7KLVgXscf
+hLGBQB6p/uQewzmmb1bUbizF3GnbFxSbFgkK3Ttf9NpHqqRtgUAaZtP9eda/kRP7
+j0iIQncCyhwUMcEg/9YsKeLOSUGzLjUSCJqOIvULnQwRBYjIEwui00qdChqV8chz
+Kbk32dj6vLFs3t7P+xoj/JjZXZiWQFTzFSVjpS5A7MECAwEAAaOCFC4wghQqMAwG
+A1UdEwQFMAMBAf8wHQYDVR0OBBYEFEFJ/4xmUF+HoQaou6uK3XMNDjcaMEcGA1Ud
+IwRAMD6AFEFJ/4xmUF+HoQaou6uK3XMNDjcaoSGkHzAdMRswGQYDVQQDDBJ3ZWIt
+cGxhdGZvcm0tdGVzdHOCAwWxRzALBgNVHQ8EBAMCAgQwggoFBgNVHR4Eggn8MIIJ
++KCCCfQwE4IRd2ViLXBsYXRmb3JtLnRlc3QwF4IVbm90LXdlYi1wbGF0Zm9ybS50
 ZXN0MBeCFXd3dy53ZWItcGxhdGZvcm0udGVzdDAYghZ3d3cxLndlYi1wbGF0Zm9y
 bS50ZXN0MBiCFnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwG4IZd3d3Lm5vdC13ZWIt
-cGxhdGZvcm0udGVzdDAcghp3d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdDAcghp3
-d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdDAggh54bi0tbHZlLTZsYWQud2ViLXBs
-YXRmb3JtLnRlc3QwJIIieG4tLWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0udGVz
-dDArgil4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdDAv
-gi14bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3Qw
-EwYDVR0lBAwwCgYIKwYBBQUHAwEwggFvBgNVHREEggFmMIIBYoIRd2ViLXBsYXRm
-b3JtLnRlc3SCFW5vdC13ZWItcGxhdGZvcm0udGVzdIIVd3d3LndlYi1wbGF0Zm9y
-bS50ZXN0ghZ3d3cxLndlYi1wbGF0Zm9ybS50ZXN0ghZ3d3cyLndlYi1wbGF0Zm9y
-bS50ZXN0ghl3d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cyLm5vdC13ZWIt
-cGxhdGZvcm0udGVzdIIad3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCHnhuLS1s
-dmUtNmxhZC53ZWItcGxhdGZvcm0udGVzdIIieG4tLWx2ZS02bGFkLm5vdC13ZWIt
-cGxhdGZvcm0udGVzdIIpeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRm
-b3JtLnRlc3SCLXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5vdC13ZWItcGxhdGZv
-cm0udGVzdDANBgkqhkiG9w0BAQsFAAOCAQEAV46XK6U/gr7JgLPvD8i5TPKmkUCr
-H3AOMft0rhcj6rHIGfcpE9pZqmF/JBckhCKBTCOx5qjYZZWwqS4tuI+GZ2m40nqH
-03VnaiQqqa8xpjMqUEbELjfw4OCh4P67L2qNnKZFzT+Pzf2VsXAkuCs5Vj+BDUJZ
-Co6yxKcbinOYUU31FKuLldxearwwV3kWPmxzCfm+G0u/y/SuOq0OVyDnL/Ufs3vP
-GndzlMb1CNUkKRKc8Qp1mUN7kcdpb/+GEFSUInP5AMKRPW1S5VrGQ+I3hExZArdZ
-bLDFGHIDYZQAEeajyxiZPo6iAIJKZcMIO8kQGcMJRDypsCrDhCxGQ7rcvw==
+cGxhdGZvcm0udGVzdDAbghl3d3cud3d3LndlYi1wbGF0Zm9ybS50ZXN0MByCGnd3
+dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzEubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGnd3dy53d3cyLndlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzIud3d3
+LndlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzEud3d3LndlYi1wbGF0Zm9ybS50ZXN0
+MByCGnd3dy53d3cxLndlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzEud3d3MS53ZWIt
+cGxhdGZvcm0udGVzdDAdght3d3cxLnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwHYIb
+d3d3Mi53d3cyLndlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzIud3d3MS53ZWItcGxh
+dGZvcm0udGVzdDAfgh13d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdDAggh53
+d3cud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3MS53d3cubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0MCCCHnhuLS1sdmUtNmxhZC53ZWItcGxhdGZvcm0udGVz
+dDAggh53d3cud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3Mi53d3cu
+bm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzIud3d3Mi5ub3Qtd2ViLXBsYXRm
+b3JtLnRlc3QwIYIfd3d3Mi53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdDAhgh93
+d3cxLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzEud3d3Mi5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3QwJIIieG4tLWx2ZS02bGFkLnd3dy53ZWItcGxhdGZv
+cm0udGVzdDAkgiJ3d3cueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0MCSC
+InhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4tLWx2ZS02
+bGFkLnd3dzEud2ViLXBsYXRmb3JtLnRlc3QwJYIjd3d3Mi54bi0tbHZlLTZsYWQu
+d2ViLXBsYXRmb3JtLnRlc3QwJYIjd3d3MS54bi0tbHZlLTZsYWQud2ViLXBsYXRm
+b3JtLnRlc3QwJYIjeG4tLWx2ZS02bGFkLnd3dzIud2ViLXBsYXRmb3JtLnRlc3Qw
+KIImeG4tLWx2ZS02bGFkLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKIImd3d3
+LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYIneG4tLWx2ZS02
+bGFkLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCmCJ3d3dzIueG4tLWx2ZS02
+bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdDApgid3d3cxLnhuLS1sdmUtNmxhZC5u
+b3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYIneG4tLWx2ZS02bGFkLnd3dzIubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0MCuCKXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndlYi1w
+bGF0Zm9ybS50ZXN0MC2CK3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQud2ViLXBs
+YXRmb3JtLnRlc3QwL4IteG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MC+CLXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dy53ZWIt
+cGxhdGZvcm0udGVzdDAvgi13d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi
+LXBsYXRmb3JtLnRlc3QwMIIud3d3MS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS53
+ZWItcGxhdGZvcm0udGVzdDAwgi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cx
+LndlYi1wbGF0Zm9ybS50ZXN0MDCCLnd3dzIueG4tLW44ajZkczUzbHd3a3JxaHYy
+OGEud2ViLXBsYXRmb3JtLnRlc3QwMIIueG4tLW44ajZkczUzbHd3a3JxaHYyOGEu
+d3d3Mi53ZWItcGxhdGZvcm0udGVzdDAxgi94bi0tbHZlLTZsYWQueG4tLWx2ZS02
+bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdDAzgjF4bi0tbjhqNmRzNTNsd3drcnFo
+djI4YS53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0MDOCMXd3dy54bi0tbjhqNmRz
+NTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwNIIyd3d3MS54bi0t
+bjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwNIIyeG4t
+LW44ajZkczUzbHd3a3JxaHYyOGEud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3Qw
+NIIyeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3MS5ub3Qtd2ViLXBsYXRmb3Jt
+LnRlc3QwNIIyd3d3Mi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3QwOII2eG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4tLWx2ZS02
+bGFkLndlYi1wbGF0Zm9ybS50ZXN0MDiCNnhuLS1sdmUtNmxhZC54bi0tbjhqNmRz
+NTNsd3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdDA8gjp4bi0tbHZlLTZsYWQu
+eG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MDyC
+OnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3QwQ4JBeG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4tLW44ajZk
+czUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3QwR4JFeG4tLW44ajZkczUz
+bHd3a3JxaHYyOGEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0
+Zm9ybS50ZXN0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMIIJhQYDVR0RBIIJfDCCCXiC
+EXdlYi1wbGF0Zm9ybS50ZXN0ghVub3Qtd2ViLXBsYXRmb3JtLnRlc3SCFXd3dy53
+ZWItcGxhdGZvcm0udGVzdIIWd3d3MS53ZWItcGxhdGZvcm0udGVzdIIWd3d3Mi53
+ZWItcGxhdGZvcm0udGVzdIIZd3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3
+Lnd3dy53ZWItcGxhdGZvcm0udGVzdIIad3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cud3d3Mi53ZWItcGxh
+dGZvcm0udGVzdIIad3d3Mi53d3cud2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEud3d3
+LndlYi1wbGF0Zm9ybS50ZXN0ghp3d3cud3d3MS53ZWItcGxhdGZvcm0udGVzdIIb
+d3d3MS53d3cxLndlYi1wbGF0Zm9ybS50ZXN0ght3d3cxLnd3dzIud2ViLXBsYXRm
+b3JtLnRlc3SCG3d3dzIud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIbd3d3Mi53d3cx
+LndlYi1wbGF0Zm9ybS50ZXN0gh13d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
+dIIed3d3Lnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0gh53d3cxLnd3dy5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3SCHnhuLS1sdmUtNmxhZC53ZWItcGxhdGZvcm0udGVz
+dIIed3d3Lnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gh53d3cyLnd3dy5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCH3d3dzIud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3MS5u
+b3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3Mi5ub3Qtd2ViLXBsYXRmb3Jt
+LnRlc3SCInhuLS1sdmUtNmxhZC53d3cud2ViLXBsYXRmb3JtLnRlc3SCInd3dy54
+bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3SCI3huLS1sdmUtNmxhZC53d3cxLndlYi1wbGF0Zm9y
+bS50ZXN0giN3d3cyLnhuLS1sdmUtNmxhZC53ZWItcGxhdGZvcm0udGVzdIIjd3d3
+MS54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCI3huLS1sdmUtNmxhZC53
+d3cyLndlYi1wbGF0Zm9ybS50ZXN0giZ4bi0tbHZlLTZsYWQud3d3Lm5vdC13ZWIt
+cGxhdGZvcm0udGVzdIImd3d3LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3Jt
+LnRlc3SCJ3huLS1sdmUtNmxhZC53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIn
+d3d3Mi54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0gid3d3cxLnhu
+LS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3huLS1sdmUtNmxhZC53
+d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIpeG4tLW44ajZkczUzbHd3a3JxaHYy
+OGEud2ViLXBsYXRmb3JtLnRlc3SCK3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQu
+d2ViLXBsYXRmb3JtLnRlc3SCLXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5vdC13
+ZWItcGxhdGZvcm0udGVzdIIteG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3Lndl
+Yi1wbGF0Zm9ybS50ZXN0gi13d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi
+LXBsYXRmb3JtLnRlc3SCLnd3dzEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi
+LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzEud2Vi
+LXBsYXRmb3JtLnRlc3SCLnd3dzIueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi
+LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzIud2Vi
+LXBsYXRmb3JtLnRlc3SCL3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0gjF4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0gjF3d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEu
+bm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ3d3cxLnhuLS1uOGo2ZHM1M2x3d2tycWh2
+MjhhLm5vdC13ZWItcGxhdGZvcm0udGVzdIIyeG4tLW44ajZkczUzbHd3a3JxaHYy
+OGEud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCMnhuLS1uOGo2ZHM1M2x3d2ty
+cWh2MjhhLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ3d3cyLnhuLS1uOGo2
+ZHM1M2x3d2tycWh2MjhhLm5vdC13ZWItcGxhdGZvcm0udGVzdII2eG4tLW44ajZk
+czUzbHd3a3JxaHYyOGEueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0gjZ4
+bi0tbHZlLTZsYWQueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3Jt
+LnRlc3SCOnhuLS1sdmUtNmxhZC54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1s
+dmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCQXhuLS1uOGo2ZHM1M2x3d2ty
+cWh2MjhhLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0
+gkV4bi0tbjhqNmRzNTNsd3drcnFodjI4YS54bi0tbjhqNmRzNTNsd3drcnFodjI4
+YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJKoZIhvcNAQELBQADggEBAHXiq1vA
+xjc8ij34i4b+8inVBVwTWyHtczlZnIQTCxqJCDk83pz8QFHGyHYz+db36U6YwHak
+I3HYhipPMB1VnlHkMA6xFuZL/aFWywLNU9nTmaAV0fP/R5k9vt8AEm0ZmEWkNYtL
+opcy0rqjAaXTIWes91OZfniTFQDHMiurK8Vq+fq/Ozw+YQbRbU1KlHCNayisvQa4
+TLO+DjMR0hzDT3DHEwPJLPYaa6RnIwo8zvCqk0ZRPAxeuldAe/u1PzteXRzEHTAE
+DMVLMwM752bLFufv1GRCZNHELZKyhUoFrP30AqE7r3pnwQRW8Kdid38IMo7u9Dem
+u5/tHefPKD7bm/Y=
 -----END CERTIFICATE-----
diff --git a/third_party/blink/web_tests/external/wpt/tools/certs/web-platform.test.key b/third_party/blink/web_tests/external/wpt/tools/certs/web-platform.test.key
index 6d60e89..b62af20 100644
--- a/third_party/blink/web_tests/external/wpt/tools/certs/web-platform.test.key
+++ b/third_party/blink/web_tests/external/wpt/tools/certs/web-platform.test.key
@@ -1,28 +1,28 @@
 -----BEGIN PRIVATE KEY-----
-MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpxFZDnnjgGrPj
-2OirthoMrhDXhgQ0MupElcIG3ZtE9PNAqT20Ysr7cYgg1vQdylSo1aK3ZcBbtfuQ
-8Yfa7+o6TiTcKiEmTWB34rJPx1t37rJz7nWC0JjIOArtpSIAI8yIXkAtw5TnHcL5
-AAC7alliVMyF15UVxdeTUgmvw5IUGzfRX9HUVhCFvxtsS+GTOoDLHFqYGH4Qc6sg
-dOEtzUPuRS51zKTwaG4QopCKfkvj3MLZ19/k0aJPibvLNACpkMlPFYZZekvt+WsB
-AUjtixXM8f9Yon2XV9F7MXvDsaZUgebuYt7qxaG0xGNez8riLIhQB8wGSIJ18Ziy
-VN62q9/bAgMBAAECggEAO9k7kBsOAfNn96tAW0iXZmD3DwPv93b7n7Ir9L+rPWQd
-XW5MkotBg+NCWlFtPhNWRS8Lbhww9CPzy+VaP5TUvjlORU+U4CvnFlyVAAsH8//y
-aWxngPaI5gzbzWup0OLN+EVB2uBYXiHf2mhl2axkVoYOlCCsLkDQ/t6tC4mmte9P
-JB8VuMWKDc+Q0bMyGQ9V/qgQuw38mYyuBrbS3pwG9/1S7qADZ4/HK85CtEY6f0wQ
-dyK7Rxjpo4eq/MWPTlrLYRZcPKkllFLLbU+346OPD06spMOxleYkMVLMhW9CZVSM
-cRqxa7MLel7XumUK+7oC5bXuBICrAu69XtW8E6fsAQKBgQDfp+e+gb/ISu5CPgFu
-/y2i191lr6uIIYTB8URx92WWqabim7U8YiSzaexY9qTNvMjxnn/qLnKvEtxLPjSx
-3J+3ewoE62G7QjNSzwTRNTrhDDzh9MhzIr3YtLvPwpobd++TpbtVHxYOEzT9dI/w
-jSIztVzLK+Md2ID7sqkwPxBmWQKBgQDCUWC99hi7mvmjoGsGpy5iZ5EL66GHlA9y
-ivgg+DCoFQ7twiASqmrsVwztFvEV2P/JZVMleHOvMumOSRdI6CG3GpXRWi4rSrS5
-K02bUS8GGE/Aobh2q6bNQfM2ujl+k/wlIIJHxlFb0JqLOEpuLft0Kf52odtLC8fV
-lGDsabwZUwKBgHYoH19e7rHjHDJ0zY8VUsfIIRf6kbVud9N6If3PhKTu5dKsDjhj
-ZR4/5HQvgWuLw+EaKlvOxBnH7gf2SiJ4+wwU/XsR22TxmWmzIslfxMZmD7gT+N4S
-yZc2DE67cWz3lOM82FYlASLYdNM+BFlCRoJo2yge/HKlEadngMiTWJepAoGAB9Ja
-wIq9aB/O2KVGaZglJ9TfY8lyURDGpmetoTYcT0e5uBxOSjIN58GBRbHctnJrqWGo
-vSNiFLVJ7W5Hv6mIYeRyD2E/5oI1UBbMIupbqDUmUKyxziUOq8hxz8wjMFMonR33
-4Ie9EqMM9XmolVLIgl6GXaQaPaUVwCUe2aVP6v0CgYEAtxJq1dY+w+79WXu6/pDj
-fX7Np07DRgrkmWL4db+ytQpONvbxXZwduSfb4dv3lfCiPzib+WXdxpGDOR94d/qL
-zhrQq25s44TtvdeUzdn5+lZYn+15ZtNgUTYDal82dxwIR56fCRdLWC26CwaBevXX
-lK3MgwivpX6mQ3nr7s/4x2A=
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCrZXVXmOPlqo/+
+2xj15PgcZGHGo/bofiQQ3gl6JL1VX1GptYINhTq2sUhfN8tCb+cHyzapO9oUmwqw
+p5Up7tJ4Ip7uE1/wwSxVcvCawG5/PN5iD7H2wsmEppHXOc3Ll085/gzes+1+Nn+q
+ARmp1bF/vjplD6VdH2rBW3sJ3DAoBaoXlAMfeRAFDpaqa+9lxMrM5WkUHndQ+uEM
+6kZyevhyp02XDP0vLwNCtPLGB0emAAfC7xpwRGVGStEsUhf/mc9yNNaKgqBKI0no
+oVnuU3RGdKHP18vcjtBSV0lYgjfg9a07OBu1hgQffhofi2BydfaCpBAMzFhlu1uy
+s6ahVkJpAgMBAAECggEAfmvzxY0MbFcGp2FMY/Nj3u1cAXznnk2MpLRiISoATXxl
+a9xp9TcUO7VAQJuS3YpUyrbltqZjEVfa5rp1l9yEegBvYgQAfEDARrblKgBOgKOR
+FJunFPBQW/vRDwOf/E+7LHdrXskwoCvqtqbhGxh4OFVEFU8ZFjsaL00e0AMNsjZl
+0OsEONlIH4nCa7E6DTasHxc1VkHQr3uvBl5/4HfOc05tr+ZKlMYXzAPWkL0sC216
+Dqy4AxJ0M0ax8BYEZuo0gqQmMAonJTkEnpyoD4z89S877vFp8w1VPbGYkV48yjV/
+I7fQ6Yjt3yg+as+s4arGEsUB0l+XApBYYY/J+qcYUQKBgQDed7DOMJUc3kPTFEcN
+p/EbSh9TXxS/74cIyGid9IEiREJYxYv8kz0KplGuJolIQ3/Ik9Rac6B3Tu4WkW0g
+TPbNunYEsydZBAnaQ4eAVdOfvRQ6V3eBZ2vErsHJRFaj5cOcesUXxBZI6m2tQESx
+dBWFDNG9kztr0HmaL6Puz4zZIwKBgQDFOxfR7FcpGdw61ziSsZmtvkf6epkG3+ou
+uhY50J0UrTbK7TuimkoRw/XHeBe4db+ejOOuLD9QE/yXvmtEWuyUTTYOVvZ+HuNj
+Rp3kdi1GuWXn6gRvdlkf9XwW7jHmgkpbA5A+uDXs3EYYa18LxPNfMSvhyHdkFnUG
+aTzyYNpdAwKBgGv/QNan4Qt1nwluU5v+hl6QGir4AnO2zR/nYloj4ziGWIsNw4pm
+1ABCg25+iLCLDBKMKU+LyD+DErPj/0zp7/opZbecXSKqgjnyBGq5v5VRTeuQoJQy
+Z6/AgpS5VzITjWV+eAW0jHjzTTEI/RAEYZoIgh18xyDswMuoCvYYzbBvAoGBAMM2
+I/Nw+ywBHotWrfXztunSpidy5Ld7NKyfHpSGuJLYhpz/hcEA+ULwM/oEEWZPlSN2
+y3t+7AN0ZNREcqMrY3G9oj07ManPJL0EDg8sMNAJfKW4aD9yYfBR50pC5D0ExFel
+BUYuyaDwvKg6zc42V7PmVUqaQiFcYOPBkcNMvZTFAoGBALBtdt0iIvtBopp+IQaV
+zZMA5ZQIQ5n5v071LKa1s7ar3+hIoDRsZbM7XkUIA8zQlrwFRhbU5YFNcbpooQSm
+7j4+fIudcpxj9tAMGAb5yg89k1DjTy7FUWL9elGIgvJMqgF6IQ53+vR8xwGDyQLB
+sP5mizF1wi47DYPJQcDRCzU+
 -----END PRIVATE KEY-----
diff --git a/third_party/blink/web_tests/external/wpt/tools/certs/web-platform.test.pem b/third_party/blink/web_tests/external/wpt/tools/certs/web-platform.test.pem
index c9f7f57..5959316 100644
--- a/third_party/blink/web_tests/external/wpt/tools/certs/web-platform.test.pem
+++ b/third_party/blink/web_tests/external/wpt/tools/certs/web-platform.test.pem
@@ -1,90 +1,133 @@
 Certificate:
     Data:
         Version: 3 (0x2)
-        Serial Number: 372739 (0x5b003)
+        Serial Number: 373064 (0x5b148)
     Signature Algorithm: sha256WithRSAEncryption
         Issuer: CN=web-platform-tests
         Validity
-            Not Before: Dec 20 12:20:36 2018 GMT
-            Not After : Dec 17 12:20:36 2028 GMT
+            Not Before: Oct 14 13:49:29 2019 GMT
+            Not After : Oct 11 13:49:29 2029 GMT
         Subject: CN=web-platform.test
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
                 Public-Key: (2048 bit)
                 Modulus:
-                    00:a9:c4:56:43:9e:78:e0:1a:b3:e3:d8:e8:ab:b6:
-                    1a:0c:ae:10:d7:86:04:34:32:ea:44:95:c2:06:dd:
-                    9b:44:f4:f3:40:a9:3d:b4:62:ca:fb:71:88:20:d6:
-                    f4:1d:ca:54:a8:d5:a2:b7:65:c0:5b:b5:fb:90:f1:
-                    87:da:ef:ea:3a:4e:24:dc:2a:21:26:4d:60:77:e2:
-                    b2:4f:c7:5b:77:ee:b2:73:ee:75:82:d0:98:c8:38:
-                    0a:ed:a5:22:00:23:cc:88:5e:40:2d:c3:94:e7:1d:
-                    c2:f9:00:00:bb:6a:59:62:54:cc:85:d7:95:15:c5:
-                    d7:93:52:09:af:c3:92:14:1b:37:d1:5f:d1:d4:56:
-                    10:85:bf:1b:6c:4b:e1:93:3a:80:cb:1c:5a:98:18:
-                    7e:10:73:ab:20:74:e1:2d:cd:43:ee:45:2e:75:cc:
-                    a4:f0:68:6e:10:a2:90:8a:7e:4b:e3:dc:c2:d9:d7:
-                    df:e4:d1:a2:4f:89:bb:cb:34:00:a9:90:c9:4f:15:
-                    86:59:7a:4b:ed:f9:6b:01:01:48:ed:8b:15:cc:f1:
-                    ff:58:a2:7d:97:57:d1:7b:31:7b:c3:b1:a6:54:81:
-                    e6:ee:62:de:ea:c5:a1:b4:c4:63:5e:cf:ca:e2:2c:
-                    88:50:07:cc:06:48:82:75:f1:98:b2:54:de:b6:ab:
-                    df:db
+                    00:ab:65:75:57:98:e3:e5:aa:8f:fe:db:18:f5:e4:
+                    f8:1c:64:61:c6:a3:f6:e8:7e:24:10:de:09:7a:24:
+                    bd:55:5f:51:a9:b5:82:0d:85:3a:b6:b1:48:5f:37:
+                    cb:42:6f:e7:07:cb:36:a9:3b:da:14:9b:0a:b0:a7:
+                    95:29:ee:d2:78:22:9e:ee:13:5f:f0:c1:2c:55:72:
+                    f0:9a:c0:6e:7f:3c:de:62:0f:b1:f6:c2:c9:84:a6:
+                    91:d7:39:cd:cb:97:4f:39:fe:0c:de:b3:ed:7e:36:
+                    7f:aa:01:19:a9:d5:b1:7f:be:3a:65:0f:a5:5d:1f:
+                    6a:c1:5b:7b:09:dc:30:28:05:aa:17:94:03:1f:79:
+                    10:05:0e:96:aa:6b:ef:65:c4:ca:cc:e5:69:14:1e:
+                    77:50:fa:e1:0c:ea:46:72:7a:f8:72:a7:4d:97:0c:
+                    fd:2f:2f:03:42:b4:f2:c6:07:47:a6:00:07:c2:ef:
+                    1a:70:44:65:46:4a:d1:2c:52:17:ff:99:cf:72:34:
+                    d6:8a:82:a0:4a:23:49:e8:a1:59:ee:53:74:46:74:
+                    a1:cf:d7:cb:dc:8e:d0:52:57:49:58:82:37:e0:f5:
+                    ad:3b:38:1b:b5:86:04:1f:7e:1a:1f:8b:60:72:75:
+                    f6:82:a4:10:0c:cc:58:65:bb:5b:b2:b3:a6:a1:56:
+                    42:69
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Basic Constraints: 
                 CA:FALSE
             X509v3 Subject Key Identifier: 
-                F7:EE:CA:20:37:0F:BC:CF:F3:B7:DC:12:76:D1:D1:CA:40:67:3A:6D
+                2A:18:0B:09:22:6E:28:D2:DB:FD:C2:2D:40:A6:F3:38:62:6E:C7:C5
             X509v3 Authority Key Identifier: 
-                keyid:7A:EA:6A:75:AA:23:78:B5:5E:06:61:4A:56:CF:56:A9:6D:B0:54:02
+                keyid:41:49:FF:8C:66:50:5F:87:A1:06:A8:BB:AB:8A:DD:73:0D:0E:37:1A
 
             X509v3 Key Usage: 
                 Digital Signature, Non Repudiation, Key Encipherment
             X509v3 Extended Key Usage: 
                 TLS Web Server Authentication
             X509v3 Subject Alternative Name: 
-                DNS:web-platform.test, DNS:not-web-platform.test, DNS:www.web-platform.test, DNS:www1.web-platform.test, DNS:www2.web-platform.test, DNS:www.not-web-platform.test, DNS:www2.not-web-platform.test, DNS:www1.not-web-platform.test, DNS:xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.not-web-platform.test
+                DNS:web-platform.test, DNS:not-web-platform.test, DNS:www.web-platform.test, DNS:www1.web-platform.test, DNS:www2.web-platform.test, DNS:www.not-web-platform.test, DNS:www.www.web-platform.test, DNS:www2.not-web-platform.test, DNS:www1.not-web-platform.test, DNS:www.www2.web-platform.test, DNS:www2.www.web-platform.test, DNS:www1.www.web-platform.test, DNS:www.www1.web-platform.test, DNS:www1.www1.web-platform.test, DNS:www1.www2.web-platform.test, DNS:www2.www2.web-platform.test, DNS:www2.www1.web-platform.test, DNS:www.www.not-web-platform.test, DNS:www.www2.not-web-platform.test, DNS:www1.www.not-web-platform.test, DNS:xn--lve-6lad.web-platform.test, DNS:www.www1.not-web-platform.test, DNS:www2.www.not-web-platform.test, DNS:www2.www2.not-web-platform.test, DNS:www2.www1.not-web-platform.test, DNS:www1.www1.not-web-platform.test, DNS:www1.www2.not-web-platform.test, DNS:xn--lve-6lad.www.web-platform.test, DNS:www.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www1.web-platform.test, DNS:www2.xn--lve-6lad.web-platform.test, DNS:www1.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www2.web-platform.test, DNS:xn--lve-6lad.www.not-web-platform.test, DNS:www.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www1.not-web-platform.test, DNS:www2.xn--lve-6lad.not-web-platform.test, DNS:www1.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www2.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.not-web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.not-web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test
     Signature Algorithm: sha256WithRSAEncryption
-         63:c9:58:a8:38:b5:1f:2d:41:9f:06:a3:50:bc:a4:da:f5:e9:
-         c6:05:64:0e:d6:7e:ee:31:8d:81:00:c1:90:fd:71:4d:3c:92:
-         44:7f:c5:b6:be:fe:8d:c0:85:90:04:5c:20:08:88:47:8c:b6:
-         0d:b4:1f:22:a8:10:a9:e7:0d:9d:a0:79:44:0b:f3:3a:77:e6:
-         e2:89:f9:a4:ee:dc:e9:6c:6c:2c:1c:6f:c6:fb:e3:2c:36:a3:
-         72:89:4e:c2:9c:51:23:cc:af:2f:9d:67:82:d2:59:ea:ff:fd:
-         ef:7c:bc:c8:ff:a7:19:43:64:e6:5f:82:28:c9:de:8e:97:e6:
-         42:e0:ca:74:e6:c8:e0:d3:6a:bc:04:ca:bb:53:f0:64:b1:31:
-         98:af:e1:b8:6b:7d:0c:ad:b3:e0:29:00:1b:50:af:30:b3:fa:
-         d4:d3:0e:45:4b:12:0d:5a:ea:11:cd:29:be:32:ea:4f:4f:7c:
-         58:7d:e2:33:37:b9:ce:0f:94:00:6d:16:e4:91:6f:e6:4c:47:
-         a7:cd:b7:f1:ab:86:68:e2:6e:c5:e9:60:b7:24:b1:aa:1b:f6:
-         f5:ce:a4:03:bf:ed:20:92:a9:f7:ad:57:61:ef:d8:9a:b6:df:
-         cb:2f:4d:3b:ab:8f:71:c4:f2:87:93:25:48:89:c5:9c:c8:d8:
-         46:c5:5e:ac
+         af:c2:ea:cc:6a:5e:49:e0:db:72:14:05:3c:21:a0:8b:ff:b6:
+         a9:71:82:f7:61:cd:23:2a:00:66:91:ac:01:99:63:38:11:21:
+         85:b2:57:92:0b:3f:79:68:f5:d8:59:8b:a7:74:19:eb:0b:e7:
+         3d:86:4e:66:d4:e6:2f:ff:ed:6c:7d:9a:5e:12:4e:bf:39:ff:
+         f7:d0:fb:52:53:a0:fb:b1:5c:9a:91:92:36:00:d8:a4:6f:f9:
+         9c:36:21:b2:c2:5e:14:11:ca:55:e7:88:30:60:8d:86:da:65:
+         26:ff:e2:45:36:2a:09:3d:a4:bb:38:61:4d:57:e4:c9:b6:50:
+         3c:06:2f:6b:bf:04:34:42:54:dc:53:b6:61:c5:4e:40:00:d6:
+         5e:19:17:3a:54:2c:c5:16:7a:6d:4a:70:56:45:cd:99:5a:2a:
+         d1:a7:4e:35:97:3d:d8:c9:95:80:ab:15:42:86:f6:a0:a6:c3:
+         21:c1:9a:07:34:49:ad:61:3c:bc:94:b2:2d:92:f7:44:80:01:
+         5f:27:bd:83:f5:51:22:39:cd:98:b1:39:23:b8:f4:5c:08:20:
+         9e:fe:f1:2d:9a:e9:9b:c7:5e:b8:33:8b:16:77:52:3d:c9:7a:
+         43:9e:25:d0:c7:5a:96:08:53:1a:dc:75:53:75:44:62:18:7c:
+         ef:fb:73:52
 -----BEGIN CERTIFICATE-----
-MIIEnDCCA4SgAwIBAgIDBbADMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
-Yi1wbGF0Zm9ybS10ZXN0czAeFw0xODEyMjAxMjIwMzZaFw0yODEyMTcxMjIwMzZa
+MIIMsjCCC5qgAwIBAgIDBbFIMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
+Yi1wbGF0Zm9ybS10ZXN0czAeFw0xOTEwMTQxMzQ5MjlaFw0yOTEwMTExMzQ5Mjla
 MBwxGjAYBgNVBAMMEXdlYi1wbGF0Zm9ybS50ZXN0MIIBIjANBgkqhkiG9w0BAQEF
-AAOCAQ8AMIIBCgKCAQEAqcRWQ5544Bqz49joq7YaDK4Q14YENDLqRJXCBt2bRPTz
-QKk9tGLK+3GIINb0HcpUqNWit2XAW7X7kPGH2u/qOk4k3CohJk1gd+KyT8dbd+6y
-c+51gtCYyDgK7aUiACPMiF5ALcOU5x3C+QAAu2pZYlTMhdeVFcXXk1IJr8OSFBs3
-0V/R1FYQhb8bbEvhkzqAyxxamBh+EHOrIHThLc1D7kUudcyk8GhuEKKQin5L49zC
-2dff5NGiT4m7yzQAqZDJTxWGWXpL7flrAQFI7YsVzPH/WKJ9l1fRezF7w7GmVIHm
-7mLe6sWhtMRjXs/K4iyIUAfMBkiCdfGYslTetqvf2wIDAQABo4IB5DCCAeAwCQYD
-VR0TBAIwADAdBgNVHQ4EFgQU9+7KIDcPvM/zt9wSdtHRykBnOm0wHwYDVR0jBBgw
-FoAUeupqdaojeLVeBmFKVs9WqW2wVAIwCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoG
-CCsGAQUFBwMBMIIBbwYDVR0RBIIBZjCCAWKCEXdlYi1wbGF0Zm9ybS50ZXN0ghVu
+AAOCAQ8AMIIBCgKCAQEAq2V1V5jj5aqP/tsY9eT4HGRhxqP26H4kEN4JeiS9VV9R
+qbWCDYU6trFIXzfLQm/nB8s2qTvaFJsKsKeVKe7SeCKe7hNf8MEsVXLwmsBufzze
+Yg+x9sLJhKaR1znNy5dPOf4M3rPtfjZ/qgEZqdWxf746ZQ+lXR9qwVt7CdwwKAWq
+F5QDH3kQBQ6WqmvvZcTKzOVpFB53UPrhDOpGcnr4cqdNlwz9Ly8DQrTyxgdHpgAH
+wu8acERlRkrRLFIX/5nPcjTWioKgSiNJ6KFZ7lN0RnShz9fL3I7QUldJWII34PWt
+OzgbtYYEH34aH4tgcnX2gqQQDMxYZbtbsrOmoVZCaQIDAQABo4IJ+jCCCfYwCQYD
+VR0TBAIwADAdBgNVHQ4EFgQUKhgLCSJuKNLb/cItQKbzOGJux8UwHwYDVR0jBBgw
+FoAUQUn/jGZQX4ehBqi7q4rdcw0ONxowCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoG
+CCsGAQUFBwMBMIIJhQYDVR0RBIIJfDCCCXiCEXdlYi1wbGF0Zm9ybS50ZXN0ghVu
 b3Qtd2ViLXBsYXRmb3JtLnRlc3SCFXd3dy53ZWItcGxhdGZvcm0udGVzdIIWd3d3
 MS53ZWItcGxhdGZvcm0udGVzdIIWd3d3Mi53ZWItcGxhdGZvcm0udGVzdIIZd3d3
-Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gh54bi0tbHZlLTZsYWQud2Vi
-LXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRl
-c3SCKXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0gi14
-bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJ
-KoZIhvcNAQELBQADggEBAGPJWKg4tR8tQZ8Go1C8pNr16cYFZA7Wfu4xjYEAwZD9
-cU08kkR/xba+/o3AhZAEXCAIiEeMtg20HyKoEKnnDZ2geUQL8zp35uKJ+aTu3Ols
-bCwcb8b74yw2o3KJTsKcUSPMry+dZ4LSWer//e98vMj/pxlDZOZfgijJ3o6X5kLg
-ynTmyODTarwEyrtT8GSxMZiv4bhrfQyts+ApABtQrzCz+tTTDkVLEg1a6hHNKb4y
-6k9PfFh94jM3uc4PlABtFuSRb+ZMR6fNt/GrhmjibsXpYLcksaob9vXOpAO/7SCS
-qfetV2Hv2Jq238svTTurj3HE8oeTJUiJxZzI2EbFXqw=
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3Lnd3dy53ZWItcGxhdGZvcm0udGVz
+dIIad3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEubm90LXdlYi1wbGF0
+Zm9ybS50ZXN0ghp3d3cud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIad3d3Mi53d3cu
+d2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEud3d3LndlYi1wbGF0Zm9ybS50ZXN0ghp3
+d3cud3d3MS53ZWItcGxhdGZvcm0udGVzdIIbd3d3MS53d3cxLndlYi1wbGF0Zm9y
+bS50ZXN0ght3d3cxLnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCG3d3dzIud3d3Mi53
+ZWItcGxhdGZvcm0udGVzdIIbd3d3Mi53d3cxLndlYi1wbGF0Zm9ybS50ZXN0gh13
+d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIed3d3Lnd3dzIubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0gh53d3cxLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCHnhu
+LS1sdmUtNmxhZC53ZWItcGxhdGZvcm0udGVzdIIed3d3Lnd3dzEubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0gh53d3cyLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3
+dzIud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3MS5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+H3d3dzEud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC53
+d3cud2ViLXBsYXRmb3JtLnRlc3SCInd3dy54bi0tbHZlLTZsYWQud2ViLXBsYXRm
+b3JtLnRlc3SCInhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCI3hu
+LS1sdmUtNmxhZC53d3cxLndlYi1wbGF0Zm9ybS50ZXN0giN3d3cyLnhuLS1sdmUt
+NmxhZC53ZWItcGxhdGZvcm0udGVzdIIjd3d3MS54bi0tbHZlLTZsYWQud2ViLXBs
+YXRmb3JtLnRlc3SCI3huLS1sdmUtNmxhZC53d3cyLndlYi1wbGF0Zm9ybS50ZXN0
+giZ4bi0tbHZlLTZsYWQud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIImd3d3Lnhu
+LS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3huLS1sdmUtNmxhZC53
+d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIInd3d3Mi54bi0tbHZlLTZsYWQubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0gid3d3cxLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCJ3huLS1sdmUtNmxhZC53d3cyLm5vdC13ZWItcGxhdGZvcm0u
+dGVzdIIpeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SC
+K3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCLXhu
+LS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5vdC13ZWItcGxhdGZvcm0udGVzdIIteG4t
+LW44ajZkczUzbHd3a3JxaHYyOGEud3d3LndlYi1wbGF0Zm9ybS50ZXN0gi13d3cu
+eG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzEu
+eG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1u
+OGo2ZHM1M2x3d2tycWh2MjhhLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzIu
+eG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1u
+OGo2ZHM1M2x3d2tycWh2MjhhLnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCL3huLS1s
+dmUtNmxhZC54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF4bi0t
+bjhqNmRzNTNsd3drcnFodjI4YS53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF3
+d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+gjJ3d3cxLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5vdC13ZWItcGxhdGZvcm0u
+dGVzdIIyeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3Mi5ub3Qtd2ViLXBsYXRm
+b3JtLnRlc3SCMnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzEubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0gjJ3d3cyLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5vdC13
+ZWItcGxhdGZvcm0udGVzdII2eG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4tLWx2
+ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0gjZ4bi0tbHZlLTZsYWQueG4tLW44ajZk
+czUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1sdmUtNmxhZC54
+bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCOnhu
+LS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRm
+b3JtLnRlc3SCQXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1uOGo2ZHM1M2x3
+d2tycWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0gkV4bi0tbjhqNmRzNTNsd3drcnFo
+djI4YS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3QwDQYJKoZIhvcNAQELBQADggEBAK/C6sxqXkng23IUBTwhoIv/tqlxgvdhzSMq
+AGaRrAGZYzgRIYWyV5ILP3lo9dhZi6d0GesL5z2GTmbU5i//7Wx9ml4STr85//fQ
++1JToPuxXJqRkjYA2KRv+Zw2IbLCXhQRylXniDBgjYbaZSb/4kU2Kgk9pLs4YU1X
+5Mm2UDwGL2u/BDRCVNxTtmHFTkAA1l4ZFzpULMUWem1KcFZFzZlaKtGnTjWXPdjJ
+lYCrFUKG9qCmwyHBmgc0Sa1hPLyUsi2S90SAAV8nvYP1USI5zZixOSO49FwIIJ7+
+8S2a6ZvHXrgzixZ3Uj3JekOeJdDHWpYIUxrcdVN1RGIYfO/7c1I=
 -----END CERTIFICATE-----
diff --git a/third_party/blink/web_tests/external/wpt/tools/ci/run_tc.py b/third_party/blink/web_tests/external/wpt/tools/ci/run_tc.py
index 3201ff3..956d1c3 100755
--- a/third_party/blink/web_tests/external/wpt/tools/ci/run_tc.py
+++ b/third_party/blink/web_tests/external/wpt/tools/ci/run_tc.py
@@ -41,6 +41,7 @@
 import re
 import subprocess
 import sys
+import tempfile
 try:
     from urllib2 import urlopen
 except ImportError:
@@ -149,20 +150,35 @@
     # Configure webkitgtk.org/debian repository for $channel and pin it with maximum priority
     run(["sudo", "apt-key", "adv", "--fetch-keys", "https://webkitgtk.org/debian/apt.key"])
     with open("/tmp/webkitgtk.list", "w") as f:
-        f.write("deb [arch=amd64] https://webkitgtk.org/debian buster-wpt-webkit-updates %s\n" % channel)
+        f.write("deb [arch=amd64] https://webkitgtk.org/apt bionic-wpt-webkit-updates %s\n" % channel)
     run(["sudo", "mv", "/tmp/webkitgtk.list", "/etc/apt/sources.list.d/"])
     with open("/tmp/99webkitgtk", "w") as f:
         f.write("Package: *\nPin: origin webkitgtk.org\nPin-Priority: 1999\n")
     run(["sudo", "mv", "/tmp/99webkitgtk", "/etc/apt/preferences.d/"])
-    # Install webkit2gtk from the webkitgtk.org/debian repository for $channel
+    # Install webkit2gtk from the webkitgtk.org/apt repository for $channel
     run(["sudo", "apt-get", "-qqy", "update"])
     run(["sudo", "apt-get", "-qqy", "upgrade"])
-    run(["sudo", "apt-get", "-qqy", "-t", "buster-wpt-webkit-updates", "install", "webkit2gtk-driver"])
+    run(["sudo", "apt-get", "-qqy", "-t", "bionic-wpt-webkit-updates", "install", "webkit2gtk-driver"])
+
+
+def install_webkitgtk_from_tarball_bundle(channel):
+    with tempfile.NamedTemporaryFile(suffix=".tar.xz") as temp_tarball:
+        resp = urlopen("https://webkitgtk.org/built-products/nightly/webkitgtk-nightly-build-last.tar.xz")
+        while True:
+            chunk = resp.read(16*1024)
+            if not chunk:
+                break
+            temp_tarball.write(chunk)
+        temp_tarball.flush()
+        run(["sudo", "tar", "xfa", temp_tarball.name, "-C", "/"])
+    # Install dependencies
+    run(["sudo", "apt-get", "-qqy", "update"])
+    run(["sudo", "/opt/webkitgtk/nightly/install-dependencies"])
 
 
 def install_webkitgtk(channel):
     if channel in ("experimental", "dev", "nightly"):
-        raise NotImplementedError("Still can't install from release channel: %s" % channel)
+        install_webkitgtk_from_tarball_bundle(channel)
     elif channel in ("beta", "stable"):
         install_webkitgtk_from_apt_repository(channel)
     else:
diff --git a/third_party/blink/web_tests/external/wpt/tools/docker/Dockerfile.webkitgtk b/third_party/blink/web_tests/external/wpt/tools/docker/Dockerfile.webkitgtk
deleted file mode 100644
index 58080def..0000000
--- a/third_party/blink/web_tests/external/wpt/tools/docker/Dockerfile.webkitgtk
+++ /dev/null
@@ -1,82 +0,0 @@
-# This image for WebKitGTK tests is based on Debian stable to ensure binary
-# compatibility with ToT/trunk built-products from build.webkit.org bots.
-# See https://github.com/web-platform-tests/wpt/pull/18595#issuecomment-537267080
-FROM debian:10
-
-# No interactive frontend during docker build
-ENV DEBIAN_FRONTEND=noninteractive \
-    DEBCONF_NONINTERACTIVE_SEEN=true
-
-
-# Update and upgrade.
-RUN apt-get -qqy update \
-  && apt-get -qqy upgrade
-
-# Install general requirements not in the base image
-RUN apt-get -qqy install \
-    bzip2 \
-    ca-certificates \
-    dbus-x11 \
-    earlyoom \
-    fluxbox \
-    gdebi \
-    git \
-    locales \
-    pulseaudio \
-    python \
-    python-pip \
-    python-virtualenv \
-    tzdata \
-    sudo \
-    unzip \
-    wget \
-    xvfb \
-    git-core
-
-
-# To speed up testers, cache in the image most of WebKitGTK dependencies
-# but don't install them (that will be done at test time)
-RUN apt-get install -qqy --download-only webkit2gtk-driver
-
-# Set the timezone
-ENV TZ "UTC"
-RUN echo "${TZ}" > /etc/timezone \
-  && dpkg-reconfigure --frontend noninteractive tzdata
-
-# Set the locale
-RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
-  && dpkg-reconfigure --frontend noninteractive locales
-ENV LANG en_US.UTF-8
-ENV LANGUAGE en_US:en
-ENV LC_ALL en_US.UTF-8
-
-RUN useradd test \
-         --shell /bin/bash  \
-         --create-home \
-  && usermod -a -G sudo test \
-  && echo 'ALL ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers \
-  && echo 'test:secret' | chpasswd
-
-ENV SCREEN_WIDTH 1280
-ENV SCREEN_HEIGHT 1024
-ENV SCREEN_DEPTH 24
-ENV DISPLAY :99.0
-
-USER test
-
-WORKDIR /home/test
-
-# Remove information on how to use sudo on login
-RUN sudo echo ""
-
-RUN mkdir -p /home/test/artifacts
-RUN mkdir -p /home/test/bin
-
-ENV PATH="/home/test/bin:/home/test/.local/bin:${PATH}"
-
-WORKDIR /home/test/
-
-COPY .bashrc /home/test/.bashrc
-
-COPY start.sh /home/test/start.sh
-COPY retry.py /home/test/bin/retry
diff --git a/third_party/blink/web_tests/external/wpt/tools/docker/README.md b/third_party/blink/web_tests/external/wpt/tools/docker/README.md
index 6bcc47c..450981f6 100644
--- a/third_party/blink/web_tests/external/wpt/tools/docker/README.md
+++ b/third_party/blink/web_tests/external/wpt/tools/docker/README.md
@@ -1,6 +1,6 @@
-This docker images is used for testing Chrome, Firefox and running other tasks
-on Taskcluster. When any of the files in this directory change, the images must
-be updated as well. To do this, assuming you have docker installed:
+This docker images is used for testing Chrome, Firefox, WebKitGTK and running
+other tasks on Taskcluster. When any of the files in this directory change, the
+images must be updated as well. To do this, assuming you have docker installed:
 
 In this directory, run
 ```sh
@@ -8,10 +8,3 @@
 docker push <tag>
 ```
 
-Then update the `image` specified in the project's .taskcluster.yml file.
-
-To update the image used for WebKitGTK:
-```sh
-docker build -f Dockerfile.webkitgtk -t <tag> .
-docker push <tag>
-```
diff --git a/third_party/blink/web_tests/external/wpt/tools/docker/github/Dockerfile b/third_party/blink/web_tests/external/wpt/tools/docker/github/Dockerfile
deleted file mode 100644
index 22d47f3..0000000
--- a/third_party/blink/web_tests/external/wpt/tools/docker/github/Dockerfile
+++ /dev/null
@@ -1,29 +0,0 @@
-FROM ubuntu:18.04
-
-# No interactive frontend during docker build
-ENV DEBIAN_FRONTEND=noninteractive \
-    DEBCONF_NONINTERACTIVE_SEEN=true
-
-RUN apt-get -qqy update \
-  && apt-get -qqy install \
-    bzip2 \
-    git \
-    locales \
-    python \
-    python-pip \
-    tzdata \
-    zstd
-
-RUN pip install --upgrade pip
-RUN pip install virtualenv
-RUN pip install requests
-
-ENV TZ "UTC"
-RUN echo "${TZ}" > /etc/timezone \
-  && dpkg-reconfigure --frontend noninteractive tzdata
-
-# Set the locale
-RUN locale-gen en_US.UTF-8
-ENV LANG en_US.UTF-8
-ENV LANGUAGE en_US:en
-ENV LC_ALL en_US.UTF-8
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/browser.py b/third_party/blink/web_tests/external/wpt/tools/wpt/browser.py
index c04162f..233778f 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wpt/browser.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wpt/browser.py
@@ -1118,10 +1118,15 @@
                 pass
         # Add Debian/Ubuntu path
         libexecpaths.append("/usr/lib/%s/webkit2gtk-4.0" % triplet)
+        if channel == "nightly":
+            libexecpaths.append("/opt/webkitgtk/nightly")
         return find_executable("MiniBrowser", os.pathsep.join(libexecpaths))
 
     def find_webdriver(self, channel=None):
-        return find_executable("WebKitWebDriver")
+        path = os.environ['PATH']
+        if channel == "nightly":
+            path = "%s:%s" % (path, "/opt/webkitgtk/nightly")
+        return find_executable("WebKitWebDriver", path)
 
     def version(self, binary=None, webdriver_binary=None):
         if binary is None:
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
index 077d4a7..de20e291 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
@@ -592,14 +592,14 @@
 
     def setup_kwargs(self, kwargs):
         if kwargs["binary"] is None:
-            binary = self.browser.find_binary()
+            binary = self.browser.find_binary(channel=kwargs["browser_channel"])
 
             if binary is None:
                 raise WptrunError("Unable to find MiniBrowser binary")
             kwargs["binary"] = binary
 
         if kwargs["webdriver_binary"] is None:
-            webdriver_binary = self.browser.find_webdriver()
+            webdriver_binary = self.browser.find_webdriver(channel=kwargs["browser_channel"])
 
             if webdriver_binary is None:
                 raise WptrunError("Unable to find WebKitWebDriver in PATH")
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/README.rst b/third_party/blink/web_tests/external/wpt/tools/wptrunner/README.rst
index d4f976d..0adf0a9 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/README.rst
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/README.rst
@@ -3,239 +3,12 @@
 
 wptrunner is a harness for running the W3C `web-platform-tests testsuite`_.
 
-.. contents::
+.. toctree::
+   :maxdepth: 2
 
-Installation
-~~~~~~~~~~~~
-
-wptrunner is expected to be installed into a virtualenv using pip. For
-development, it can be installed using the `-e` option::
-
-  pip install -e ./
-
-Running the Tests
-~~~~~~~~~~~~~~~~~
-
-After installation, the command ``wptrunner`` should be available to run
-the tests.
-
-The ``wptrunner`` command  takes multiple options, of which the
-following are most significant:
-
-``--product`` (defaults to `firefox`)
-  The product to test against: `chrome`, `firefox`, or `servo`.
-
-``--binary`` (required if product is `firefox` or `servo`)
-  The path to a binary file for the product (browser) to test against.
-
-``--webdriver-binary`` (required if product is `chrome`)
-  The path to a `driver` binary; e.g., a `chromedriver` binary.
-
-``--certutil-binary`` (required if product is `firefox` [#]_)
-  The path to a `certutil` binary (for tests that must be run over https).
-
-``--metadata`` (required)
-  The path to a directory containing test metadata. [#]_
-
-``--tests`` (required)
-  The path to a directory containing a web-platform-tests checkout.
-
-``--prefs-root`` (required only when testing a Firefox binary)
-  The path to a directory containing Firefox test-harness preferences. [#]_
-
-``--config`` (should default to `wptrunner.default.ini`)
-  The path to the config (ini) file.
-
-.. [#] The ``--certutil-binary`` option is required when the product is
-   ``firefox`` unless ``--ssl-type=none`` is specified.
-
-.. [#] The ``--metadata`` path is to a directory that contains:
-
-  * a ``MANIFEST.json`` file (instructions on generating this file are
-    available in the `detailed documentation
-    <http://wptrunner.readthedocs.org/en/latest/usage.html#installing-wptrunner>`_);
-    and
-  * (optionally) any expectation files (see below)
-
-.. [#] Example ``--prefs-root`` value: ``~/mozilla-central/testing/profiles``.
-
-There are also a variety of other options available; use ``--help`` to
-list them.
-
--------------------------------
-Example: How to start wptrunner
--------------------------------
-
-To test a Firefox Nightly build in an OS X environment, you might start
-wptrunner using something similar to the following example::
-
-  wptrunner --metadata=~/web-platform-tests/ --tests=~/web-platform-tests/ \
-    --binary=~/mozilla-central/obj-x86_64-apple-darwin14.3.0/dist/Nightly.app/Contents/MacOS/firefox \
-    --certutil-binary=~/mozilla-central/obj-x86_64-apple-darwin14.3.0/security/nss/cmd/certutil/certutil \
-    --prefs-root=~/mozilla-central/testing/profiles
-
-And to test a Chromium build in an OS X environment, you might start
-wptrunner using something similar to the following example::
-
-  wptrunner --metadata=~/web-platform-tests/ --tests=~/web-platform-tests/ \
-    --binary=~/chromium/src/out/Release/Chromium.app/Contents/MacOS/Chromium \
-    --webdriver-binary=/usr/local/bin/chromedriver --product=chrome
-
--------------------------------------
-Example: How to run a subset of tests
--------------------------------------
-
-To restrict a test run just to tests in a particular web-platform-tests
-subdirectory, specify the directory name in the positional arguments after
-the options; for example, run just the tests in the `dom` subdirectory::
-
-  wptrunner --metadata=~/web-platform-tests/ --tests=~/web-platform-tests/ \
-    --binary=/path/to/firefox --certutil-binary=/path/to/certutil \
-    --prefs-root=/path/to/testing/profiles \
-    dom
-
-Output
-~~~~~~
-
-By default wptrunner just dumps its entire output as raw JSON messages
-to stdout. This is convenient for piping into other tools, but not ideal
-for humans reading the output.
-
-As an alternative, you can use the ``--log-mach`` option, which provides
-output in a reasonable format for humans. The option requires a value:
-either the path for a file to write the `mach`-formatted output to, or
-"`-`" (a hyphen) to write the `mach`-formatted output to stdout.
-
-When using ``--log-mach``, output of the full raw JSON log is still
-available, from the ``--log-raw`` option. So to output the full raw JSON
-log to a file and a human-readable summary to stdout, you might start
-wptrunner using something similar to the following example::
-
-  wptrunner --metadata=~/web-platform-tests/ --tests=~/web-platform-tests/ \
-    --binary=/path/to/firefox --certutil-binary=/path/to/certutil \
-    --prefs-root=/path/to/testing/profiles \
-    --log-raw=output.log --log-mach=-
-
-Expectation Data
-~~~~~~~~~~~~~~~~
-
-wptrunner is designed to be used in an environment where it is not
-just necessary to know which tests passed, but to compare the results
-between runs. For this reason it is possible to store the results of a
-previous run in a set of ini-like "expectation files". This format is
-documented below. To generate the expectation files use `wptrunner` with
-the `--log-raw=/path/to/log/file` option. This can then be used as
-input to the `wptupdate` tool.
-
-Expectation File Format
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Metadata about tests, notably including their expected results, is
-stored in a modified ini-like format that is designed to be human
-editable, but also to be machine updatable.
-
-Each test file that requires metadata to be specified (because it has
-a non-default expectation or because it is disabled, for example) has
-a corresponding expectation file in the `metadata` directory. For
-example a test file `html/test1.html` containing a failing test would
-have an expectation file called `html/test1.html.ini` in the
-`metadata` directory.
-
-An example of an expectation file is::
-
-  example_default_key: example_value
-
-  [filename.html]
-    [subtest1]
-      expected: FAIL
-
-    [subtest2]
-      expected:
-        if platform == 'win': TIMEOUT
-        if platform == 'osx': ERROR
-        FAIL
-
-    [subtest3]
-      expected: [PASS, TIMEOUT]
-
-  [filename.html?query=something]
-    disabled: bug12345
-
-The file consists of two elements, key-value pairs and
-sections.
-
-Sections are delimited by headings enclosed in square brackets. Any
-closing square bracket in the heading itself my be escaped with a
-backslash. Each section may then contain any number of key-value pairs
-followed by any number of subsections. So that it is clear which data
-belongs to each section without the use of end-section markers, the
-data for each section (i.e. the key-value pairs and subsections) must
-be indented using spaces. Indentation need only be consistent, but
-using two spaces per level is recommended.
-
-In a test expectation file, each resource provided by the file has a
-single section, with the section heading being the part after the last
-`/` in the test url. Tests that have subsections may have subsections
-for those subtests in which the heading is the name of the subtest.
-
-Simple key-value pairs are of the form::
-
-  key: value
-
-Note that unlike ini files, only `:` is a valid separator; `=` will
-not work as expected. Key-value pairs may also have conditional
-values of the form::
-
-  key:
-    if condition1: value1
-    if condition2: value2
-    default
-
-In this case each conditional is evaluated in turn and the value is
-that on the right hand side of the first matching conditional. In the
-case that no condition matches, the unconditional default is used. If
-no condition matches and no default is provided it is equivalent to
-the key not being present. Conditionals use a simple python-like expression
-language e.g.::
-
-  if debug and (platform == "linux" or platform == "osx"): FAIL
-
-For test expectations the available variables are those in the
-`run_info` which for desktop are `version`, `os`, `bits`, `processor`,
-`debug` and `product`.
-
-Key-value pairs specified at the top level of the file before any
-sections are special as they provide defaults for the rest of the file
-e.g.::
-
-  key1: value1
-
-  [section 1]
-    key2: value2
-
-  [section 2]
-    key1: value3
-
-In this case, inside section 1, `key1` would have the value `value1`
-and `key2` the value `value2` whereas in section 2 `key1` would have
-the value `value3` and `key2` would be undefined.
-
-The web-platform-test harness knows about several keys:
-
-`expected`
-  Must evaluate to a possible test status indicating the expected
-  result of the test. The implicit default is PASS or OK when the
-  field isn't present. When `expected` is a list, the first status
-  is the primary expected status and the trailing statuses listed are
-  expected intermittent statuses.
-
-`disabled`
-  Any value indicates that the test is disabled.
-
-`reftype`
-  The type of comparison for reftests; either `==` or `!=`.
-
-`refurl`
-  The reference url for reftests.
+   docs/usage
+   docs/expectation
+   docs/design
+   docs/internals
 
 .. _`web-platform-tests testsuite`: https://github.com/web-platform-tests/wpt
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/base.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/base.py
index d17229da..8607f77 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/base.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/base.py
@@ -88,21 +88,21 @@
 
 
 class Browser(object):
+    """Abstract class serving as the basis for Browser implementations.
+
+    The Browser is used in the TestRunnerManager to start and stop the browser
+    process, and to check the state of that process. This class also acts as a
+    context manager, enabling it to do browser-specific setup at the start of
+    the testrun and cleanup after the run is complete.
+
+    :param logger: Structured logger to use for output.
+    """
     __metaclass__ = ABCMeta
 
     process_cls = None
     init_timeout = 30
 
     def __init__(self, logger):
-        """Abstract class serving as the basis for Browser implementations.
-
-        The Browser is used in the TestRunnerManager to start and stop the browser
-        process, and to check the state of that process. This class also acts as a
-        context manager, enabling it to do browser-specific setup at the start of
-        the testrun and cleanup after the run is complete.
-
-        :param logger: Structured logger to use for output.
-        """
         self.logger = logger
 
     def __enter__(self):
@@ -182,14 +182,14 @@
 
 
 class ExecutorBrowser(object):
-    def __init__(self, **kwargs):
-        """View of the Browser used by the Executor object.
-        This is needed because the Executor runs in a child process and
-        we can't ship Browser instances between processes on Windows.
+    """View of the Browser used by the Executor object.
+    This is needed because the Executor runs in a child process and
+    we can't ship Browser instances between processes on Windows.
 
-        Typically this will have a few product-specific properties set,
-        but in some cases it may have more elaborate methods for setting
-        up the browser from the runner process.
-        """
+    Typically this will have a few product-specific properties set,
+    but in some cases it may have more elaborate methods for setting
+    up the browser from the runner process.
+    """
+    def __init__(self, **kwargs):
         for k, v in kwargs.iteritems():
             setattr(self, k, v)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/environment.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/environment.py
index 9244092..e79ae37 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/environment.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/environment.py
@@ -50,9 +50,9 @@
 
 
 class TestEnvironment(object):
+    """Context manager that owns the test environment i.e. the http and
+    websockets servers"""
     def __init__(self, test_paths, testharness_timeout_multipler, pause_after_test, debug_info, options, ssl_config, env_extras):
-        """Context manager that owns the test environment i.e. the http and
-        websockets servers"""
         self.test_paths = test_paths
         self.server = None
         self.config_ctx = None
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py
index f581c5c..6305563 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py
@@ -129,6 +129,17 @@
 
 
 class TestExecutor(object):
+    """Abstract Base class for object that actually executes the tests in a
+    specific browser. Typically there will be a different TestExecutor
+    subclass for each test type and method of executing tests.
+
+    :param browser: ExecutorBrowser instance providing properties of the
+                    browser that will be tested.
+    :param server_config: Dictionary of wptserve server configuration of the
+                          form stored in TestEnvironment.config
+    :param timeout_multiplier: Multiplier relative to base timeout to use
+                               when setting test timeout.
+    """
     __metaclass__ = ABCMeta
 
     test_type = None
@@ -138,17 +149,6 @@
 
     def __init__(self, browser, server_config, timeout_multiplier=1,
                  debug_info=None, **kwargs):
-        """Abstract Base class for object that actually executes the tests in a
-        specific browser. Typically there will be a different TestExecutor
-        subclass for each test type and method of executing tests.
-
-        :param browser: ExecutorBrowser instance providing properties of the
-                        browser that will be tested.
-        :param server_config: Dictionary of wptserve server configuration of the
-                              form stored in TestEnvironment.config
-        :param timeout_multiplier: Multiplier relative to base timeout to use
-                                   when setting test timeout.
-        """
         self.runner = None
         self.browser = browser
         self.server_config = server_config
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testloader.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testloader.py
index 1ffdda6..fa54ca3 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testloader.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testloader.py
@@ -69,6 +69,8 @@
 
 
 class TestFilter(object):
+    """Callable that restricts the set of tests in a given manifest according
+    to initial criteria"""
     def __init__(self, test_manifests, include=None, exclude=None, manifest_path=None, explicit=False):
         if manifest_path is None or include or explicit:
             self.manifest = manifestinclude.IncludeManifest.create()
@@ -147,6 +149,7 @@
 
 
 class TestLoader(object):
+    """Loads tests according to a WPT manifest and any associated expectation files"""
     def __init__(self,
                  test_manifests,
                  test_types,
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testrunner.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testrunner.py
index 5c0c60a..c2cb5c4d 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testrunner.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testrunner.py
@@ -51,19 +51,19 @@
 
 
 class TestRunner(object):
+    """Class implementing the main loop for running tests.
+
+    This class delegates the job of actually running a test to the executor
+    that is passed in.
+
+    :param logger: Structured logger
+    :param command_queue: subprocess.Queue used to send commands to the
+                          process
+    :param result_queue: subprocess.Queue used to send results to the
+                         parent TestRunnerManager process
+    :param executor: TestExecutor object that will actually run a test.
+    """
     def __init__(self, logger, command_queue, result_queue, executor):
-        """Class implementing the main loop for running tests.
-
-        This class delegates the job of actually running a test to the executor
-        that is passed in.
-
-        :param logger: Structured logger
-        :param command_queue: subprocess.Queue used to send commands to the
-                              process
-        :param result_queue: subprocess.Queue used to send results to the
-                             parent TestRunnerManager process
-        :param executor: TestExecutor object that will actually run a test.
-        """
         self.command_queue = command_queue
         self.result_queue = result_queue
 
@@ -773,6 +773,7 @@
 
 
 class ManagerGroup(object):
+    """Main thread object that owns all the TestRunnerManager threads."""
     def __init__(self, suite_name, size, test_source_cls, test_source_kwargs,
                  browser_cls, browser_kwargs,
                  executor_cls, executor_kwargs,
@@ -782,7 +783,6 @@
                  restart_on_unexpected=True,
                  debug_info=None,
                  capture_stdio=True):
-        """Main thread object that owns all the TestRunnerManager threads."""
         self.suite_name = suite_name
         self.size = size
         self.test_source_cls = test_source_cls
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py
index 8dcdcde..88b51d0 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py
@@ -134,6 +134,8 @@
 
 
 def run_tests(config, test_paths, product, **kwargs):
+    """Set up the test environment, load the list of tests to be executed, and
+    invoke the remainder of the code to execute tests"""
     with capture.CaptureIO(logger, not kwargs["no_capture_stdio"]):
         env.do_delayed_imports(logger, test_paths)
 
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/sslutils/openssl.py b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/sslutils/openssl.py
index 3c5c1dc23..aea1c738 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/sslutils/openssl.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/sslutils/openssl.py
@@ -362,6 +362,7 @@
                     "-passin", "pass:%s" % self.password,
                     "-selfsign",
                     "-extensions", "v3_ca",
+                    "-notext",
                     "-in", req_path,
                     "-out", cert_path)
 
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt
new file mode 100644
index 0000000..af5b66f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt
@@ -0,0 +1,19 @@
+This is a testharness.js-based test.
+PASS idl_test setup
+PASS idl_test validation
+PASS WakeLock interface: existence and properties of interface object
+PASS WakeLock interface object length
+PASS WakeLock interface object name
+PASS WakeLock interface: existence and properties of interface prototype object
+PASS WakeLock interface: existence and properties of interface prototype object's "constructor" property
+PASS WakeLock interface: existence and properties of interface prototype object's @@unscopables property
+FAIL WakeLock interface: operation requestPermission(WakeLockType) assert_own_property: interface object missing static operation expected property "requestPermission" missing
+FAIL WakeLock interface: operation request(WakeLockType, WakeLockRequestOptions) assert_own_property: interface object missing static operation expected property "request" missing
+PASS WakeLock must be primary interface of navigator.wakeLock
+PASS Stringification of navigator.wakeLock
+PASS WakeLock interface: navigator.wakeLock must inherit property "requestPermission(WakeLockType)" with the proper type
+FAIL WakeLock interface: calling requestPermission(WakeLockType) on navigator.wakeLock with too few arguments must throw TypeError assert_own_property: interface object must have static operation as own property expected property "requestPermission" missing
+PASS WakeLock interface: navigator.wakeLock must inherit property "request(WakeLockType, WakeLockRequestOptions)" with the proper type
+FAIL WakeLock interface: calling request(WakeLockType, WakeLockRequestOptions) on navigator.wakeLock with too few arguments must throw TypeError assert_own_property: interface object must have static operation as own property expected property "request" missing
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.js b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.js
index 2ad9980..31d20aed 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.js
@@ -10,7 +10,7 @@
   ['dom', 'html', 'permissions'],
   idl_array => {
     idl_array.add_objects({
-      WakeLock: []
+      WakeLock: ['navigator.wakeLock'],
     });
   }
 );
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt
new file mode 100644
index 0000000..6c96a32
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt
@@ -0,0 +1,18 @@
+This is a testharness.js-based test.
+PASS idl_test setup
+PASS idl_test validation
+PASS WakeLock interface: existence and properties of interface object
+PASS WakeLock interface object length
+PASS WakeLock interface object name
+PASS WakeLock interface: existence and properties of interface prototype object
+PASS WakeLock interface: existence and properties of interface prototype object's "constructor" property
+PASS WakeLock interface: existence and properties of interface prototype object's @@unscopables property
+PASS WakeLock interface: member requestPermission
+FAIL WakeLock interface: operation request(WakeLockType, WakeLockRequestOptions) assert_own_property: interface object missing static operation expected property "request" missing
+PASS WakeLock must be primary interface of navigator.wakeLock
+PASS Stringification of navigator.wakeLock
+PASS WakeLock interface: navigator.wakeLock must not have property "requestPermission"
+PASS WakeLock interface: navigator.wakeLock must inherit property "request(WakeLockType, WakeLockRequestOptions)" with the proper type
+FAIL WakeLock interface: calling request(WakeLockType, WakeLockRequestOptions) on navigator.wakeLock with too few arguments must throw TypeError assert_own_property: interface object must have static operation as own property expected property "request" missing
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-abortsignal.https.any.js b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-abortsignal.https.any.js
deleted file mode 100644
index 671852f..0000000
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-abortsignal.https.any.js
+++ /dev/null
@@ -1,43 +0,0 @@
-// META: title=WakeLock.request() AbortSignal Test
-
-'use strict';
-
-promise_test(async t => {
-  const invalidSignals = [
-    "string",
-    123,
-    {},
-    true,
-    Symbol(),
-    () => {},
-    self
-  ];
-
-  for (let signal of invalidSignals) {
-    await promise_rejects(t, new TypeError(), WakeLock.request('system', { signal: signal }));
-  }
-}, "'TypeError' is thrown when the signal option is not an AbortSignal");
-
-promise_test(t => {
-  const abortController = new AbortController();
-  const abortSignal = abortController.signal;
-  abortController.abort();
-  assert_true(abortSignal.aborted);
-
-  return promise_rejects(t, "AbortError", WakeLock.request('system', { signal: abortSignal }));
-}, "A WakeLock request with an AbortSignal whose abort flag is set always aborts");
-
-promise_test(async t => {
-  const abortController = new AbortController();
-  const abortSignal = abortController.signal;
-  abortController.abort();
-  assert_true(abortSignal.aborted);
-
-  const lock1 = WakeLock.request('system', { signal: abortSignal });
-  const lock2 = WakeLock.request('system', { signal: abortSignal });
-  const lock3 = WakeLock.request('system', { signal: abortSignal });
-
-  await promise_rejects(t, "AbortError", lock1);
-  await promise_rejects(t, "AbortError", lock2);
-  await promise_rejects(t, "AbortError", lock3);
-}, "The same AbortSignal can be used to cause multiple wake locks to abort");
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-active-document.https.window.js b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-active-document.https.window.js
index f0f1e38..ad6250e 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-active-document.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-active-document.https.window.js
@@ -3,8 +3,8 @@
     iframe.addEventListener(
       "load",
       () => {
-        const { WakeLock } = iframe.contentWindow;
-        resolve(WakeLock);
+        const { wakeLock } = iframe.contentWindow.navigator;
+        resolve(wakeLock);
       },
       { once: true }
     );
@@ -35,7 +35,7 @@
   );
   // We are done, so clean up.
   iframe.remove();
-}, "WakeLock.request() aborts if the document is not active.");
+}, "navigator.wakeLock.request() aborts if the document is not active.");
 
 promise_test(async t => {
   // We nest two iframes and wait for them to load.
@@ -78,4 +78,4 @@
   );
   // We are done, so clean up.
   outerIframe.remove();
-}, "WakeLock.request() aborts if the document is active, but not fully active.");
+}, "navigator.wakeLock.request() aborts if the document is active, but not fully active.");
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html
index 0d451c9..07eeb36 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html
@@ -12,12 +12,12 @@
     "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src;
 
   promise_test(t => {
-    return promise_rejects(t, "NotAllowedError", WakeLock.request("screen"));
+    return promise_rejects(t, "NotAllowedError", navigator.wakeLock.request("screen"));
   }, 'Feature-Policy header {"wake-lock" : []} disallows the top-level document.');
 
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       same_origin_src,
       expect_feature_unavailable_default
@@ -26,7 +26,7 @@
 
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       cross_origin_src,
       expect_feature_unavailable_default
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden-manual.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden-manual.https.html
index d7c1248..babd629 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden-manual.https.html
@@ -8,30 +8,20 @@
 <script>
 
 promise_test(async t => {
-  const controller = new AbortController();
-  const screenWakeLock = WakeLock.request('screen', { signal: controller.signal });
-  const systemWakeLock = WakeLock.request('system', { signal: controller.signal });
-  const systemWakeLockPromise = new Promise((resolve, reject) => {
-    systemWakeLock.catch(error => {
-      assert_equals("AbortError", error.name, "systemWakeLock must have been aborted");
-      assert_false(document.hidden, "systemWakeLock must have been aborted after the page is visible again");
-      resolve();
-    });
-  });
+  const screenWakeLock = await navigator.wakeLock.request('screen');
+  const screenWakeLockReleased =
+      new EventWatcher(t, screenWakeLock, "release").wait_for("release");
 
   const eventWatcher = new EventWatcher(t, document, "visibilitychange");
   await eventWatcher.wait_for("visibilitychange");
   assert_true(document.hidden, "document is hidden after the visibilitychange event");
-  await promise_rejects(t, "AbortError", screenWakeLock, "existing screen locks are aborted");
-  await promise_rejects(t, "NotAllowedError", WakeLock.request('screen'),
+  await screenWakeLockReleased;
+  await promise_rejects(t, "NotAllowedError", navigator.wakeLock.request('screen'),
       "new screen locks are not allowed when the page is not visible");
 
   await eventWatcher.wait_for("visibilitychange");
   assert_false(document.hidden, "document is no longer hidden after the visibilitychange event");
-  controller.abort();
-
-  return systemWakeLockPromise;
-}, "Test screen locks respect page visibility changes and system locks are unchanged");
+}, "Test screen locks respect page visibility changes");
 
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub-expected.txt
new file mode 100644
index 0000000..5c21953
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL Feature-Policy allow="wake-lock" allows same-origin relocation assert_true: navigator.wakeLock.request("screen") expected true got false
+PASS Feature-Policy allow="wake-lock" disallows cross-origin relocation
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html
index b27fbef..18a2d7c 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -12,9 +12,13 @@
   const cross_origin_src =
     base_src + "https://{{domains[www]}}:{{ports[https][0]}}" + relative_path;
 
+  // request() checks for both Feature Policy and permission, so the tests below
+  // can have inconsistent results due to the default permission a wake lock
+  // request might return.
+
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       same_origin_src,
       expect_feature_available_default,
@@ -24,7 +28,7 @@
 
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       cross_origin_src,
       expect_feature_unavailable_default,
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub-expected.txt
new file mode 100644
index 0000000..265fa6d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL Feature policy "wake-lock" can be enabled in same-origin iframe using allow="wake-lock" attribute assert_true: navigator.wakeLock.request("screen") expected true got false
+FAIL Feature policy "wake-lock" can be enabled in cross-origin iframe using allow="wake-lock" attribute assert_true: navigator.wakeLock.request("screen") expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html
index 3897df6..5587a85 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html
@@ -13,7 +13,7 @@
 
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       same_origin_src,
       expect_feature_available_default,
@@ -23,7 +23,7 @@
 
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       cross_origin_src,
       expect_feature_available_default,
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub-expected.txt
new file mode 100644
index 0000000..a0108cf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL Feature-Policy header {"wake-lock" : ["*"]} allows the top-level document. promise_test: Unhandled rejection with value: object "NotAllowedError: Wake Lock permission request denied"
+FAIL Feature-Policy header {"wake-lock" : ["*"]} allows same-origin iframes. assert_true: navigator.wakeLock.request("screen") expected true got false
+FAIL Feature-Policy header {"wake-lock" : ["*"]} allows cross-origin iframes. assert_true: navigator.wakeLock.request("screen") expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html
index f4aaa73..8573f7a 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html
@@ -11,16 +11,17 @@
   const cross_origin_src =
     "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src;
 
+  // request() checks for both Feature Policy and permission, so the tests below
+  // can have inconsistent results due to the default permission a wake lock
+  // request might return.
+
   promise_test(t => {
-    const controller = new AbortController();
-    const lock = WakeLock.request("screen", { signal: controller.signal });
-    controller.abort();
-    return promise_rejects(t, "AbortError", lock);
+    return navigator.wakeLock.request('screen').then(lock => lock.release());
   }, 'Feature-Policy header {"wake-lock" : ["*"]} allows the top-level document.');
 
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       same_origin_src,
       expect_feature_available_default
@@ -29,7 +30,7 @@
 
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       cross_origin_src,
       expect_feature_available_default
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub-expected.txt
new file mode 100644
index 0000000..969fb83a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL Feature-Policy header wake-lock "self" allows the top-level document. promise_test: Unhandled rejection with value: object "NotAllowedError: Wake Lock permission request denied"
+FAIL Feature-Policy header wake-lock "self" allows same-origin iframes. assert_true: navigator.wakeLock.request("screen") expected true got false
+PASS Feature-Policy header wake-lock "self" disallows cross-origin iframes.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html
index 19bf59d..3082170 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html
@@ -12,16 +12,17 @@
   const cross_origin_src =
     "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src;
 
+  // request() checks for both Feature Policy and permission, so the tests below
+  // can have inconsistent results due to the default permission a wake lock
+  // request might return.
+
   promise_test(t => {
-    const controller = new AbortController();
-    const lock = WakeLock.request("screen", { signal: controller.signal });
-    controller.abort();
-    return promise_rejects(t, "AbortError", lock);
+    return navigator.wakeLock.request('screen').then(lock => lock.release());
   }, 'Feature-Policy header wake-lock "self" allows the top-level document.');
 
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       same_origin_src,
       expect_feature_available_default
@@ -30,7 +31,7 @@
 
   async_test(t => {
     test_feature_availability(
-      'WakeLock.request("screen")',
+      'navigator.wakeLock.request("screen")',
       t,
       cross_origin_src,
       expect_feature_unavailable_default
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker.js b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker.js
index 28e3394..5450fe5b 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker.js
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker.js
@@ -2,7 +2,7 @@
 importScripts("/resources/testharness.js");
 
 promise_test(t => {
-  return promise_rejects(t, "NotAllowedError", WakeLock.request('screen'));
+  return promise_rejects(t, "NotAllowedError", navigator.wakeLock.request('screen'));
 }, "Screen wake lock should not be allowed in dedicated worker");
 
 done();
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.js b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.js
index cc37c76..62f59a7 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.js
@@ -1,7 +1,7 @@
-//META: title=WakeLock.request() with invalid type
+//META: title=navigator.wakeLock.request() with invalid type
 
 promise_test(async t => {
-  await promise_rejects(t, new TypeError(), WakeLock.request());
+  return promise_rejects(t, new TypeError(), navigator.wakeLock.request());
 }, "'TypeError' is thrown when set an empty wake lock type");
 
 promise_test(t => {
@@ -14,6 +14,6 @@
     true
   ];
   return Promise.all(invalidTypes.map(invalidType => {
-    return promise_rejects(t, new TypeError(), WakeLock.request(invalidType));
+    return promise_rejects(t, new TypeError(), navigator.wakeLock.request(invalidType));
   }));
 }, "'TypeError' is thrown when set an invalid wake lock type");
diff --git a/third_party/blink/web_tests/fast/borders/border-radius-with-composited-child.html b/third_party/blink/web_tests/fast/borders/border-radius-with-composited-child.html
index 1e8782d..59012765 100644
--- a/third_party/blink/web_tests/fast/borders/border-radius-with-composited-child.html
+++ b/third_party/blink/web_tests/fast/borders/border-radius-with-composited-child.html
@@ -2,5 +2,5 @@
 <p>Below there should be a solid green circle with a black border and no red.</p>
 <br>
 <div style="position:relative; z-index:1; overflow:hidden; margin-top:100px; width:200px; height:200px; border-radius:50%; border:10px solid black; background:red;">
-    <div style="transform:translateZ(0); width:300px; height:300px; margin-left:-50px; margin-top:-50px; background:green;"></div>
+    <div style="will-change: transform; width:300px; height:300px; margin-left:-50px; margin-top:-50px; background:green;"></div>
 </div>
diff --git a/third_party/blink/web_tests/fast/borders/overflow-hidden-border-radius-force-backing-store.html b/third_party/blink/web_tests/fast/borders/overflow-hidden-border-radius-force-backing-store.html
index 1125ba0..37872c1 100644
--- a/third_party/blink/web_tests/fast/borders/overflow-hidden-border-radius-force-backing-store.html
+++ b/third_party/blink/web_tests/fast/borders/overflow-hidden-border-radius-force-backing-store.html
@@ -22,7 +22,7 @@
 
 #content {
     height: 1000px;
-    transform: translatez(0);
+    will-change: transform;
     background-image: linear-gradient(to bottom,red,orange,yellow, green, blue,indigo,violet);
 }
 
diff --git a/third_party/blink/web_tests/fast/clip/overflow-border-radius-composited-parent.html b/third_party/blink/web_tests/fast/clip/overflow-border-radius-composited-parent.html
index 5adb7116..4c6eb91 100644
--- a/third_party/blink/web_tests/fast/clip/overflow-border-radius-composited-parent.html
+++ b/third_party/blink/web_tests/fast/clip/overflow-border-radius-composited-parent.html
@@ -9,14 +9,15 @@
     height: 100px;
     margin: 10px;
     display: inline-block;
-    transform: translateZ(0);
+    will-change: transform;
 }
 .inner {
     background: #808080;
     width: 100%;
     height: 100%;
     color: #FFFFFF;
-    transform: rotate(45deg) translateZ(0);
+    transform: rotate(45deg);
+    will-change: transform;
 }
 </style>
 </head>
diff --git a/third_party/blink/web_tests/fast/clip/overflow-border-radius-composited.html b/third_party/blink/web_tests/fast/clip/overflow-border-radius-composited.html
index 310657c..1cc9c4c9 100644
--- a/third_party/blink/web_tests/fast/clip/overflow-border-radius-composited.html
+++ b/third_party/blink/web_tests/fast/clip/overflow-border-radius-composited.html
@@ -15,7 +15,8 @@
     width: 100%;
     height: 100%;
     color: #FFFFFF;
-    transform: rotate(45deg) translateZ(0);
+    transform: rotate(45deg);
+    will-change: transform;
 }
 </style>
 </head>
diff --git a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-many.html b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-many.html
index 3c5d67b..84595059 100644
--- a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-many.html
+++ b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-many.html
@@ -4,7 +4,7 @@
 <link rel="stylesheet" href="resources/compositor-touch-hit-rects.css">
 <style>
 #layer {
-  transform: translateZ(0);
+  will-change: transform;
 }
 #manychildren {
   height: 10px;
diff --git a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html
index 7ecf57b..0ad09026c 100644
--- a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html
+++ b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html
@@ -70,7 +70,7 @@
   </div>
   <div id="scroll6" class="scroll" style="margin-bottom: 10px">
     <div style='height: 10px;'></div>
-    <div id="compositedLayer" style="transform: translateZ(0)">
+    <div id="compositedLayer" style="will-change: transform;">
       <div style='height: 10px;'></div>
       <div class="testcase" id="divInsideCompositedLayer">div in composited</div>
     </div>
diff --git a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-squashing.html b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-squashing.html
index 4d2bf8e..e14e7e0 100644
--- a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-squashing.html
+++ b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-squashing.html
@@ -4,7 +4,7 @@
 <link rel="stylesheet" href="resources/compositor-touch-hit-rects.css">
 <style>
 .composited {
-  transform: translatez(0);
+  will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-with-negative-child.html b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-with-negative-child.html
index b97255a..5ae7f8c 100644
--- a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-with-negative-child.html
+++ b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-with-negative-child.html
@@ -8,7 +8,8 @@
     width: 100px;
     height: 10px;
     border: 1px dotted blue;
-    transform: translateX(calc(120%)) translateZ(0);
+    transform: translateX(calc(120%));
+    will-change: transform;
     clear: both;
 }
 #negativeOffsetChild {
diff --git a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects.html b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects.html
index 2ffcbaa..98215c8 100644
--- a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects.html
+++ b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects.html
@@ -42,7 +42,8 @@
     width: 100px;
     height: 10px;
     border: 1px dotted blue;
-    transform: translateX(calc(120%)) translateZ(0);
+    transform: translateX(calc(120%));
+    will-change: transform;
     clear: both;
 }
 #negativeOffsetChild {
diff --git a/third_party/blink/web_tests/fast/events/touch/touch-rect-crash-on-unpromote-layer.html b/third_party/blink/web_tests/fast/events/touch/touch-rect-crash-on-unpromote-layer.html
index 77d1b35..1ce7645 100644
--- a/third_party/blink/web_tests/fast/events/touch/touch-rect-crash-on-unpromote-layer.html
+++ b/third_party/blink/web_tests/fast/events/touch/touch-rect-crash-on-unpromote-layer.html
@@ -11,7 +11,7 @@
   overflow: hidden;
 }
 .composited {
-  transform: translate3d(0, 0, 0);
+  will-change: transform;
 }
 </style>
 </head>
diff --git a/third_party/blink/web_tests/fast/layers/scroll-with-transform-composited-layer.html b/third_party/blink/web_tests/fast/layers/scroll-with-transform-composited-layer.html
index 69a6856..1630b3b 100644
--- a/third_party/blink/web_tests/fast/layers/scroll-with-transform-composited-layer.html
+++ b/third_party/blink/web_tests/fast/layers/scroll-with-transform-composited-layer.html
@@ -9,7 +9,7 @@
     div.relative { position: relative }
     div.composited
     {
-        transform: translateZ(0);
+        will-change: transform;
     }
     div.translated
     {
diff --git a/third_party/blink/web_tests/fast/multicol/composited-layer-multiple-fragments-translated.html b/third_party/blink/web_tests/fast/multicol/composited-layer-multiple-fragments-translated.html
index d6b85d2..2b5c215 100644
--- a/third_party/blink/web_tests/fast/multicol/composited-layer-multiple-fragments-translated.html
+++ b/third_party/blink/web_tests/fast/multicol/composited-layer-multiple-fragments-translated.html
@@ -13,7 +13,7 @@
     height: 20px;
     background: red;
 }
-.layer { transform: translateZ(0) translateY(20px); }
+.layer { transform: translateY(20px); will-change: transform; }
 .layer .square { background: green; }
 </style>
 
diff --git a/third_party/blink/web_tests/fast/multicol/composited-layer-multiple-fragments.html b/third_party/blink/web_tests/fast/multicol/composited-layer-multiple-fragments.html
index 7ae4c62..a97bd4c 100644
--- a/third_party/blink/web_tests/fast/multicol/composited-layer-multiple-fragments.html
+++ b/third_party/blink/web_tests/fast/multicol/composited-layer-multiple-fragments.html
@@ -13,7 +13,7 @@
     height: 20px;
     background: green;
 }
-.layer { transform: translateZ(0); }
+.layer { will-change: transform; }
 </style>
 
 <p>If no compositing were present, there should be two green squares below. Since some elements are composited, and therefore not fragmented, the output is different.</p>
diff --git a/third_party/blink/web_tests/fast/multicol/composited-layer-nested.html b/third_party/blink/web_tests/fast/multicol/composited-layer-nested.html
index 87e7447..e35ec54 100644
--- a/third_party/blink/web_tests/fast/multicol/composited-layer-nested.html
+++ b/third_party/blink/web_tests/fast/multicol/composited-layer-nested.html
@@ -14,7 +14,7 @@
     background: green;
 }
 
-.layer { transform: translateZ(0); }
+.layer { will-change: transform; }
 
 </style>
 <p>If no compositing were present, there should be two green squares below. Since some elements are composited, and therefore not fragmented, the output is different.</p>
diff --git a/third_party/blink/web_tests/fast/multicol/composited-layer.html b/third_party/blink/web_tests/fast/multicol/composited-layer.html
index 5b5c8ec..dffb9c89 100644
--- a/third_party/blink/web_tests/fast/multicol/composited-layer.html
+++ b/third_party/blink/web_tests/fast/multicol/composited-layer.html
@@ -7,7 +7,7 @@
     column-gap: 0;
     width: 200px;
     height: 100px;
-    transform: translateZ(0);
+    will-change: transform;
 }
 
 .filler {
diff --git a/third_party/blink/web_tests/fast/multicol/composited-opacity-2nd-and-3rd-column.html b/third_party/blink/web_tests/fast/multicol/composited-opacity-2nd-and-3rd-column.html
index fd8df2b..876c6d18 100644
--- a/third_party/blink/web_tests/fast/multicol/composited-opacity-2nd-and-3rd-column.html
+++ b/third_party/blink/web_tests/fast/multicol/composited-opacity-2nd-and-3rd-column.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <p>The word 'PASS' should be seen <em>twice</em> below. The second PASS is not overlapping the yellow because it is composited with the first one, and hence not fragmented.</p>
 <div style="-webkit-columns:3; -webkit-column-gap:1em; column-fill:auto; width:17em; height:13em; line-height:2em; orphans:1; widows:1;">
-    <div style="transform:translateZ(0); position:absolute; left:0; right:0; height:8em; background:yellow;"></div>
+    <div style="will-change: transform; position:absolute; left:0; right:0; height:8em; background:yellow;"></div>
     <br>
     <br>
     <br>
diff --git a/third_party/blink/web_tests/fast/multicol/composited-with-overflow-in-next-column.html b/third_party/blink/web_tests/fast/multicol/composited-with-overflow-in-next-column.html
index 707305b..f94b459 100644
--- a/third_party/blink/web_tests/fast/multicol/composited-with-overflow-in-next-column.html
+++ b/third_party/blink/web_tests/fast/multicol/composited-with-overflow-in-next-column.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <p>The word 'PASS' should be seen below, in the third column.</p>
 <div style="-webkit-columns:3; column-fill:auto; -webkit-column-rule:1px solid; height:9em; line-height:2em; orphans:1; widows:1;">
-    <div style="position:absolute; transform:translateZ(0); margin-top:3em; left:0; right:0; height:1em; border:1px dotted;"></div>
+    <div style="position:absolute; will-change: transform; margin-top:3em; left:0; right:0; height:1em; border:1px dotted;"></div>
     <br>
     <br>
     <br>
diff --git a/third_party/blink/web_tests/fast/scrolling/scroll-chaining-from-position-fixed.html b/third_party/blink/web_tests/fast/scrolling/scroll-chaining-from-position-fixed.html
index 473e42c..48f4d077e 100644
--- a/third_party/blink/web_tests/fast/scrolling/scroll-chaining-from-position-fixed.html
+++ b/third_party/blink/web_tests/fast/scrolling/scroll-chaining-from-position-fixed.html
@@ -88,7 +88,7 @@
 </div>
 
 <div id="fixedScrollerInFixedTransform" class="box"
-     style="right: 20px; bottom: 20px; transform: translateZ(0)">
+     style="right: 20px; bottom: 20px; will-change: transform;">
   position: fixed scroller child in position: fixed non-scroller
   <div class="scrolls subbox" style="position: fixed; top: 40px">
     <div class="spacer"></div>
diff --git a/third_party/blink/web_tests/fast/sub-pixel/clip-sub-pixel-composited-layer.html b/third_party/blink/web_tests/fast/sub-pixel/clip-sub-pixel-composited-layer.html
index 0ace54c..b17c41b 100644
--- a/third_party/blink/web_tests/fast/sub-pixel/clip-sub-pixel-composited-layer.html
+++ b/third_party/blink/web_tests/fast/sub-pixel/clip-sub-pixel-composited-layer.html
@@ -21,7 +21,7 @@
 	position: absolute;
 }
 .composited {
-	transform: translateZ(0);
+	will-change: transform;
 	z-index: 1;
 }
 .test {
diff --git a/third_party/blink/web_tests/fast/sub-pixel/negative-composited-offset.html b/third_party/blink/web_tests/fast/sub-pixel/negative-composited-offset.html
index c5a9dc88..bbbdb55 100644
--- a/third_party/blink/web_tests/fast/sub-pixel/negative-composited-offset.html
+++ b/third_party/blink/web_tests/fast/sub-pixel/negative-composited-offset.html
@@ -10,7 +10,7 @@
   background-color: red;
 }
 .composited {
-  transform: translateZ(0px);
+  will-change: transform;
   background-color: green;
 }
 </style>
diff --git a/third_party/blink/web_tests/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html b/third_party/blink/web_tests/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html
index 92deae9..af2ea18 100644
--- a/third_party/blink/web_tests/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html
+++ b/third_party/blink/web_tests/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html
@@ -5,7 +5,7 @@
     position: relative;
     width: 100px;
     height: 50px;
-    transform: translateZ(0);
+    will-change: transform;
 }
 #test {
     position: absolute;
diff --git a/third_party/blink/web_tests/fast/sub-pixel/sub-pixel-composited-layers.html b/third_party/blink/web_tests/fast/sub-pixel/sub-pixel-composited-layers.html
index 821e7eb..a74aa28 100644
--- a/third_party/blink/web_tests/fast/sub-pixel/sub-pixel-composited-layers.html
+++ b/third_party/blink/web_tests/fast/sub-pixel/sub-pixel-composited-layers.html
@@ -6,7 +6,7 @@
         margin: 5px;
     }
     #test.composite > .container {
-        transform: translateZ(0);
+        will-change: transform;
     }
     .container {
         position: absolute;
diff --git a/third_party/blink/web_tests/fast/sub-pixel/transformed-iframe-copy-on-scroll.html b/third_party/blink/web_tests/fast/sub-pixel/transformed-iframe-copy-on-scroll.html
index f032d26..5dbd567 100644
--- a/third_party/blink/web_tests/fast/sub-pixel/transformed-iframe-copy-on-scroll.html
+++ b/third_party/blink/web_tests/fast/sub-pixel/transformed-iframe-copy-on-scroll.html
@@ -14,6 +14,7 @@
 }
 .transform {
   transform: rotate3d(0, 0, 1, 45deg);
+  will-change: transform;
 }
 </style>
 <script src="../../resources/run-after-layout-and-paint.js" type="text/javascript"></script>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/clip-child-by-non-stacking-ancestor-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/clip-child-by-non-stacking-ancestor-expected.txt
index 92ef8129..7498575 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/clip-child-by-non-stacking-ancestor-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/clip-child-by-non-stacking-ancestor-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV class='container'",
-      "position": [8, 8],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0"
+      "backgroundColor": "#C0C0C0",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/background-clip-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/background-clip-expected.txt
index 0417772..9174fb3 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/background-clip-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/background-clip-expected.txt
@@ -8,22 +8,51 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box composited'",
-      "position": [13, 8],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box composited padding-clip'",
-      "position": [13, 113],
       "bounds": [100, 100],
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box composited content-clip'",
-      "position": [13, 218],
       "bounds": [100, 100],
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 3
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [13, 8, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [13, 113, 0, 1]
+      ]
+    },
+    {
+      "id": 3,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [13, 218, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/background-color-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/background-color-expected.txt
index 6041fc3..61681f9 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/background-color-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/background-color-expected.txt
@@ -8,16 +8,36 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box translucent composited'",
-      "position": [8, 108],
       "bounds": [100, 100],
-      "backgroundColor": "#00FF0080"
+      "backgroundColor": "#00FF0080",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box opaque composited'",
-      "position": [8, 208],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 108, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 208, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/body-background-painted-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/body-background-painted-expected.txt
index 60b76d0..5594101 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/body-background-painted-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/body-background-painted-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='underbody'",
-      "position": [8, 8],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow HTML",
@@ -20,6 +20,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#0000FF"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/body-background-skipped-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/body-background-skipped-expected.txt
index 4363bedf..71e9ce5 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/body-background-skipped-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/body-background-skipped-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='underbody'",
-      "position": [8, 8],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/hidden-with-visible-text-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/hidden-with-visible-text-expected.txt
index cc93dd66..620ee38 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/hidden-with-visible-text-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/hidden-with-visible-text-expected.txt
@@ -9,9 +9,20 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='caption'",
-      "position": [8, 13],
       "bounds": [50, 19],
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 13, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
index 9606ef8..f4af425 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
@@ -8,9 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box'",
-      "position": [28, 20],
+      "position": [-30, -30],
       "bounds": [160, 160],
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [58, 50, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt
index 7abd315..906235c9 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt
@@ -8,9 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited'",
-      "position": [80, 80],
+      "position": [-25, -25],
       "bounds": [125, 125],
-      "backgroundColor": "#000000"
+      "backgroundColor": "#000000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software'",
@@ -18,6 +19,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#008000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [105, 105, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
index 18c867f..34f1e05 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
@@ -8,15 +8,27 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-parent'",
-      "position": [205, 205],
+      "position": [-125, -125],
       "bounds": [225, 225],
-      "backgroundColor": "#000000"
+      "backgroundColor": "#000000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-parent'",
       "bounds": [225, 225],
       "backgroundColor": "#008000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [330, 330, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-shadow-overlaps-hw-layer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-shadow-overlaps-hw-layer-expected.txt
index e48f12f..bc2b1ed 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-shadow-overlaps-hw-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-shadow-overlaps-hw-layer-expected.txt
@@ -8,16 +8,27 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited'",
-      "position": [105, 105],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#000000"
+      "backgroundColor": "#000000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software'",
       "bounds": [125, 125],
       "backgroundColor": "#008000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [105, 105, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-shadow-overlaps-hw-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-shadow-overlaps-hw-shadow-expected.txt
index 9427011..a0b193b45 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-shadow-overlaps-hw-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/filters/sw-shadow-overlaps-hw-shadow-expected.txt
@@ -8,15 +8,27 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited'",
-      "position": [105, 105],
+      "position": [-25, -25],
       "bounds": [125, 125],
-      "backgroundColor": "#000000"
+      "backgroundColor": "#000000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software'",
       "bounds": [125, 125],
       "backgroundColor": "#008000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [130, 130, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/fixed-position-changed-to-absolute-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/fixed-position-changed-to-absolute-expected.txt
index 5ca59ce..32fc382 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/fixed-position-changed-to-absolute-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/fixed-position-changed-to-absolute-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited'",
-      "position": [8, 13],
       "bounds": [150, 150],
       "contentsOpaque": true,
-      "backgroundColor": "#D9CCA7"
+      "backgroundColor": "#D9CCA7",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='layer-A'",
@@ -19,6 +19,17 @@
       "bounds": [226, 180],
       "backgroundColor": "#6AA6A6"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 13, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-composited-descendant-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-composited-descendant-expected.txt
index cc7bd14..dd8a8e7 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-composited-descendant-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-composited-descendant-expected.txt
@@ -14,17 +14,39 @@
     },
     {
       "name": "LayoutImage (positioned) IMG",
-      "position": [10, 260],
+      "position": [10, 10],
       "bounds": [50, 50],
       "contentsOpaque": true,
-      "backgroundColor": "#000000"
+      "backgroundColor": "#000000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='composited inner box'",
-      "position": [500, 370],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, 250, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [500, 120, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt
index fb0d979..49d3d06 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt
@@ -14,10 +14,22 @@
     },
     {
       "name": "LayoutImage (positioned) IMG",
-      "position": [10, 260],
+      "position": [10, 10],
       "bounds": [50, 50],
       "contentsOpaque": true,
-      "backgroundColor": "#000000"
+      "backgroundColor": "#000000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, 250, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex-expected.txt
index aa887a7..6469a16 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex-expected.txt
@@ -13,15 +13,26 @@
     },
     {
       "name": "LayoutImage (positioned) IMG",
-      "position": [0, 250],
       "bounds": [150, 150],
-      "backgroundColor": "#000000"
+      "backgroundColor": "#000000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='indicator box'",
       "bounds": [100, 350],
       "backgroundColor": "#008000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, 250, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/composited-in-columns-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/composited-in-columns-expected.txt
index aa67e3f3..cfafce5a 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/composited-in-columns-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/composited-in-columns-expected.txt
@@ -11,29 +11,51 @@
     },
     {
       "name": "LayoutBlockFlow DIV class='composited block'",
-      "position": [14, 164],
+      "position": [-5, -5],
       "bounds": [210, 60],
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutBlockFlow DIV class='composited box'",
-      "position": [19, 169],
       "bounds": [50, 50],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
     },
     {
       "name": "LayoutBlockFlow DIV class='composited block'",
-      "position": [272, 89],
+      "position": [-5, -5],
       "bounds": [210, 60],
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 2
     },
     {
       "name": "LayoutBlockFlow DIV class='composited box'",
-      "position": [277, 94],
       "bounds": [50, 50],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [19, 169, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [277, 94, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/flipped-writing-mode-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/flipped-writing-mode-expected.txt
index 098ea2a..0a6151d 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/flipped-writing-mode-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/flipped-writing-mode-expected.txt
@@ -8,16 +8,38 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV class='composited flipped'",
-      "position": [18, 10],
       "bounds": [250, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0"
+      "backgroundColor": "#C0C0C0",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow DIV class='composited box'",
-      "position": [53, 20],
+      "position": [-95, 0],
       "bounds": [195, 100],
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [130, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/become-overlapped-iframe-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/become-overlapped-iframe-expected.txt
index 3a62eb7b..f5512db0 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/become-overlapped-iframe-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/become-overlapped-iframe-expected.txt
@@ -21,11 +21,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 1
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow HTML",
@@ -43,6 +42,16 @@
         [0, 0, 1, 0],
         [73, 73, 0, 1]
       ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/composited-parent-iframe-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/composited-parent-iframe-expected.txt
index 963ce32..4a31da3 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/composited-parent-iframe-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/composited-parent-iframe-expected.txt
@@ -27,11 +27,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 2
+      "transform": 3
     }
   ],
   "transforms": [
@@ -53,6 +52,16 @@
         [0, 0, 1, 0],
         [15, 15, 0, 1]
       ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe-delayed-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe-delayed-expected.txt
index 9751cf3a..e9bd2c0 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe-delayed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe-delayed-expected.txt
@@ -23,18 +23,17 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 1
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow DIV id='box' class='composited'",
-      "position": [8, 8],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 3
     }
   ],
   "transforms": [
@@ -46,6 +45,25 @@
         [0, 0, 1, 0],
         [43, 143, 0, 1]
       ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 3,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe-expected.txt
index 11c821e..3a1fcb5 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe-expected.txt
@@ -27,11 +27,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='test' class='composited box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 2
+      "transform": 3
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='overlay'",
@@ -59,6 +58,16 @@
         [0, 0, 1, 0],
         [15, 15, 0, 1]
       ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe2-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe2-expected.txt
index 5b3e6b4..661ae9f77 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe2-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe2-expected.txt
@@ -7,7 +7,7 @@
       "backgroundColor": "#FFFFFF"
     },
     {
-      "name": "LayoutIFrame IFRAME id='iframe' class='composited'",
+      "name": "LayoutIFrame IFRAME id='iframe'",
       "position": [-30, -30],
       "bounds": [390, 240],
       "transform": 1
@@ -27,11 +27,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 2
+      "transform": 3
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='overlay'",
@@ -59,6 +58,16 @@
         [0, 0, 1, 0],
         [15, 15, 0, 1]
       ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe3-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe3-expected.txt
index 3b2de6e..ebe4414 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe3-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/connect-compositing-iframe3-expected.txt
@@ -27,11 +27,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 2
+      "transform": 3
     }
   ],
   "transforms": [
@@ -53,6 +52,16 @@
         [0, 0, 1, 0],
         [15, 15, 0, 1]
       ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/enter-compositing-iframe-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/enter-compositing-iframe-expected.txt
index 077f576..ffb8ae77 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/enter-compositing-iframe-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/enter-compositing-iframe-expected.txt
@@ -21,11 +21,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='test' class='composited box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 1
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow HTML",
@@ -43,6 +42,16 @@
         [0, 0, 1, 0],
         [43, 43, 0, 1]
       ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/iframe-resize-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/iframe-resize-expected.txt
index b13e62d..3ee26fc6 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/iframe-resize-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/iframe-resize-expected.txt
@@ -21,11 +21,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 1
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow HTML",
@@ -43,6 +42,16 @@
         [0, 0, 1, 0],
         [43, 43, 0, 1]
       ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/iframe-size-from-zero-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/iframe-size-from-zero-expected.txt
index 2003e441..fd235af 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/iframe-size-from-zero-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/iframe-size-from-zero-expected.txt
@@ -21,11 +21,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 1
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow HTML",
@@ -43,6 +42,16 @@
         [0, 0, 1, 0],
         [43, 43, 0, 1]
       ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/invisible-nested-iframe-hide-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/invisible-nested-iframe-hide-expected.txt
index 6bde2026..77e4b78 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/invisible-nested-iframe-hide-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/invisible-nested-iframe-hide-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/invisible-nested-iframe-show-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/invisible-nested-iframe-show-expected.txt
index 91a2c42..0dedc302 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/invisible-nested-iframe-show-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/invisible-nested-iframe-show-expected.txt
@@ -14,18 +14,17 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
-      "bounds": [210, 160],
+      "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 2
+      "transform": 3
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box'",
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 4
+      "transform": 5
     }
   ],
   "transforms": [
@@ -50,6 +49,16 @@
     },
     {
       "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 4,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
@@ -58,8 +67,8 @@
       ]
     },
     {
-      "id": 4,
-      "parent": 3,
+      "id": 5,
+      "parent": 4,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/overlapped-iframe-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/overlapped-iframe-expected.txt
index 2003e441..fd235af 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/overlapped-iframe-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/overlapped-iframe-expected.txt
@@ -21,11 +21,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 1
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow HTML",
@@ -43,6 +42,16 @@
         [0, 0, 1, 0],
         [43, 43, 0, 1]
       ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/overlapped-nested-iframes-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/overlapped-nested-iframes-expected.txt
index af8b30b..eaba1c2 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/overlapped-nested-iframes-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/overlapped-nested-iframes-expected.txt
@@ -14,19 +14,17 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
-      "bounds": [210, 160],
+      "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 3
+      "transform": 4
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
-      "bounds": [210, 160],
+      "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 5
+      "transform": 7
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='banner'",
@@ -66,6 +64,16 @@
     },
     {
       "id": 4,
+      "parent": 3,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
       "parent": 1,
       "transform": [
         [1, 0, 0, 0],
@@ -75,14 +83,24 @@
       ]
     },
     {
-      "id": 5,
-      "parent": 4,
+      "id": 6,
+      "parent": 5,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
         [9, 9, 0, 1]
       ]
+    },
+    {
+      "id": 7,
+      "parent": 6,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/resizer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/resizer-expected.txt
index d55df783..6870d45 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/resizer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/resizer-expected.txt
@@ -27,11 +27,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 2
+      "transform": 3
     },
     {
       "name": "LayoutIFrame IFRAME class='container'",
@@ -58,6 +57,16 @@
         [0, 0, 1, 0],
         [2, 2, 0, 1]
       ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/scrolling-iframe-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/scrolling-iframe-expected.txt
index 809a7a99..23b6f6b 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/scrolling-iframe-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/iframes/scrolling-iframe-expected.txt
@@ -20,11 +20,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='iframe-content' class='box'",
-      "position": [108, 100],
       "bounds": [200, 200],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
-      "transform": 2
+      "transform": 3
     },
     {
       "name": "LayoutNGBlockFlow HTML",
@@ -52,6 +51,16 @@
         [0, 0, 1, 0],
         [-80, -80, 0, 1]
       ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [108, 100, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/images/direct-image-dynamic-border-draws-content-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/images/direct-image-dynamic-border-draws-content-expected.txt
index 1e8ca86..b566a7b5 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/images/direct-image-dynamic-border-draws-content-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/images/direct-image-dynamic-border-draws-content-expected.txt
@@ -10,8 +10,19 @@
     },
     {
       "name": "LayoutImage IMG class='composited'",
-      "position": [8, 8],
-      "bounds": [256, 256]
+      "bounds": [256, 256],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
     }
   ]
 }
@@ -28,8 +39,19 @@
     },
     {
       "name": "LayoutImage IMG class='composited border'",
-      "position": [8, 8],
-      "bounds": [260, 260]
+      "bounds": [260, 260],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/animation-overlap-with-children-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/animation-overlap-with-children-expected.txt
index b292d934..b2f463d 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/animation-overlap-with-children-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/animation-overlap-with-children-expected.txt
@@ -16,11 +16,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV class='composited banner'",
-      "position": [6, 6],
       "bounds": [250, 50],
       "contentsOpaque": true,
       "backgroundColor": "#C0C0C0",
-      "transform": 2
+      "transform": 3
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='test1 box'",
@@ -49,6 +48,16 @@
         [0, 0, 1, 0],
         [0, 0, 0, 1]
       ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [6, 6, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-nonscrollable-body-overlap-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-nonscrollable-body-overlap-expected.txt
index 9db9467..b326772 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-nonscrollable-body-overlap-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-nonscrollable-body-overlap-expected.txt
@@ -10,10 +10,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='absolute composited red box'",
-      "position": [10, 100],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FF0000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='fixed lime box'",
@@ -22,6 +22,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#00FF00"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 100, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page-expected.txt
index 9a33783..f67e188 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page-expected.txt
@@ -14,16 +14,16 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box'",
-      "position": [50, 360],
       "bounds": [300, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#00FFFF"
+      "backgroundColor": "#00FFFF",
+      "transform": 1
     },
     {
       "name": "LayoutIFrame (positioned) IFRAME id='iframe2' class='composited'",
-      "position": [10, 200],
       "bounds": [154, 154],
-      "backgroundColor": "#9A9A9A"
+      "backgroundColor": "#9A9A9A",
+      "transform": 2
     },
     {
       "name": "LayoutIFrame (positioned) IFRAME id='iframe3'",
@@ -31,6 +31,26 @@
       "bounds": [154, 154],
       "backgroundColor": "#9A9A9A"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 360, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 200, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-under-transform-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-under-transform-expected.txt
index 2cb83ad..0a67a40 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-under-transform-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/fixed-position-under-transform-expected.txt
@@ -14,11 +14,11 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='indicator'",
-      "position": [108, 1113],
+      "position": [100, 100],
       "bounds": [256, 256],
       "contentsOpaque": true,
       "backgroundColor": "#FF0000",
-      "transform": 1
+      "transform": 3
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='overlap'",
@@ -36,6 +36,26 @@
         [0, 0, 1, 0],
         [0, -1000, 0, 1]
       ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 13, 0, 1]
+      ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, 1000, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/no-compositing-for-fixed-position-under-transform-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/no-compositing-for-fixed-position-under-transform-expected.txt
index 8b9df92..08ff01c 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/no-compositing-for-fixed-position-under-transform-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/no-compositing-for-fixed-position-under-transform-expected.txt
@@ -9,10 +9,21 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV class='transform'",
-      "position": [8, 8],
       "bounds": [100, 30],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/overlap-child-layer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/overlap-child-layer-expected.txt
index 616fe000..8077fe1 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/overlap-child-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/overlap-child-layer-expected.txt
@@ -8,9 +8,11 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='container'",
+      "position": [-400, 0],
       "bounds": [256, 256],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FF0000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='green'",
@@ -18,6 +20,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#008000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [400, 0, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/overlap-clipping-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/overlap-clipping-expected.txt
index ef4d5c5..bb2ea72 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/overlap-clipping-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/overlap-clipping-expected.txt
@@ -8,17 +8,17 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='child'",
-      "position": [50, 50],
-      "bounds": [100, 100],
+      "bounds": [500, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow DIV id='child'",
-      "position": [50, 200],
       "bounds": [500, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='overlap'",
@@ -27,6 +27,26 @@
       "contentsOpaque": true,
       "backgroundColor": "#0000FF"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 200, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/remove-clipping-layer-with-no-children-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/remove-clipping-layer-with-no-children-expected.txt
index 6050f21f..1b900f3 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/remove-clipping-layer-with-no-children-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/remove-clipping-layer-with-no-children-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='parent' class='fade'",
-      "position": [8, 8],
       "bounds": [400, 400],
       "contentsOpaque": true,
-      "backgroundColor": "#FFC0CB"
+      "backgroundColor": "#FFC0CB",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/rotate3d-overlap-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/rotate3d-overlap-expected.txt
index d26c91c..2bee6f6 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/rotate3d-overlap-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/rotate3d-overlap-expected.txt
@@ -10,16 +10,17 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='box translateZ'",
-      "position": [23, 23],
+      "position": [-5, -5],
       "bounds": [110, 110],
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='composited box rotate15'",
       "position": [-5, -5],
       "bounds": [110, 110],
       "backgroundColor": "#0000FF",
-      "transform": 2
+      "transform": 3
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='box'",
@@ -32,7 +33,7 @@
       "position": [-5, -5],
       "bounds": [110, 110],
       "backgroundColor": "#0000FF",
-      "transform": 4
+      "transform": 5
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='box'",
@@ -48,12 +49,21 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [172, 28, 0, 1]
+        [28, 28, 0, 1]
       ]
     },
     {
       "id": 2,
-      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [172, 28, 0, 1]
+      ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
       "transform": [
         [0.965925826289068, 0.258819045102521, 0, 0],
         [-0.258819045102521, 0.965925826289068, 0, 0],
@@ -63,7 +73,7 @@
       "origin": [50, 50]
     },
     {
-      "id": 3,
+      "id": 4,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
@@ -72,8 +82,8 @@
       ]
     },
     {
-      "id": 4,
-      "parent": 3,
+      "id": 5,
+      "parent": 4,
       "transform": [
         [0.707106781186548, 0.707106781186548, 0, 0],
         [-0.707106781186548, 0.707106781186548, 0, 0],
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
index 9d4fabf69..4ef40b5 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='composited'",
-      "position": [8, 58],
-      "bounds": [100, 50],
+      "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#FA8072"
+      "backgroundColor": "#FA8072",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='squashed'",
@@ -20,6 +20,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#008000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 58, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/stacking-context-overlap-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/stacking-context-overlap-expected.txt
index b514144c..25aa5ed 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/stacking-context-overlap-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/stacking-context-overlap-expected.txt
@@ -8,16 +8,27 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV class='trigger'",
-      "position": [8, 8],
       "bounds": [20, 20],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='container'",
       "position": [8, 18],
       "bounds": [142, 142]
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/stacking-context-overlap-nested-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/stacking-context-overlap-nested-expected.txt
index 617a10a..c040b7c 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/stacking-context-overlap-nested-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/stacking-context-overlap-nested-expected.txt
@@ -8,15 +8,17 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box'",
-      "position": [10, 10],
+      "position": [-10, -10],
       "bounds": [120, 120],
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box'",
-      "position": [60, 60],
+      "position": [-10, -10],
       "bounds": [220, 120],
-      "backgroundColor": "#FF000099"
+      "backgroundColor": "#FF000099",
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='indicator'",
@@ -25,6 +27,27 @@
       "contentsOpaque": true,
       "backgroundColor": "#0000FF"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [20, 20, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/translatez-added-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/translatez-added-expected.txt
index c537b93..1fbb4bdf 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/translatez-added-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/translatez-added-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='test' class='box composited'",
-      "position": [18, 10],
       "bounds": [210, 210],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/translatez-overlap-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/translatez-overlap-expected.txt
index 34ae3f9..09fe6d9 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/translatez-overlap-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/layer-creation/translatez-overlap-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='composited box'",
-      "position": [18, 10],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [18, 10, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/composited-scrolling-paint-phases-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/composited-scrolling-paint-phases-expected.txt
index 92aea19..d0f4f791 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/composited-scrolling-paint-phases-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/composited-scrolling-paint-phases-expected.txt
@@ -8,11 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='composited'",
-      "position": [1, 11],
       "bounds": [80, 10],
       "contentsOpaque": true,
       "backgroundColor": "#008000",
-      "transform": 1
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow DIV class='container'",
@@ -34,6 +33,16 @@
         [0, 0, 1, 0],
         [28, 20, 0, 1]
       ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [1, 11, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rendering-contexts-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rendering-contexts-expected.txt
index 382c291..b688de4 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rendering-contexts-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rendering-contexts-expected.txt
@@ -25,7 +25,7 @@
       "bounds": [100, 100],
       "contentsOpaque": true,
       "backgroundColor": "#008000",
-      "transform": 4
+      "transform": 5
     }
   ],
   "transforms": [
@@ -54,6 +54,11 @@
       "parent": 3,
       "flattenInheritedTransform": false,
       "renderingContext": 1
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "renderingContext": 2
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-absolute-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-absolute-expected.txt
index 4c2324c..884e112e 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-absolute-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-absolute-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='positioned layer'",
-      "position": [50, 50],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-fixed-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-fixed-expected.txt
index 4c2324c..884e112e 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-fixed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-fixed-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='positioned layer'",
-      "position": [50, 50],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-iframe-fixed-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-iframe-fixed-expected.txt
index 79c4eb3..0d4c363 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-iframe-fixed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-iframe-fixed-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='positioned layer'",
-      "position": [50, 50],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-relative-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-relative-expected.txt
index 17e0549..20e4ec8 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-relative-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/rtl/rtl-relative-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='layer'",
-      "position": [642, 58],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [642, 58, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/clipping-ancestor-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/clipping-ancestor-expected.txt
index 1957ec25..d13d1b17 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/clipping-ancestor-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/clipping-ancestor-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='inner'",
-      "position": [8, 8],
       "bounds": [200, 10],
       "contentsOpaque": true,
-      "backgroundColor": "#F5F5F5"
+      "backgroundColor": "#F5F5F5",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='hoverable'",
@@ -20,6 +20,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#90EE90"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/iframes-are-never-squashed-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/iframes-are-never-squashed-expected.txt
index 8308535..c0706d7 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/iframes-are-never-squashed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/iframes-are-never-squashed-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV",
-      "position": [8, 8],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3"
+      "backgroundColor": "#D3D3D3",
+      "transform": 1
     },
     {
       "name": "LayoutIFrame (positioned) IFRAME",
@@ -19,6 +19,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#ADD8E6"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt
index 112c414..88257780 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box'",
-      "position": [10, 10],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box'",
@@ -20,6 +20,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#008000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 10, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/move-squashing-layer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/move-squashing-layer-expected.txt
index a5fc6a5..8e97b50 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/move-squashing-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/move-squashing-layer-expected.txt
@@ -10,17 +10,17 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='background'",
-      "position": [8, 50],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFF00"
+      "backgroundColor": "#FFFF00",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='host'",
-      "position": [100, 100],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='squashed'",
@@ -29,6 +29,26 @@
       "contentsOpaque": true,
       "backgroundColor": "#0000FF"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 50, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/no-squashing-for-filters-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/no-squashing-for-filters-expected.txt
index 92bb092..10a1043 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/no-squashing-for-filters-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/no-squashing-for-filters-expected.txt
@@ -8,16 +8,27 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV",
-      "position": [8, 8],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#ADD8E6"
+      "backgroundColor": "#ADD8E6",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='trysquashed'",
       "bounds": [100, 100],
       "backgroundColor": "#D3D3D3"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt
index 47cd10c..97a15e1 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='compositedlayer'",
-      "position": [400, 40],
       "bounds": [24, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3"
+      "backgroundColor": "#D3D3D3",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='notsquashedelement'",
@@ -19,6 +19,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#008000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [400, 40, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/opacity-squashed-owner-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/opacity-squashed-owner-expected.txt
index b219922..8bb1a93 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/opacity-squashed-owner-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/opacity-squashed-owner-expected.txt
@@ -8,9 +8,9 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='target' class='composited box opaque'",
-      "position": [8, 8],
       "bounds": [100, 100],
-      "backgroundColor": "#ADD8E6"
+      "backgroundColor": "#ADD8E6",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='squashed'",
@@ -18,6 +18,17 @@
       "bounds": [40, 90],
       "backgroundColor": "#90EE90"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/repaint-child-of-squashed-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/repaint-child-of-squashed-expected.txt
index bae9427..b7ac9ba 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/repaint-child-of-squashed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/repaint-child-of-squashed-expected.txt
@@ -9,10 +9,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box behind'",
-      "position": [50, 50],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box top'",
@@ -21,6 +21,17 @@
       "contentsOpaque": true,
       "backgroundColor": "#00FFFF"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
+      ]
+    }
   ]
 }
 
@@ -35,10 +46,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box behind'",
-      "position": [50, 50],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box top'",
@@ -54,6 +65,17 @@
         }
       ]
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-onto-distant-relative-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-onto-distant-relative-expected.txt
index d437df1..82c7392 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-onto-distant-relative-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-onto-distant-relative-expected.txt
@@ -5,11 +5,6 @@
       "bounds": [800, 600],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow (positioned) DIV id='squashing'",
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-onto-nephew-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-onto-nephew-expected.txt
index 6acb954..2288050 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-onto-nephew-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-onto-nephew-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box behind'",
-      "position": [125, 125],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
@@ -19,6 +19,17 @@
       "bounds": [180, 190],
       "backgroundColor": "#00FF00"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [125, 125, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-paint-invalidation-fixed-position-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-paint-invalidation-fixed-position-expected.txt
index 2b93d631..565ddf0 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-paint-invalidation-fixed-position-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-paint-invalidation-fixed-position-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV",
-      "position": [8, 8],
-      "bounds": [100, 592],
+      "bounds": [100, 5000],
       "contentsOpaque": true,
-      "backgroundColor": "#ADD8E6"
+      "backgroundColor": "#ADD8E6",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV",
@@ -26,6 +26,17 @@
         }
       ]
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
  {
@@ -38,10 +49,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV",
-      "position": [8, 8],
-      "bounds": [100, 592],
+      "bounds": [100, 5000],
       "contentsOpaque": true,
-      "backgroundColor": "#ADD8E6"
+      "backgroundColor": "#ADD8E6",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV",
@@ -56,6 +67,17 @@
         }
       ]
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-simple-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-simple-expected.txt
index e55d6da..16a3b8b 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-simple-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-simple-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box behind'",
-      "position": [100, 100],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
@@ -19,6 +19,17 @@
       "bounds": [260, 260],
       "backgroundColor": "#00FF00"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-three-layers-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-three-layers-expected.txt
index c96bc1def..cb53fdb 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-three-layers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/squashing/squash-three-layers-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box behind'",
-      "position": [100, 100],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
@@ -19,6 +19,17 @@
       "bounds": [180, 190],
       "backgroundColor": "#00FF00"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/tiled-layers-hidpi-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/tiled-layers-hidpi-expected.txt
index c6e09552..88365f6d 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/tiled-layers-hidpi-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/tiled-layers-hidpi-expected.txt
@@ -13,10 +13,21 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='composited'",
-      "position": [16, 16],
       "bounds": [3600, 20],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [16, 16, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt
index ea918f7..98593a1 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt
@@ -8,9 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer' class='final-drop-shadow'",
-      "position": [25, 25],
+      "position": [-75, -75],
       "bounds": [260, 260],
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-bounds-with-composited-blur-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-bounds-with-composited-blur-expected.txt
index df919c5..27fc0a8 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-bounds-with-composited-blur-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-bounds-with-composited-blur-expected.txt
@@ -8,9 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited'",
-      "position": [25, 25],
+      "position": [-75, -75],
       "bounds": [250, 250],
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
index 68de410..432c9ed 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
-      "position": [250, 250],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
     }
   ]
 }
@@ -25,10 +36,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
-      "position": [250, 250],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
@@ -36,6 +47,17 @@
       "bounds": [200, 200],
       "backgroundColor": "#000000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
index 68de410..432c9ed 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
-      "position": [250, 250],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
     }
   ]
 }
@@ -25,10 +36,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
-      "position": [250, 250],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
@@ -36,6 +47,17 @@
       "bounds": [200, 200],
       "backgroundColor": "#000000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/events/touch/compositor-touch-hit-rects-with-negative-child-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/events/touch/compositor-touch-hit-rects-with-negative-child-expected.txt
deleted file mode 100644
index f3c5422..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/events/touch/compositor-touch-hit-rects-with-negative-child-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This tests verifies the hit test regions given to the compositor for an element with child at negative offset. It can only be run in DumpRenderTree.
-
-negativeOffsetChild: layer(212x13) has hit test rect (0,1 103x12)
-
-
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt
index f541c98d..bcd2895 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer-expected.txt
@@ -9,7 +9,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
-      "position": [21, 0],
+      "position": [10, 0],
       "bounds": [12, 12],
       "paintInvalidations": [
         {
@@ -17,6 +17,18 @@
           "rect": [0, 0, 12, 12],
           "reason": "paint property change"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [11, 0, 0, 1]
       ]
     }
   ]
@@ -32,7 +44,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
-      "position": [20, 0],
+      "position": [9, 0],
       "bounds": [13, 12],
       "paintInvalidations": [
         {
@@ -40,6 +52,18 @@
           "rect": [0, 0, 13, 12],
           "reason": "paint property change"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [11, 0, 0, 1]
       ]
     }
   ]
@@ -55,7 +79,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
-      "position": [20, 0],
+      "position": [10, 0],
       "bounds": [13, 12],
       "paintInvalidations": [
         {
@@ -63,6 +87,18 @@
           "rect": [0, 0, 13, 12],
           "reason": "paint property change"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 0, 0, 1]
       ]
     }
   ]
@@ -78,7 +114,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
-      "position": [21, 0],
+      "position": [10, 0],
       "bounds": [13, 12],
       "paintInvalidations": [
         {
@@ -86,6 +122,18 @@
           "rect": [0, 0, 13, 12],
           "reason": "paint property change"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [11, 0, 0, 1]
       ]
     }
   ]
@@ -101,7 +149,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'",
-      "position": [20, 0],
+      "position": [10, 0],
       "bounds": [13, 12],
       "paintInvalidations": [
         {
@@ -109,6 +157,18 @@
           "rect": [0, 0, 13, 12],
           "reason": "paint property change"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 0, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/multiple-backgrounds-style-change-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/multiple-backgrounds-style-change-expected.txt
index f17c5d8..313bfe9 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/multiple-backgrounds-style-change-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/multiple-backgrounds-style-change-expected.txt
@@ -8,8 +8,29 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='test' class='composited box changed'",
-      "position": [58, 58],
-      "bounds": [202, 202]
+      "bounds": [202, 202],
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt
index a6e087e..2ded46d 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt
@@ -8,7 +8,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='container'",
-      "position": [100, 100],
+      "position": [-1, 0],
       "bounds": [15, 14],
       "paintInvalidations": [
         {
@@ -16,6 +16,18 @@
           "rect": [0, 0, 15, 14],
           "reason": "style change"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [101, 100, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/chunk-reorder-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/chunk-reorder-expected.txt
index efe986c..68de53f 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/chunk-reorder-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/chunk-reorder-expected.txt
@@ -8,7 +8,6 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV",
-      "position": [8, 8],
       "bounds": [550, 550],
       "backgroundColor": "#FF0000",
       "paintInvalidations": [
@@ -22,6 +21,18 @@
           "rect": [0, 0, 1, 1],
           "reason": "chunk reordered"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer-expected.txt
index 456d2ea..cd43e025 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer-expected.txt
@@ -13,7 +13,6 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV",
-      "position": [8, 408],
       "bounds": [304, 154],
       "backgroundColor": "#9A9A9A",
       "paintInvalidations": [
@@ -22,6 +21,18 @@
           "rect": [10, 10, 50, 50],
           "reason": "background"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 408, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt
index f845d26..61bc62d 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV",
-      "position": [8, 8],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3"
+      "backgroundColor": "#D3D3D3",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV",
@@ -29,7 +29,6 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='target'",
-      "position": [50, 50],
       "bounds": [200, 200],
       "contentsOpaque": true,
       "backgroundColor": "#ADD8E6",
@@ -39,6 +38,27 @@
           "rect": [0, 0, 200, 200],
           "reason": "full layer"
         }
+      ],
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidations-on-composited-layers-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidations-on-composited-layers-expected.txt
index c123e81..874f4f1 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidations-on-composited-layers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/invalidations-on-composited-layers-expected.txt
@@ -8,7 +8,6 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='parent'",
-      "position": [8, 8],
       "bounds": [400, 400],
       "contentsOpaque": true,
       "backgroundColor": "#008000",
@@ -18,11 +17,11 @@
           "rect": [0, 0, 400, 400],
           "reason": "background"
         }
-      ]
+      ],
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='child'",
-      "position": [58, 58],
       "bounds": [75, 75],
       "contentsOpaque": true,
       "backgroundColor": "#0000FF",
@@ -32,6 +31,28 @@
           "rect": [0, 0, 75, 75],
           "reason": "background"
         }
+      ],
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.txt
index 4042a82..99fef7c 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.txt
@@ -12,10 +12,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV",
-      "position": [8, 8],
       "bounds": [800, 800],
       "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3"
+      "backgroundColor": "#D3D3D3",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV",
@@ -30,6 +30,17 @@
         }
       ]
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
index a160f68..6b13d199 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV",
-      "position": [8, 8],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#ADD8E6"
+      "backgroundColor": "#ADD8E6",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='container'",
@@ -27,6 +27,17 @@
         }
       ]
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/resize-repaint-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/resize-repaint-expected.txt
index 957fb6d..eac40e31 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/resize-repaint-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/resize-repaint-expected.txt
@@ -8,7 +8,6 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='resizing'",
-      "position": [8, 8],
       "bounds": [402, 207],
       "paintInvalidations": [
         {
@@ -26,6 +25,18 @@
           "rect": [2, 104, 398, 50],
           "reason": "appeared"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/should-not-repaint-composited-transform-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/should-not-repaint-composited-transform-expected.txt
index be82e3c..6a9bd9d 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/should-not-repaint-composited-transform-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/should-not-repaint-composited-transform-expected.txt
@@ -8,8 +8,29 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='composited-box'",
-      "position": [108, 108],
-      "bounds": [102, 102]
+      "bounds": [102, 102],
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.txt
index b7e4e2b..f44f248 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.txt
@@ -8,10 +8,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box behind'",
-      "position": [100, 100],
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
@@ -26,6 +26,17 @@
         }
       ]
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt
index d3630bc..62078659 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt
@@ -11,7 +11,7 @@
       "bounds": [100, 100],
       "contentsOpaque": true,
       "backgroundColor": "#D3D3D3",
-      "transform": 2
+      "transform": 3
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='target'",
@@ -45,6 +45,12 @@
       ],
       "flattenInheritedTransform": false,
       "renderingContext": 1
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "flattenInheritedTransform": false,
+      "renderingContext": 1
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/tricky-element-removal-crash-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/tricky-element-removal-crash-expected.txt
index efd3ebd..a01b998 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/tricky-element-removal-crash-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/compositing/tricky-element-removal-crash-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV",
-      "position": [8, 8],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#FA8072"
+      "backgroundColor": "#FA8072",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-invalidation-with-composited-container-change-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-invalidation-with-composited-container-change-expected.txt
index a921ed9..9e2d7f4 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-invalidation-with-composited-container-change-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-invalidation-with-composited-container-change-expected.txt
@@ -15,14 +15,27 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='box' class='green box blurry'",
-      "bounds": [238, 238],
+      "position": [-30, -30],
+      "bounds": [260, 260],
       "backgroundColor": "#008000",
       "paintInvalidations": [
         {
           "object": "LayoutNGBlockFlow DIV id='box' class='green box blurry'",
-          "rect": [0, 0, 238, 238],
+          "rect": [0, 0, 260, 260],
           "reason": "full layer"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.txt
index 01947e4e..3bfa301f 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.txt
@@ -8,14 +8,27 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='resize' class='drop-shadow'",
-      "bounds": [154, 254],
+      "position": [-14, -14],
+      "bounds": [160, 260],
       "backgroundColor": "#008000",
       "paintInvalidations": [
         {
           "object": "LayoutNGBlockFlow DIV id='resize' class='drop-shadow'",
-          "rect": [0, 0, 154, 254],
+          "rect": [0, 0, 160, 260],
           "reason": "geometry"
         }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-repaint-on-accelerated-layer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-repaint-on-accelerated-layer-expected.txt
index d5448a0..50335ce 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-repaint-on-accelerated-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/filters/filter-repaint-on-accelerated-layer-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow DIV id='resize' class='accelerated'",
-      "position": [8, 8],
       "bounds": [100, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt
index bced5de..72b1b4e 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt
@@ -20,7 +20,6 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='container'",
-      "position": [50, 0],
       "bounds": [600, 600],
       "contentsOpaque": true,
       "backgroundColor": "#FF0000",
@@ -31,7 +30,7 @@
           "reason": "appeared"
         }
       ],
-      "transform": 2
+      "transform": 3
     }
   ],
   "transforms": [
@@ -53,6 +52,16 @@
         [0, 0, 1, 0],
         [-365, 0, 0, 1]
       ]
+    },
+    {
+      "id": 3,
+      "parent": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 0, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/color-suggestion-picker-appearance-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/color-suggestion-picker-appearance-expected.png
deleted file mode 100644
index f3ddf80..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/color-suggestion-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/color-suggestion-picker-appearance-value-attribute-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/color-suggestion-picker-appearance-value-attribute-expected.png
deleted file mode 100644
index 203556a..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/color-suggestion-picker-appearance-value-attribute-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt
index 8c9add12..08f1d5810 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt
@@ -8,9 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer' class='final-drop-shadow'",
-      "position": [50, 50],
+      "position": [-150, -150],
       "bounds": [520, 520],
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [200, 200, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-bounds-with-composited-blur-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-bounds-with-composited-blur-expected.txt
index 82105ea..605105eb 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-bounds-with-composited-blur-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-bounds-with-composited-blur-expected.txt
@@ -8,9 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited'",
-      "position": [50, 50],
+      "position": [-150, -150],
       "bounds": [500, 500],
-      "backgroundColor": "#008000"
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [200, 200, 0, 1]
+      ]
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
index b3927fa6..ffcc372 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
-      "position": [500, 500],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [500, 500, 0, 1]
+      ]
     }
   ]
 }
@@ -25,10 +36,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
-      "position": [500, 500],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
@@ -36,6 +47,17 @@
       "bounds": [400, 400],
       "backgroundColor": "#000000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [500, 500, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
index b3927fa6..ffcc372 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
@@ -8,10 +8,21 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
-      "position": [500, 500],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [500, 500, 0, 1]
+      ]
     }
   ]
 }
@@ -25,10 +36,10 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
-      "position": [500, 500],
       "bounds": [200, 200],
       "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
+      "backgroundColor": "#0000FF",
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
@@ -36,6 +47,17 @@
       "bounds": [400, 400],
       "backgroundColor": "#000000"
     }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [500, 500, 0, 1]
+      ]
+    }
   ]
 }
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/layers/layer-canvas-log.js b/third_party/blink/web_tests/http/tests/devtools/layers/layer-canvas-log.js
index 398d3fa7..48d0b50 100644
--- a/third_party/blink/web_tests/http/tests/devtools/layers/layer-canvas-log.js
+++ b/third_party/blink/web_tests/http/tests/devtools/layers/layer-canvas-log.js
@@ -6,7 +6,7 @@
   TestRunner.addResult(`Tests layer command log\n`);
   await TestRunner.loadModule('layers_test_runner');
   await TestRunner.loadHTML(`
-      <div id="a" style="transform: translateZ(0px); background-color:blue; width:100px; height:100px;">
+      <div id="a" style="will-change: transform; background-color:blue; width:100px; height:100px;">
           <div style="width:50px; height:50px; background-color:red;"></div>
           <img src="resources/test.png">
           <svg>
diff --git a/third_party/blink/web_tests/http/tests/devtools/layers/layer-replay-scale.js b/third_party/blink/web_tests/http/tests/devtools/layers/layer-replay-scale.js
index 10f5903..d0fbcd7 100644
--- a/third_party/blink/web_tests/http/tests/devtools/layers/layer-replay-scale.js
+++ b/third_party/blink/web_tests/http/tests/devtools/layers/layer-replay-scale.js
@@ -7,7 +7,7 @@
       `Tests that when layer snapshots are replayed with scaling applied the image dimensions are properly scaled.\n`);
   await TestRunner.loadModule('layers_test_runner');
   await TestRunner.loadHTML(`
-      <div id="a" style="background-color:blue; transform: translateZ(0px); overflow: hidden;">
+      <div id="a" style="background-color:blue; will-change: transform; overflow: hidden;">
 
           <div style="width:50px; height:50px; background-color:red;"></div>
           <img src="../tracing/resources/test.png">
diff --git a/third_party/blink/web_tests/http/tests/devtools/layers/layers-3d-view-hit-testing.js b/third_party/blink/web_tests/http/tests/devtools/layers/layers-3d-view-hit-testing.js
index 93e01768..1f96c8b 100644
--- a/third_party/blink/web_tests/http/tests/devtools/layers/layers-3d-view-hit-testing.js
+++ b/third_party/blink/web_tests/http/tests/devtools/layers/layers-3d-view-hit-testing.js
@@ -7,8 +7,8 @@
   await TestRunner.loadModule('layers_test_runner');
 
   await TestRunner.loadHTML(`
-      <div id="a" style="transform:translateZ(0px) translateY(60px) rotateZ(45deg);width:300px;height:300px;margin-left:100px; border: 1px solid black;">
-          <div id="b" style="transform:translateX(0px) translateY(0px) translateZ(0px) rotateX(45deg) rotateY(45deg);width:300px;height:300px; border: 1px solid black;"></div>
+      <div id="a" style="will-change: transform; transform:translateY(60px) rotateZ(45deg);width:300px;height:300px;margin-left:100px; border: 1px solid black;">
+          <div id="b" style="will-change: transform; transform:translateX(0px) translateY(0px) rotateX(45deg) rotateY(45deg);width:300px;height:300px; border: 1px solid black;"></div>
       </div>
   `);
 
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 93fd88d..c767408d 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -3744,6 +3744,7 @@
     getter storage
     getter usb
     getter userAgent
+    getter wakeLock
     method constructor
 interface WritableStream
     attribute @@toStringTag
diff --git a/third_party/blink/web_tests/images/color-profile-image-canvas-pattern.html b/third_party/blink/web_tests/images/color-profile-image-canvas-pattern.html
index eae8d06..dfaabb0 100644
--- a/third_party/blink/web_tests/images/color-profile-image-canvas-pattern.html
+++ b/third_party/blink/web_tests/images/color-profile-image-canvas-pattern.html
@@ -3,7 +3,7 @@
 <script src="../resources/run-after-layout-and-paint.js"></script>
 
 <style>
-  canvas { transform: translateZ(0); }
+  canvas { will-change: transform; }
   img, canvas { margin: 5px; width: 48% }
 </style>
 
diff --git a/third_party/blink/web_tests/images/cross-fade-tiled.html b/third_party/blink/web_tests/images/cross-fade-tiled.html
index 66b9b4845..28c48c4 100644
--- a/third_party/blink/web_tests/images/cross-fade-tiled.html
+++ b/third_party/blink/web_tests/images/cross-fade-tiled.html
@@ -2,11 +2,10 @@
 <style>
 div
 {
-	width: 100px;
-	height: 80px;
-	margin: 20px;
-
-	transform:translateZ(0);
+  width: 100px;
+  height: 80px;
+  margin: 20px;
+  will-change: transform;
 }
 </style>
 <!--The 1st cross-fade should appear as a simple tartan, with the pattern clipped to fit.-->
diff --git a/third_party/blink/web_tests/images/imagemap-focus-ring-with-paint-root-offset.html b/third_party/blink/web_tests/images/imagemap-focus-ring-with-paint-root-offset.html
index a6cd4038..4c64448 100644
--- a/third_party/blink/web_tests/images/imagemap-focus-ring-with-paint-root-offset.html
+++ b/third_party/blink/web_tests/images/imagemap-focus-ring-with-paint-root-offset.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <style>
 .paintroot {
-  transform: translateZ(0);
+  will-change: transform;
   position: absolute;
   left: 5px;
   top: 50px;
diff --git a/third_party/blink/web_tests/images/yuv-decode-eligible/color-profile-layer-filter.html b/third_party/blink/web_tests/images/yuv-decode-eligible/color-profile-layer-filter.html
index 84f6f51b..1b4f630 100644
--- a/third_party/blink/web_tests/images/yuv-decode-eligible/color-profile-layer-filter.html
+++ b/third_party/blink/web_tests/images/yuv-decode-eligible/color-profile-layer-filter.html
@@ -2,7 +2,7 @@
 <html>
 <style>
   img {
-    transform: translateZ(0); /* Enable direct compositing. */
+    will-change: transform; /* Enable direct compositing. */
     width: 250px;
   }
   .filter {
diff --git a/third_party/blink/web_tests/images/yuv-decode-eligible/color-profile-layer.html b/third_party/blink/web_tests/images/yuv-decode-eligible/color-profile-layer.html
index 8865c03e..2b49b1b 100644
--- a/third_party/blink/web_tests/images/yuv-decode-eligible/color-profile-layer.html
+++ b/third_party/blink/web_tests/images/yuv-decode-eligible/color-profile-layer.html
@@ -2,7 +2,7 @@
 <html>
 <style>
   .layer {
-    transform: translateZ(0); /* Enable direct compositing. */
+    will-change: transform; /* Enable direct compositing. */
     width: 250px;
   }
 </style>
diff --git a/third_party/blink/web_tests/paint/invalidation/background/multiple-backgrounds-style-change-expected.html b/third_party/blink/web_tests/paint/invalidation/background/multiple-backgrounds-style-change-expected.html
index 3a4ee61..82de4c4 100644
--- a/third_party/blink/web_tests/paint/invalidation/background/multiple-backgrounds-style-change-expected.html
+++ b/third_party/blink/web_tests/paint/invalidation/background/multiple-backgrounds-style-change-expected.html
@@ -9,6 +9,7 @@
         background-position: 0 0, 100px 100px;
         background-image: url('../../../images/resources/green-256x256.jpg'), url('../../../images/resources/dice.png');
         transform: translate3d(50px, 50px, 0);
+        will-change: transform;
     }
 </style>
 <div id="test" class="box">
diff --git a/third_party/blink/web_tests/paint/invalidation/background/multiple-backgrounds-style-change.html b/third_party/blink/web_tests/paint/invalidation/background/multiple-backgrounds-style-change.html
index eebd8d32..08ede49 100644
--- a/third_party/blink/web_tests/paint/invalidation/background/multiple-backgrounds-style-change.html
+++ b/third_party/blink/web_tests/paint/invalidation/background/multiple-backgrounds-style-change.html
@@ -11,6 +11,7 @@
     }
 
     .composited {
+        will-change: transform;
         transform: translate3d(0, 0, 0);
     }
 
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer.html b/third_party/blink/web_tests/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer.html
index f961363..7919b5f 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 .container {
-  transform: translateZ(0);
+  will-change: transform;
   position: absolute;
   top: 100px;
   left:100.5px;
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/chunk-reorder.html b/third_party/blink/web_tests/paint/invalidation/compositing/chunk-reorder.html
index 025e409..aac9b2f 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/chunk-reorder.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/chunk-reorder.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<div style="transform:translateZ(0);">
+<div style="will-change: transform;">
   <div id="chunk1" style="width:1px; height:1px; background:red;"></div>
   <div id="chunk2" style="transform:translateX(0); position:absolute; z-index:0; left:0; top:0; width:1px; height:1px; background:orange;"></div>
   <div id="chunk3" style="transform:translateX(0); position:absolute; z-index:1; left:400px; top:400px; width:100px; height:100px; background:yellow;"></div>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/clipped-layer-size-change.html b/third_party/blink/web_tests/paint/invalidation/compositing/clipped-layer-size-change.html
index 2642aad..57d91b1b 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/clipped-layer-size-change.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/clipped-layer-size-change.html
@@ -27,7 +27,7 @@
         .composited {
             height: 150px;
             width: 100px;
-            transform: translateZ(0);
+            will-change: transform;
         }
     </style>
     <script>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html b/third_party/blink/web_tests/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html
index acdab24..3d791af4 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html
@@ -9,7 +9,7 @@
     .clipping-container {
         position: absolute;
         height: 300px;
-        transform: translateZ(0);
+        will-change: transform;
     }
 
     .with-initial-clipping {
@@ -21,7 +21,7 @@
         height: 250px;
         background-color: yellow;
         border: 1px solid black;
-        transform: translateZ(0);
+        will-change: transform;
     }
 </style>
 <style id="alt1">
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-document-element.html b/third_party/blink/web_tests/paint/invalidation/compositing/composited-document-element.html
index 251da80a..0d9e37a4 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/composited-document-element.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-document-element.html
@@ -11,7 +11,7 @@
       background-color: transparent;
     }
     body {
-      transform: translateZ(0);
+      will-change: transform;
     }
     .box {
       width: 100px;
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer.html b/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer.html
index 4e3b3328..9c58f35 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer.html
@@ -8,7 +8,7 @@
 .compositedBehind {
   width: 500px;
   height: 500px;
-  transform: translatez(0);
+  will-change: transform;
   background-color: cyan;
 }
 
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.html b/third_party/blink/web_tests/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.html
index 028a358..9a2efd7 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <body>
-<div id="foo" style="width: 200px; height: 1000px; transform: translateZ(0); background-color: lightgray;"></div>
+<div id="foo" style="width: 200px; height: 1000px; will-change: transform; background-color: lightgray;"></div>
 
 <!-- The squashing layer will contain the following two divs. Note that the second is 100px lower than the top. -->
 <div style="position: absolute; z-index: 0; top: 0px; width: 100px; height: 500px"></div>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/iframe-inside-squashed-layer.html b/third_party/blink/web_tests/paint/invalidation/compositing/iframe-inside-squashed-layer.html
index 791d15e..fb3983d 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/iframe-inside-squashed-layer.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/iframe-inside-squashed-layer.html
@@ -6,7 +6,7 @@
 }
 </script>
 <body onload="runRepaintAndPixelTest()">
-<div id="foo" style="width: 200px; height: 1000px; transform: translateZ(0); background-color: lightgray;"></div>
+<div id="foo" style="width: 200px; height: 1000px; will-change: transform; background-color: lightgray;"></div>
 
 <!-- The squashing layer will contain the following two divs. Note that the second is 100px lower than the top. -->
 <div style="position: absolute; z-index: 0; top: 0px; width: 100px; height: 500px"></div>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/inline-repaint-container.html b/third_party/blink/web_tests/paint/invalidation/compositing/inline-repaint-container.html
index a011235..777cd6b 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/inline-repaint-container.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/inline-repaint-container.html
@@ -13,7 +13,7 @@
         width: 200px;
         height: 100px;
         border: 1px solid black;
-        transform: translateZ(0);
+        will-change: transform;
     }
   </style>
   <script type="text/javascript" charset="utf-8">
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer.html b/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer.html
index 7e01f2f..021d3cf 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer.html
@@ -17,6 +17,6 @@
 </script>
 </head>
 <div style="height: 400px"></div>
-<div style="height: 200px; width: 200px; transform: translateZ(0)">
+<div style="height: 200px; width: 200px; will-change: transform;">
     <iframe srcdoc="<div style='height: 50px; width: 50px; background-color: red;'></div>"></iframe>
 </div>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html b/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html
index 8215269a..b12d09e 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<div style="position:absolute; height: 200px; width: 200px; transform: translateZ(0); background: lightgray"></div>
+<div style="position:absolute; height: 200px; width: 200px; will-change: transform; background: lightgray"></div>
 <div style="position:absolute; height: 200px; width: 200px; top: 50px; left: 50px; background:lightblue"></div>
 <div id="target" style="position:absolute; height: 200px; width: 200px; top: 50px; left: 50px; background:lightblue"></div>
 <script src="../resources/text-based-repaint.js"></script>
@@ -8,7 +8,7 @@
 // location of the squashed layer.
 function repaintTest() {
     var target = document.getElementById("target");
-    target.style.transform = 'translateZ(0)';
+    target.style.willChange = 'transform';
 };
 runRepaintAndPixelTest();
 </script>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/invalidations-on-composited-layers.html b/third_party/blink/web_tests/paint/invalidation/compositing/invalidations-on-composited-layers.html
index f97a7e9..6d45d818 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/invalidations-on-composited-layers.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/invalidations-on-composited-layers.html
@@ -8,14 +8,14 @@
 <head>
   <style type="text/css">
     #parent {
-        transform: translateZ(0px);
+        will-change: transform;
         width: 400px;
         height: 400px;
         background: blue;
     }
 
     #child {
-        transform: translateZ(0px);
+        will-change: transform;
         position: relative;
         left: 50px;
         top: 50px;
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/newly-composited-repaint-rect.html b/third_party/blink/web_tests/paint/invalidation/compositing/newly-composited-repaint-rect.html
index a3af37f..de7964a6 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/newly-composited-repaint-rect.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/newly-composited-repaint-rect.html
@@ -16,7 +16,7 @@
 
   <style type="text/css">
       .composited {
-          transform: translatez(0);
+          will-change: transform;
           border: 2px solid black;
       }
 
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter.html b/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter.html
index b7cb695e..b28d307 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter.html
@@ -4,7 +4,7 @@
     margin: 0;
 }
 </style>
-<iframe style="width:300px;height:100px;border:0;margin:0" src="data:text/html,<body style='transform:translateZ(0);background:yellow'>">
+<iframe style="width:300px;height:100px;border:0;margin:0" src="data:text/html,<body style='will-change: transform;background:yellow'>">
 </iframe>
 <div style="border:0; margin:0; width:300px;height:100px; filter: drop-shadow(red 0 0 0);  position: absolute; top: 0px; left: 0px; transform: translateX(151px); background: lightgray;">
 </div> 
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/remove-squashed-layer-plus-move.html b/third_party/blink/web_tests/paint/invalidation/compositing/remove-squashed-layer-plus-move.html
index 65f5aac..caaba58 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/remove-squashed-layer-plus-move.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/remove-squashed-layer-plus-move.html
@@ -8,7 +8,7 @@
     margin-right:410px;
 }
 </style>
-<div style="position: absolute; width: 1000px; height: 1000px; transform: translateZ(0)"></div>
+<div style="position: absolute; width: 1000px; height: 1000px; will-change: transform;"></div>
 <div id="container">
     <div class="mv-tile" id="foo"></div>
     <div class="mv-tile" style="background-color: lightblue;"></div>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html
index c677f114..22609d6 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <div style="position: absolute; overflow:scroll; width:200px; height:200px">
-  <div id="foo2" style="height: 1000px; width: 150px;  background: lightblue; transform: translateZ(0) "></div>
+  <div id="foo2" style="height: 1000px; width: 150px;  background: lightblue; will-change: transform;"></div>
   <div id="foo" style="height: 1000px; width: 100px; position: absolute; top: 0px; left: 0px; background: lightgray"></div>
 </div>
 <script src="../resources/text-based-repaint.js"></script>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-squashed-layer-in-rect.html b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-squashed-layer-in-rect.html
index 5c9f278..5cd48f1a 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-squashed-layer-in-rect.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-squashed-layer-in-rect.html
@@ -1,5 +1,5 @@
 <!doctype html>
-<div style="height: 800px; width: 800px; background-color: lightgray; transform:translateZ(0)">
+<div style="height: 800px; width: 800px; background-color: lightgray; will-change: transform;">
 </div>
 <div style="position:absolute; top: 0px; height: 200px; width: 200px">
 </div>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-via-layout-offset.html b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-via-layout-offset.html
index f742027..184e05c 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-via-layout-offset.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-via-layout-offset.html
@@ -21,7 +21,7 @@
   background-color: green;
 }
 </style>
-<div style="width:200px; height:200px; transform: translateZ(0px); background-color: lightblue"></div>
+<div style="width:200px; height:200px; will-change: transform; background-color: lightblue"></div>
 <div id="container">
   <span class="child"></span>
   <span class="child"></span>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/resize-repaint.html b/third_party/blink/web_tests/paint/invalidation/compositing/resize-repaint.html
index 12958ca6..ba6c13cc 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/resize-repaint.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/resize-repaint.html
@@ -6,7 +6,7 @@
         #resizing {
             width: 400px;
             border: 1px solid black;
-            transform: translateZ(0);
+            will-change: transform;
         }
 
         #resizing > div {
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint.html b/third_party/blink/web_tests/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint.html
index 31fb9ec..275ae5a 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint.html
@@ -2,7 +2,7 @@
 <script src="../resources/text-based-repaint.js"></script>
 
 <!-- The second two divs form a combined squashing layer. display:none'ing the first of them will resize the squashing layer. -->
-<div style="width: 500px; height: 500px; transform: translateZ(0)"></div>
+<div style="width: 500px; height: 500px; will-change: transform;"></div>
 <div style="position: absolute; top: 55px; left: 55px; width: 500px; height: 500px; background-color: lightblue"></div>
 <div id="to-be-removed" style="position: absolute; top: 0px; left: 0px; width: 50px; height: 50px; background-color: lightgray"></div>
 
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/should-invoke-deferred-compositing.html b/third_party/blink/web_tests/paint/invalidation/compositing/should-invoke-deferred-compositing.html
index 667b61f..7d31719a 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/should-invoke-deferred-compositing.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/should-invoke-deferred-compositing.html
@@ -15,7 +15,7 @@
 <style>
 
 .composited {
-  transform: translatez(0);
+  will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-transform.html b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-transform.html
index cebe594..c584937 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-transform.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-transform.html
@@ -4,13 +4,14 @@
     width: 100px;
     height: 100px;
     border: solid 1px black;
-    transform:translate3D(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+    will-change: transform;
 }
 </style>
 <script src="../resources/text-based-repaint.js"></script>
 <script>
 function repaintTest() {
-    document.getElementById('composited-box').style.transform = 'translate3D(100px, 100px, 0)';
+    document.getElementById('composited-box').style.transform = 'translate3d(100px, 100px, 0)';
 }
 window.onload = runRepaintTest;
 </script>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer.html b/third_party/blink/web_tests/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer.html
index 6311f0a..4a0bf39d 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer.html
@@ -2,7 +2,7 @@
 <head>
 <style>
 .composited {
-transform: translatez(0);
+will-change: transform;
 }
 
 .box {
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/squashing-inside-preserve-3d-element.html b/third_party/blink/web_tests/paint/invalidation/compositing/squashing-inside-preserve-3d-element.html
index d86617e..1d8ccf40 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/squashing-inside-preserve-3d-element.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/squashing-inside-preserve-3d-element.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <div style="transform-style: preserve-3d">
-  <div style="width: 100px; height: 100px; background:lightgray; transform:translateZ(0)"></div>
+  <div style="width: 100px; height: 100px; background:lightgray; will-change: transform;"></div>
   <div id="target" style="position: absolute; top: 20px; left: 20px; height: 100px; width: 100px; background:lightblue"></div>
 </div>
 <script src="../resources/text-based-repaint.js"></script>
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/tricky-element-removal-crash.html b/third_party/blink/web_tests/paint/invalidation/compositing/tricky-element-removal-crash.html
index 7a2153b..24c4b7c 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/tricky-element-removal-crash.html
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/tricky-element-removal-crash.html
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <script src="../resources/text-based-repaint.js"></script>
-<div style="width: 200px; height: 200px; transform: translateZ(0); background-color: salmon;"></div>
+<div style="width: 200px; height: 200px; will-change: transform; background-color: salmon;"></div>
 <div style="position: absolute; z-index: 0; top: 8px; width: 100px; height: 100px">
-  <div id="target" style="width: 100px; height: 100px; transform: translateZ(0); background-color: blue">
+  <div id="target" style="width: 100px; height: 100px; will-change: transform; background-color: blue">
 </div>
 <script>
 function repaintTest() {
diff --git a/third_party/blink/web_tests/paint/invalidation/filters/filter-invalidation-with-composited-container-change.html b/third_party/blink/web_tests/paint/invalidation/filters/filter-invalidation-with-composited-container-change.html
index ad6076e6..c88e0e9 100644
--- a/third_party/blink/web_tests/paint/invalidation/filters/filter-invalidation-with-composited-container-change.html
+++ b/third_party/blink/web_tests/paint/invalidation/filters/filter-invalidation-with-composited-container-change.html
@@ -12,7 +12,7 @@
 }
 .blurry {
   filter: blur(10px);
-  transform: translateZ(0);
+  will-change: transform;
 }
 </style>
 <!--
diff --git a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.html b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.html
index c4dce2a..71d4cd1 100644
--- a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.html
+++ b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.html
@@ -14,7 +14,7 @@
 }
 
 .accelerated {
-    transform: translateZ(0);
+    will-change: transform;
 }
 
 #resize {
diff --git a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child.html b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child.html
index ab61e4d4..fe8094b7 100644
--- a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child.html
+++ b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child.html
@@ -14,7 +14,7 @@
 }
 
 .accelerated {
-    transform: translateZ(0);
+    will-change: transform;
 }
 
 #resize {
diff --git a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter-expected.html b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter-expected.html
index c62f54d..ddfd8ad2 100644
--- a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter-expected.html
+++ b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter-expected.html
@@ -14,7 +14,7 @@
 }
 
 .accelerated {
-    transform: translateZ(0);
+    will-change: transform;
 }
 
 #resize {
diff --git a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter.html b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter.html
index 591ea8b..4495a362 100644
--- a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter.html
+++ b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter.html
@@ -14,7 +14,7 @@
 }
 
 .accelerated {
-    transform: translateZ(0);
+    will-change: transform;
 }
 
 #resize {
diff --git a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-on-accelerated-layer-expected.html b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-on-accelerated-layer-expected.html
index 750d2bc..b8e3254 100644
--- a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-on-accelerated-layer-expected.html
+++ b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-on-accelerated-layer-expected.html
@@ -10,7 +10,7 @@
 }
 
 .accelerated {
-    transform: translateZ(0);
+    will-change: transform;
 }
 
 #resize {
diff --git a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-on-accelerated-layer.html b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-on-accelerated-layer.html
index d7a80a4e8..a50964d 100644
--- a/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-on-accelerated-layer.html
+++ b/third_party/blink/web_tests/paint/invalidation/filters/filter-repaint-on-accelerated-layer.html
@@ -10,7 +10,7 @@
 }
 
 .accelerated {
-    transform: translateZ(0);
+    will-change: transform;
 }
 
 #resize {
diff --git a/third_party/blink/web_tests/paint/invalidation/overflow/overflow-changed-on-child-of-composited-layer.html b/third_party/blink/web_tests/paint/invalidation/overflow/overflow-changed-on-child-of-composited-layer.html
index b1fe04f..7bebd63 100644
--- a/third_party/blink/web_tests/paint/invalidation/overflow/overflow-changed-on-child-of-composited-layer.html
+++ b/third_party/blink/web_tests/paint/invalidation/overflow/overflow-changed-on-child-of-composited-layer.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<div id="parent" style="margin: 20px; transform: scale3d(1, 1, 1);">
+<div id="parent" style="margin: 20px; will-change: transform;">
     <div id="test" style="height: 100px; width: 100px;"></div>
 </div>
 <script src="../resources/text-based-repaint.js"></script>
diff --git a/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-overlay.html b/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-overlay.html
index 3e81111..e76e5d8 100644
--- a/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-overlay.html
+++ b/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-overlay.html
@@ -56,89 +56,56 @@
 var expected = {
   "layers": [
     {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
       "name": "Scrolling Contents Layer",
       "bounds": [800, 2016],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
+      "scrollPosition": [0, 20],
       "transform": 1
     },
     {
-      "name": "LayoutBlockFlow (positioned) DIV id='container'",
-      "position": [40, 50],
+      "name": "LayoutNGBlockFlow (positioned) DIV id='container'",
       "bounds": [100, 100],
       "backgroundColor": "#0000FF80",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow (relative positioned) DIV id='child1'",
+          "object": "LayoutNGBlockFlow (relative positioned) DIV id='child1'",
           "rect": [20, 20, 10, 10],
           "reason": "background"
         }
       ],
-      "transform": 1
+      "transform": 3
     },
     {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrollable'",
-      "position": [104, 103],
+      "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrollable'",
       "bounds": [302, 302],
-      "transform": 1
+      "transform": 4
     },
     {
-      "name": "Scrolling Layer",
-      "position": [105, 104],
-      "bounds": [300, 300],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [105, 104],
-      "bounds": [795, 1491],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='transform'",
+      "name": "LayoutNGBlockFlow (relative positioned) DIV id='transform'",
       "bounds": [200, 200],
       "contentsOpaque": true,
       "backgroundColor": "#FFFF00",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow (relative positioned) DIV id='child2'",
+          "object": "LayoutNGBlockFlow (relative positioned) DIV id='child2'",
           "rect": [20, 20, 10, 10],
           "reason": "background"
         }
       ],
-      "transform": 4
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [104, 103],
-      "bounds": [302, 302],
-      "drawsContent": false,
-      "transform": 1
+      "transform": 7
     },
     {
       "name": "Horizontal Scrollbar Layer",
-      "position": [105, 404],
+      "position": [1, 301],
       "bounds": [300, 0],
-      "transform": 1
+      "transform": 4
     },
     {
       "name": "Vertical Scrollbar Layer",
-      "position": [405, 104],
+      "position": [301, 1],
       "bounds": [0, 300],
-      "transform": 1
+      "transform": 4
     }
   ],
   "transforms": [
@@ -149,19 +116,16 @@
         [0, 1, 0, 0],
         [0, 0, 1, 0],
         [0, -20, 0, 1]
-      ],
-      "flattenInheritedTransform": false
+      ]
     },
     {
       "id": 2,
-      "parent": 1,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [0, -30, 0, 1]
-      ],
-      "flattenInheritedTransform": false
+        [0, -20, 0, 1]
+      ]
     },
     {
       "id": 3,
@@ -170,13 +134,43 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [193, 181, 0, 1]
+        [40, 50, 0, 1]
       ]
     },
     {
       "id": 4,
       "parent": 3,
       "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [64, 53, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -30, 0, 1]
+      ]
+    },
+    {
+      "id": 6,
+      "parent": 5,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [89, 78, 0, 1]
+      ]
+    },
+    {
+      "id": 7,
+      "parent": 6,
+      "transform": [
         [3.53553390593274, 3.53553390593274, 0, 0],
         [-3.53553390593274, 3.53553390593274, 0, 0],
         [0, 0, 1, 0],
@@ -190,89 +184,56 @@
 var actual = {
   "layers": [
     {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
       "name": "Scrolling Contents Layer",
       "bounds": [800, 2016],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
+      "scrollPosition": [0, 20],
       "transform": 1
     },
     {
-      "name": "LayoutBlockFlow (positioned) DIV id='container'",
-      "position": [40, 50],
+      "name": "LayoutNGBlockFlow (positioned) DIV id='container'",
       "bounds": [100, 100],
       "backgroundColor": "#0000FF80",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow (relative positioned) DIV id='child1'",
+          "object": "LayoutNGBlockFlow (relative positioned) DIV id='child1'",
           "rect": [20, 20, 10, 10],
           "reason": "background"
         }
       ],
-      "transform": 1
+      "transform": 3
     },
     {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrollable'",
-      "position": [104, 103],
+      "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrollable'",
       "bounds": [302, 302],
-      "transform": 1
+      "transform": 4
     },
     {
-      "name": "Scrolling Layer",
-      "position": [105, 104],
-      "bounds": [300, 300],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [105, 104],
-      "bounds": [795, 1491],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='transform'",
+      "name": "LayoutNGBlockFlow (relative positioned) DIV id='transform'",
       "bounds": [200, 200],
       "contentsOpaque": true,
       "backgroundColor": "#FFFF00",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow (relative positioned) DIV id='child2'",
+          "object": "LayoutNGBlockFlow (relative positioned) DIV id='child2'",
           "rect": [20, 20, 10, 10],
           "reason": "background"
         }
       ],
-      "transform": 4
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [104, 103],
-      "bounds": [302, 302],
-      "drawsContent": false,
-      "transform": 1
+      "transform": 7
     },
     {
       "name": "Horizontal Scrollbar Layer",
-      "position": [105, 404],
+      "position": [1, 301],
       "bounds": [300, 0],
-      "transform": 1
+      "transform": 4
     },
     {
       "name": "Vertical Scrollbar Layer",
-      "position": [405, 104],
+      "position": [301, 1],
       "bounds": [0, 300],
-      "transform": 1
+      "transform": 4
     }
   ],
   "transforms": [
@@ -283,19 +244,16 @@
         [0, 1, 0, 0],
         [0, 0, 1, 0],
         [0, -20, 0, 1]
-      ],
-      "flattenInheritedTransform": false
+      ]
     },
     {
       "id": 2,
-      "parent": 1,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [0, -30, 0, 1]
-      ],
-      "flattenInheritedTransform": false
+        [0, -20, 0, 1]
+      ]
     },
     {
       "id": 3,
@@ -304,13 +262,43 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [193, 181, 0, 1]
+        [40, 50, 0, 1]
       ]
     },
     {
       "id": 4,
       "parent": 3,
       "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [64, 53, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -30, 0, 1]
+      ]
+    },
+    {
+      "id": 6,
+      "parent": 5,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [89, 78, 0, 1]
+      ]
+    },
+    {
+      "id": 7,
+      "parent": 6,
+      "transform": [
         [3.53553390593274, 3.53553390593274, 0, 0],
         [-3.53553390593274, 3.53553390593274, 0, 0],
         [0, 0, 1, 0],
diff --git a/third_party/blink/web_tests/paint/invalidation/resources/composited-iframe-scroll-repaint-iframe.html b/third_party/blink/web_tests/paint/invalidation/resources/composited-iframe-scroll-repaint-iframe.html
index 3ffdd6a..3ce722a 100644
--- a/third_party/blink/web_tests/paint/invalidation/resources/composited-iframe-scroll-repaint-iframe.html
+++ b/third_party/blink/web_tests/paint/invalidation/resources/composited-iframe-scroll-repaint-iframe.html
@@ -11,6 +11,6 @@
   document.documentElement.scrollTop = 20;
 }
 </script>
-<body onload="runRepaintTest()" style="transform: translateZ(0);">
+<body onload="runRepaintTest()" style="will-change: transform;">
 <div style="height:500px">
 
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child.html b/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child.html
index 3a32550..578ec68 100644
--- a/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child.html
+++ b/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child.html
@@ -40,7 +40,7 @@
 </style>
 </head>
 <body onload="runRepaintTest()">
-<div class="icon" style="transform: translateZ(0)"></div>
+<div class="icon" style="will-change: transform;"></div>
 <div class="scroller">
     <div class="list">
         <div class="commit">
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html b/third_party/blink/web_tests/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html
index 0e3c59e..1114fc2 100644
--- a/third_party/blink/web_tests/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html
+++ b/third_party/blink/web_tests/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html
@@ -15,7 +15,7 @@
     width: 600px;
     height: 600px;
     background-color: red;
-    transform: translateZ(0);
+    will-change: transform;
 }
 </style>
 <body onload="runRepaintAndPixelTest()">
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/resize-svg-invalidate-children-2.html b/third_party/blink/web_tests/paint/invalidation/svg/resize-svg-invalidate-children-2.html
index 5f422ee..46f0687f 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/resize-svg-invalidate-children-2.html
+++ b/third_party/blink/web_tests/paint/invalidation/svg/resize-svg-invalidate-children-2.html
@@ -10,7 +10,7 @@
 </script>
 <div id="target" style="width: 200px; height: 400px">
   <svg width='500' height='400' viewBox='0 0 500 400'
-       style='width: 100%; height: 100%; transform: translateZ(0)'>
+       style='width: 100%; height: 100%; will-change: transform;'>
     <rect width='500' height='400' fill='green'/>
   </svg>
 </div>
diff --git a/third_party/blink/web_tests/svg/custom/pattern-userSpaceOnUse-userToBaseTransform.xhtml b/third_party/blink/web_tests/svg/custom/pattern-userSpaceOnUse-userToBaseTransform.xhtml
index 25be65f..cdfd1a0fe 100644
--- a/third_party/blink/web_tests/svg/custom/pattern-userSpaceOnUse-userToBaseTransform.xhtml
+++ b/third_party/blink/web_tests/svg/custom/pattern-userSpaceOnUse-userToBaseTransform.xhtml
@@ -31,7 +31,7 @@
         </pattern>
     </defs>
 </svg>
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg" width="200" height="300" style="border: solid 1px black; transform: translateZ(0px); -moz-transform: translateZ(0px); -o-transform: translateZ(0px);">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg" width="200" height="300" style="border: solid 1px black; will-change: transform;">
     <text x="5" y="280">+Accelerated Compositing</text>
     <g>
         <rect x="0" y="100" width="100" height="100" fill="url(#pattern)"/>
diff --git a/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html b/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html
index e0fc6b3..73986d7 100644
--- a/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html
+++ b/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html
@@ -11,28 +11,38 @@
 promise_test(t => {
   window.testRunner.setPageVisibility('hidden');
   assert_true(document.hidden);
-  return promise_rejects(t, "NotAllowedError", WakeLock.request('screen'));
-}, "WakeLock.request('screen') fails when the document is hidden");
+  return promise_rejects(t, "NotAllowedError", navigator.wakeLock.request('screen'));
+}, "navigator.wakeLock.request('screen') fails when the document is hidden");
 
+// This test currently checks for Chromium-specific behavior: WakeLock::request()
+// performs an asynchronous permission request, which is why it is possible to
+// call navigator.wakeLock.request(), change page visibility later and still get
+// a NotAllowedError.
+// A more interoperable test would allow both |screenLock| to reject with
+// NotAllowedError as well as it resolving to a WakeLockSentinel that would fire
+// a "release" event upon page vsibility change.
 promise_test(t => {
   window.testRunner.setPageVisibility('visible');
 
-  const screenLock = WakeLock.request('screen');
+  const screenLock = navigator.wakeLock.request('screen');
   window.testRunner.setPageVisibility('hidden');
   assert_true(document.hidden);
   return promise_rejects(t, "NotAllowedError", screenLock);
-}, "WakeLock.request('screen') aborts when the page is hidden");
+}, "navigator.wakeLock.request('screen') aborts when the page is hidden");
 
 promise_test(async t => {
   window.testRunner.setPageVisibility('visible');
 
-  const controller = new AbortController();
-  const screenLock = WakeLock.request('screen', { signal: controller.signal });
+  const screenLock1 = await navigator.wakeLock.request('screen');
+  const screenLock2 = await navigator.wakeLock.request('screen');
+
+  const wait1 = new EventWatcher(t, screenLock1, 'release').wait_for('release');
+  const wait2 = new EventWatcher(t, screenLock2, 'release').wait_for('release');
+
   window.testRunner.setPageVisibility('hidden');
-  assert_true(document.hidden);
-  await promise_rejects(t, "NotAllowedError", screenLock);
-  controller.abort();
-}, "Aborting a rejected wake lock does not crash");
+
+  return Promise.all([wait1, wait2]);
+}, "Screen wake locks are released when the document the page is hidden");
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/wake-lock/wakelock-request-denied.html b/third_party/blink/web_tests/wake-lock/wakelock-request-denied.html
index adecbf0..2819e5ca 100644
--- a/third_party/blink/web_tests/wake-lock/wakelock-request-denied.html
+++ b/third_party/blink/web_tests/wake-lock/wakelock-request-denied.html
@@ -8,7 +8,7 @@
 
 promise_test(t => {
   self.testRunner.setPermission('wake-lock-screen', 'denied', location.origin, location.origin);
-  return promise_rejects(t, "NotAllowedError", WakeLock.request('screen'));
+  return promise_rejects(t, "NotAllowedError", navigator.wakeLock.request('screen'));
 }, 'Denied requests should abort with NotAllowedError');
 </script>
 </body>
diff --git a/third_party/blink/web_tests/wake-lock/wakelock-requestPermission.https.html b/third_party/blink/web_tests/wake-lock/wakelock-requestPermission.https.html
deleted file mode 100644
index be7df136..0000000
--- a/third_party/blink/web_tests/wake-lock/wakelock-requestPermission.https.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script>
-'use strict';
-
-promise_test(async t => {
-  self.testRunner.setPermission('wake-lock-screen', 'granted', location.origin, location.origin);
-  const status = await WakeLock.requestPermission('screen');
-  assert_equals(status, 'granted');
-}, 'WakeLock.requestPermission() returns "granted" for allowed requests');
-
-promise_test(async t => {
-  self.testRunner.setPermission('wake-lock-system', 'denied', location.origin, location.origin);
-  const status = await WakeLock.requestPermission('system');
-  assert_equals(status, 'denied');
-}, 'WakeLock.requestPermission() returns "denied" for blocked requests');
-</script>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index e6fff60..dd04540 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1515,9 +1515,20 @@
 [Worker]     getter isActive
 [Worker]     method constructor
 [Worker] interface WakeLock
-[Worker]     static method request
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
+[Worker]     method request
+[Worker] interface WakeLockEvent : Event
+[Worker]     attribute @@toStringTag
+[Worker]     getter lock
+[Worker]     method constructor
+[Worker] interface WakeLockSentinel : EventTarget
+[Worker]     attribute @@toStringTag
+[Worker]     getter onrelease
+[Worker]     getter type
+[Worker]     method constructor
+[Worker]     method release
+[Worker]     setter onrelease
 [Worker] interface WebGL2ComputeRenderingContext
 [Worker]     attribute @@toStringTag
 [Worker]     attribute ACTIVE_ATOMIC_COUNTER_BUFFERS
@@ -3794,6 +3805,7 @@
 [Worker]     getter storage
 [Worker]     getter usb
 [Worker]     getter userAgent
+[Worker]     getter wakeLock
 [Worker]     method constructor
 [Worker] interface WritableStream
 [Worker]     attribute @@toStringTag
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index fcfa531..5d9a5c1 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5206,6 +5206,7 @@
     getter userAgent
     getter vendor
     getter vendorSub
+    getter wakeLock
     getter webkitPersistentStorage
     getter webkitTemporaryStorage
     getter xr
@@ -8464,10 +8465,20 @@
     setter onresize
     setter onscroll
 interface WakeLock
-    static method request
-    static method requestPermission
     attribute @@toStringTag
     method constructor
+    method request
+interface WakeLockEvent : Event
+    attribute @@toStringTag
+    getter lock
+    method constructor
+interface WakeLockSentinel : EventTarget
+    attribute @@toStringTag
+    getter onrelease
+    getter type
+    method constructor
+    method release
+    setter onrelease
 interface WaveShaperNode : AudioNode
     attribute @@toStringTag
     getter curve
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index 1b87eaa..647debe 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -3643,6 +3643,7 @@
 [Worker]     getter storage
 [Worker]     getter usb
 [Worker]     getter userAgent
+[Worker]     getter wakeLock
 [Worker]     method constructor
 [Worker] interface WritableStream
 [Worker]     attribute @@toStringTag
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni
index 9fa9af1..56bc257 100644
--- a/third_party/boringssl/BUILD.generated.gni
+++ b/third_party/boringssl/BUILD.generated.gni
@@ -93,6 +93,7 @@
   "src/crypto/dsa/dsa.c",
   "src/crypto/dsa/dsa_asn1.c",
   "src/crypto/ec_extra/ec_asn1.c",
+  "src/crypto/ec_extra/ec_derive.c",
   "src/crypto/ecdh_extra/ecdh_extra.c",
   "src/crypto/ecdsa_extra/ecdsa_asn1.c",
   "src/crypto/engine/engine.c",
diff --git a/third_party/boringssl/linux-aarch64/crypto/chacha/chacha-armv8.S b/third_party/boringssl/linux-aarch64/crypto/chacha/chacha-armv8.S
index e05a265..49449bf5 100644
--- a/third_party/boringssl/linux-aarch64/crypto/chacha/chacha-armv8.S
+++ b/third_party/boringssl/linux-aarch64/crypto/chacha/chacha-armv8.S
@@ -1982,3 +1982,4 @@
 .size	ChaCha20_512_neon,.-ChaCha20_512_neon
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S
index 1680444..60c70a24 100644
--- a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S
+++ b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S
@@ -772,3 +772,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/armv8-mont.S b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/armv8-mont.S
index 1ea05ba9f..360bf4c7 100644
--- a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/armv8-mont.S
+++ b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/armv8-mont.S
@@ -1420,3 +1420,4 @@
 .align	4
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S
index 3567683..f876db3 100644
--- a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S
+++ b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S
@@ -338,3 +338,4 @@
 .align	2
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S
index 1267937..37d9731 100644
--- a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S
+++ b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S
@@ -246,3 +246,4 @@
 .align	2
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha1-armv8.S b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha1-armv8.S
index ecb4885..f681b99 100644
--- a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha1-armv8.S
+++ b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha1-armv8.S
@@ -1232,3 +1232,4 @@
 .hidden	OPENSSL_armcap_P
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha256-armv8.S b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha256-armv8.S
index b319688..6e09f69 100644
--- a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha256-armv8.S
+++ b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha256-armv8.S
@@ -1210,3 +1210,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha512-armv8.S b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha512-armv8.S
index 37e00d7..7b9b22a0 100644
--- a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha512-armv8.S
+++ b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha512-armv8.S
@@ -1082,3 +1082,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S
index 3a34209..f57b7b5 100644
--- a/third_party/boringssl/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S
+++ b/third_party/boringssl/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S
@@ -1213,3 +1213,4 @@
 .size	vpaes_ctr32_encrypt_blocks,.-vpaes_ctr32_encrypt_blocks
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/test/trampoline-armv8.S b/third_party/boringssl/linux-aarch64/crypto/test/trampoline-armv8.S
index f5296f6..9a21cc2 100644
--- a/third_party/boringssl/linux-aarch64/crypto/test/trampoline-armv8.S
+++ b/third_party/boringssl/linux-aarch64/crypto/test/trampoline-armv8.S
@@ -685,3 +685,4 @@
 .size	abi_test_clobber_v15_upper,.-abi_test_clobber_v15_upper
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-aarch64/crypto/third_party/sike/asm/fp-armv8.S b/third_party/boringssl/linux-aarch64/crypto/third_party/sike/asm/fp-armv8.S
index da49a40..63e8d1c 100644
--- a/third_party/boringssl/linux-aarch64/crypto/third_party/sike/asm/fp-armv8.S
+++ b/third_party/boringssl/linux-aarch64/crypto/third_party/sike/asm/fp-armv8.S
@@ -996,3 +996,4 @@
 	ret
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/chacha/chacha-armv4.S b/third_party/boringssl/linux-arm/crypto/chacha/chacha-armv4.S
index aed7ca6..363aeee5 100644
--- a/third_party/boringssl/linux-arm/crypto/chacha/chacha-armv4.S
+++ b/third_party/boringssl/linux-arm/crypto/chacha/chacha-armv4.S
@@ -1490,3 +1490,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/aes-armv4.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/aes-armv4.S
index b2966b4a..cfe2a36 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/aes-armv4.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/aes-armv4.S
@@ -1219,3 +1219,4 @@
 .align	2
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/aesv8-armx32.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/aesv8-armx32.S
index 3a2d2e4..5d6e22d 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/aesv8-armx32.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/aesv8-armx32.S
@@ -778,3 +778,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/armv4-mont.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/armv4-mont.S
index 12ebe40c..02968947 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/armv4-mont.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/armv4-mont.S
@@ -974,3 +974,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S
index f6cec3d..69a8fca 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S
@@ -1526,3 +1526,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/ghash-armv4.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/ghash-armv4.S
index a0fa53c..42cce58 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/ghash-armv4.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/ghash-armv4.S
@@ -588,3 +588,4 @@
 .align	2
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/ghashv8-armx32.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/ghashv8-armx32.S
index 65c9f22a..d684294 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/ghashv8-armx32.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/ghashv8-armx32.S
@@ -250,3 +250,4 @@
 .align	2
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/sha1-armv4-large.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/sha1-armv4-large.S
index 2b70a325..61deddf 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/sha1-armv4-large.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/sha1-armv4-large.S
@@ -1508,3 +1508,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/sha256-armv4.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/sha256-armv4.S
index 1928075..aee04785 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/sha256-armv4.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/sha256-armv4.S
@@ -2836,3 +2836,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/sha512-armv4.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/sha512-armv4.S
index c44fcc6..a06d41f 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/sha512-armv4.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/sha512-armv4.S
@@ -1891,3 +1891,4 @@
 #endif
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/fipsmodule/vpaes-armv7.S b/third_party/boringssl/linux-arm/crypto/fipsmodule/vpaes-armv7.S
index 9124ce2..e5ad6ed 100644
--- a/third_party/boringssl/linux-arm/crypto/fipsmodule/vpaes-armv7.S
+++ b/third_party/boringssl/linux-arm/crypto/fipsmodule/vpaes-armv7.S
@@ -1233,3 +1233,4 @@
 .size	vpaes_ctr32_encrypt_blocks,.-vpaes_ctr32_encrypt_blocks
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-arm/crypto/test/trampoline-armv4.S b/third_party/boringssl/linux-arm/crypto/test/trampoline-armv4.S
index e526e99..5c788b3 100644
--- a/third_party/boringssl/linux-arm/crypto/test/trampoline-armv4.S
+++ b/third_party/boringssl/linux-arm/crypto/test/trampoline-armv4.S
@@ -377,3 +377,4 @@
 .size	abi_test_clobber_d15,.-abi_test_clobber_d15
 #endif
 #endif  // !OPENSSL_NO_ASM
+.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/boringssl/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S b/third_party/boringssl/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S
index 911d6383..86b06fc 100644
--- a/third_party/boringssl/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S
+++ b/third_party/boringssl/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S
@@ -3667,3 +3667,4 @@
 .long	0
 .byte	0,12,0x14,0,0,0,0,0
 #endif  // !OPENSSL_NO_ASM && __powerpc64__
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S b/third_party/boringssl/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S
index 88a8a254..5b909a3 100644
--- a/third_party/boringssl/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S
+++ b/third_party/boringssl/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S
@@ -584,3 +584,4 @@
 .align	2
 .align	2
 #endif  // !OPENSSL_NO_ASM && __powerpc64__
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/chacha/chacha-x86.S b/third_party/boringssl/linux-x86/crypto/chacha/chacha-x86.S
index 287b62a..feceb5d9 100644
--- a/third_party/boringssl/linux-x86/crypto/chacha/chacha-x86.S
+++ b/third_party/boringssl/linux-x86/crypto/chacha/chacha-x86.S
@@ -972,3 +972,4 @@
 .byte	60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111
 .byte	114,103,62,0
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/aes-586.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/aes-586.S
index c8eeee53..e43cfea 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/aes-586.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/aes-586.S
@@ -3260,3 +3260,4 @@
 .byte	80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114
 .byte	111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/aesni-x86.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/aesni-x86.S
index 671c79e..a418869 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/aesni-x86.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/aesni-x86.S
@@ -2510,3 +2510,4 @@
 .byte	32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115
 .byte	115,108,46,111,114,103,62,0
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/bn-586.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/bn-586.S
index 64e36ce..4a6ccfb 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/bn-586.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/bn-586.S
@@ -1541,3 +1541,4 @@
 	ret
 .size	bn_sub_part_words,.-.L_bn_sub_part_words_begin
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/co-586.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/co-586.S
index b617d81a2..837b0cb 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/co-586.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/co-586.S
@@ -1263,3 +1263,4 @@
 	ret
 .size	bn_sqr_comba4,.-.L_bn_sqr_comba4_begin
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S
index 7aa0ea5..3e5f2d7e 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S
@@ -291,3 +291,4 @@
 .Llow4_mask:
 .long	252645135,252645135,252645135,252645135
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-x86.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-x86.S
index e183078..7016235 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-x86.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-x86.S
@@ -1072,3 +1072,4 @@
 .byte	112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62
 .byte	0
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/md5-586.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/md5-586.S
index cc0dcd8..6de8ff8 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/md5-586.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/md5-586.S
@@ -685,3 +685,4 @@
 	ret
 .size	md5_block_asm_data_order,.-.L_md5_block_asm_data_order_begin
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/sha1-586.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/sha1-586.S
index 4df4d06..4449e38 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/sha1-586.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/sha1-586.S
@@ -3805,3 +3805,4 @@
 .byte	89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112
 .byte	114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/sha256-586.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/sha256-586.S
index 39d57786..f61fa3df 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/sha256-586.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/sha256-586.S
@@ -5564,3 +5564,4 @@
 	ret
 .size	sha256_block_data_order,.-.L_sha256_block_data_order_begin
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/sha512-586.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/sha512-586.S
index c8dd6770..89fb50b 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/sha512-586.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/sha512-586.S
@@ -2834,3 +2834,4 @@
 .byte	112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103
 .byte	62,0
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/vpaes-x86.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/vpaes-x86.S
index 7200cfde..8807116 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/vpaes-x86.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/vpaes-x86.S
@@ -705,3 +705,4 @@
 	ret
 .size	vpaes_cbc_encrypt,.-.L_vpaes_cbc_encrypt_begin
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/fipsmodule/x86-mont.S b/third_party/boringssl/linux-x86/crypto/fipsmodule/x86-mont.S
index 9924c02..f2c6fde 100644
--- a/third_party/boringssl/linux-x86/crypto/fipsmodule/x86-mont.S
+++ b/third_party/boringssl/linux-x86/crypto/fipsmodule/x86-mont.S
@@ -481,3 +481,4 @@
 .byte	32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46
 .byte	111,114,103,62,0
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86/crypto/test/trampoline-x86.S b/third_party/boringssl/linux-x86/crypto/test/trampoline-x86.S
index 2222347a..13eb677 100644
--- a/third_party/boringssl/linux-x86/crypto/test/trampoline-x86.S
+++ b/third_party/boringssl/linux-x86/crypto/test/trampoline-x86.S
@@ -203,3 +203,4 @@
 	ret
 .size	abi_test_clobber_xmm7,.-.L_abi_test_clobber_xmm7_begin
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/chacha/chacha-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/chacha/chacha-x86_64.S
index 4e2267b..b7671339 100644
--- a/third_party/boringssl/linux-x86_64/crypto/chacha/chacha-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/chacha/chacha-x86_64.S
@@ -1630,3 +1630,4 @@
 .cfi_endproc	
 .size	ChaCha20_8x,.-ChaCha20_8x
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S
index 3eb1688..a22bee8f 100644
--- a/third_party/boringssl/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S
@@ -3076,3 +3076,4 @@
 .cfi_endproc	
 .size	aes256gcmsiv_kdf, .-aes256gcmsiv_kdf
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S b/third_party/boringssl/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S
index 677335b..e313348 100644
--- a/third_party/boringssl/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S
@@ -8984,3 +8984,4 @@
 	jmp	seal_sse_tail_16
 .cfi_endproc	
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aes-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aes-x86_64.S
index f45e010..47a69ec8 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aes-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aes-x86_64.S
@@ -2662,3 +2662,4 @@
 .byte	65,69,83,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
index 98365a87..65ab5c78 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
@@ -849,3 +849,4 @@
 .byte	65,69,83,45,78,73,32,71,67,77,32,109,111,100,117,108,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S
index de309533..b98107f3 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S
@@ -2503,3 +2503,4 @@
 .byte	65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69,83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S
index ecf5b66..a44790b 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S
@@ -424,3 +424,4 @@
 .Llow4_mask:
 .quad	0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S
index 0b36afa..674e2da 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S
@@ -1869,3 +1869,4 @@
 .byte	71,72,65,83,72,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/md5-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/md5-x86_64.S
index 18e2e92..04aaf057 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/md5-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/md5-x86_64.S
@@ -699,3 +699,4 @@
 .cfi_endproc	
 .size	md5_block_asm_data_order,.-md5_block_asm_data_order
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S
index 067575e..85f4899 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S
@@ -4540,3 +4540,4 @@
 .cfi_endproc	
 .size	ecp_nistz256_point_add_affinex,.-ecp_nistz256_point_add_affinex
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S
index 5dfecc8..d072a834 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S
@@ -340,3 +340,4 @@
 
 .size	beeu_mod_inverse_vartime, .-beeu_mod_inverse_vartime
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S
index fefccd6f..18d66f6 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S
@@ -60,3 +60,4 @@
 .cfi_endproc	
 .size	CRYPTO_rdrand_multiple8_buf,.-CRYPTO_rdrand_multiple8_buf
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S
index 579c7055..faccd48 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S
@@ -1746,3 +1746,4 @@
 .long	4,4,4,4, 4,4,4,4
 .align	64
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S
index 044f36f0..a4ce81f 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S
@@ -3598,3 +3598,4 @@
 .byte	83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S
index 55b540f..0bacd6a 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S
@@ -3970,3 +3970,4 @@
 .cfi_endproc	
 .size	sha256_block_data_order_avx,.-sha256_block_data_order_avx
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S
index 509e144..afc47f1 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S
@@ -2989,3 +2989,4 @@
 .cfi_endproc	
 .size	sha512_block_data_order_avx,.-sha512_block_data_order_avx
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S
index 8546d0d..27a3461 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S
@@ -1130,3 +1130,4 @@
 .align	64
 .size	_vpaes_consts,.-_vpaes_consts
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont.S
index f3637f0..bdb4454 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont.S
@@ -1257,3 +1257,4 @@
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	16
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S
index b12393e..c86b3b0 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S
@@ -3787,3 +3787,4 @@
 .long	2,2, 2,2
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,115,99,97,116,116,101,114,47,103,97,116,104,101,114,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/test/trampoline-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/test/trampoline-x86_64.S
index 91a13f3..9f7c0d8 100644
--- a/third_party/boringssl/linux-x86_64/crypto/test/trampoline-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/test/trampoline-x86_64.S
@@ -515,3 +515,4 @@
 	.byte	0xf3,0xc3
 .size	abi_test_set_direction_flag,.-abi_test_set_direction_flag
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/boringssl/linux-x86_64/crypto/third_party/sike/asm/fp-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/third_party/sike/asm/fp-x86_64.S
index 4b3c9254..07f708a 100644
--- a/third_party/boringssl/linux-x86_64/crypto/third_party/sike/asm/fp-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/third_party/sike/asm/fp-x86_64.S
@@ -1868,3 +1868,4 @@
 	.byte	0xf3,0xc3
 .cfi_endproc	
 #endif
+.section	.note.GNU-stack,"",@progbits
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index af60a1b6..2edb025 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -2144,15 +2144,11 @@
 
     # Settings used by the codesearch builders to generate cross-references.
     'codesearch': {
-      'gn_args': ('clang_use_chrome_plugins=false '
-                  'enable_kythe_annotations=true '
-                  'is_chrome_branded=true'),
+      'gn_args': 'clang_use_chrome_plugins=false enable_kythe_annotations=true',
       'mixins': ['goma', 'clang', 'shared', 'debug', 'minimal_symbols'],
     },
     'codesearch_release': {
-      'gn_args': ('clang_use_chrome_plugins=false '
-                  'enable_kythe_annotations=true '
-                  'is_chrome_branded=true'),
+      'gn_args': 'clang_use_chrome_plugins=false enable_kythe_annotations=true',
       'mixins': ['release', 'static', 'goma'],
     },
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index f07863a7..0db61b5 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -18292,6 +18292,7 @@
   <int value="625" label="PrintJobHistoryExpirationPeriod"/>
   <int value="626" label="TLS13HardeningForLocalAnchorsEnabled"/>
   <int value="627" label="ForceDisableAudioSandbox"/>
+  <int value="628" label="DeviceLoginScreenScreenMagnifierType"/>
 </enum>
 
 <enum name="EnterprisePolicyInvalidations">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index a351b09f..c8ec672 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -58481,7 +58481,11 @@
 </histogram>
 
 <histogram name="LibraryLoader.PrefetchDetailedStatus"
-    enum="LibraryLoaderPrefetchDetailedStatus" expires_after="2020-04-05">
+    enum="LibraryLoaderPrefetchDetailedStatus" expires_after="M79">
+  <obsolete>
+    Removed 2019-10. The code has stabilized, the failure rate is 0.04% on
+    Stable.
+  </obsolete>
   <owner>lizeb@chromium.org</owner>
   <owner>pasko@chromium.org</owner>
   <summary>
@@ -58491,8 +58495,10 @@
   </summary>
 </histogram>
 
-<histogram name="LibraryLoader.PrefetchStatus" enum="BooleanSuccess"
-    expires_after="M79">
+<histogram name="LibraryLoader.PrefetchStatus" enum="BooleanSuccess">
+  <obsolete>
+    Deprecated 2019-10. No longer recorded.
+  </obsolete>
   <owner>lizeb@chromium.org</owner>
   <owner>pasko@chromium.org</owner>
   <summary>
@@ -103825,6 +103831,17 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordProtection.SampleReportSent" units="Boolean"
+    expires_after="2020-08-05">
+  <owner>bdea@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <summary>
+    Logs when an event where users reuse their password or focus on a password
+    field is sent as a sample ping when the URL in the allowlist to Safe
+    Browsing. Events only happen 1% of the time when URLs match the allowlist.
+  </summary>
+</histogram>
+
 <histogram name="PasswordProtection.UnfamiliarLoginPageVerdict"
     enum="PasswordProtectionVerdict" expires_after="2017-05-16">
   <obsolete>
diff --git a/tools/perf/contrib/oilpan/OWNERS b/tools/perf/contrib/oilpan/OWNERS
deleted file mode 100644
index 2789dd3..0000000
--- a/tools/perf/contrib/oilpan/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-haraken@chromium.org
-peria@chromium.org
diff --git a/tools/perf/contrib/oilpan/__init__.py b/tools/perf/contrib/oilpan/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/contrib/oilpan/__init__.py
+++ /dev/null
diff --git a/tools/perf/contrib/oilpan/oilpan_benchmarks.py b/tools/perf/contrib/oilpan/oilpan_benchmarks.py
deleted file mode 100644
index bf0e703..0000000
--- a/tools/perf/contrib/oilpan/oilpan_benchmarks.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import os
-
-from core import perf_benchmark
-
-from benchmarks import blink_perf
-from benchmarks import silk_flags
-
-from telemetry import benchmark
-from telemetry import story
-
-import page_sets
-
-from contrib.oilpan import oilpan_gc_times
-
-
-class OilpanGCTimesBlinkPerfStress(perf_benchmark.PerfBenchmark):
-  tag = 'blink_perf_stress'
-  test = oilpan_gc_times.OilpanGCTimesForInternals
-
-  @classmethod
-  def Name(cls):
-    return 'oilpan_gc_times.blink_perf_stress'
-
-  def CreateStorySet(self, options):
-    path = os.path.join(blink_perf.BLINK_PERF_BASE_DIR, 'blink_gc')
-    return blink_perf.CreateStorySetFromPath(path, blink_perf.SKIPPED_FILE)
-
-
-@benchmark.Info(emails=['peria@chromium.org'])
-class OilpanGCTimesSmoothnessAnimation(perf_benchmark.PerfBenchmark):
-  test = oilpan_gc_times.OilpanGCTimesForSmoothness
-  page_set = page_sets.ToughAnimationCasesPageSet
-
-  @classmethod
-  def Name(cls):
-    return 'oilpan_gc_times.tough_animation_cases'
-
-
-class OilpanGCTimesKeySilkCases(perf_benchmark.PerfBenchmark):
-  test = oilpan_gc_times.OilpanGCTimesForSmoothness
-  page_set = page_sets.KeySilkCasesPageSet
-  SUPPORTED_PLATFORMS = [story.expectations.ALL_ANDROID]
-
-  @classmethod
-  def Name(cls):
-    return 'oilpan_gc_times.key_silk_cases'
-
-
-class OilpanGCTimesSyncScrollKeyMobileSites(perf_benchmark.PerfBenchmark):
-  tag = 'sync_scroll'
-  test = oilpan_gc_times.OilpanGCTimesForSmoothness
-  page_set = page_sets.KeyMobileSitesSmoothPageSet
-  SUPPORTED_PLATFORMS = [story.expectations.ALL_ANDROID]
-
-  def SetExtraBrowserOptions(self, options):
-    silk_flags.CustomizeBrowserOptionsForSyncScrolling(options)
-
-  @classmethod
-  def Name(cls):
-    return 'oilpan_gc_times.sync_scroll.key_mobile_sites_smooth'
diff --git a/tools/perf/contrib/oilpan/oilpan_gc_times.py b/tools/perf/contrib/oilpan/oilpan_gc_times.py
deleted file mode 100644
index 4e27837..0000000
--- a/tools/perf/contrib/oilpan/oilpan_gc_times.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import os
-
-from telemetry.page import legacy_page_test
-from telemetry.timeline.model import TimelineModel
-from telemetry.timeline import tracing_config
-
-
-_CR_RENDERER_MAIN = 'CrRendererMain'
-_RUN_SMOOTH_ACTIONS = 'RunSmoothAllActions'
-
-
-def _AddTracingResults(thread, results):
-  _GC_REASONS = ['precise', 'conservative', 'idle', 'forced']
-  _GC_STAGES = ['mark', 'lazy_sweep', 'complete_sweep']
-
-  def GetGcReason(event, async_slices):
-    args = event.args
-
-    # Old format
-    if 'precise' in args:
-      if args['forced']:
-        return 'forced'
-      return 'precise' if args['precise'] else 'conservative'
-    if args['gcReason'] == 'ConservativeGC':
-      return 'conservative'
-    if args['gcReason'] == 'PreciseGC':
-      return 'precise'
-    if args['gcReason'] == 'ForcedGCForTesting':
-      for s in async_slices:
-        if s.start <= event.start and event.end <= s.end:
-          return 'forced'
-      # Ignore this forced GC being out of target ranges
-      return None
-    if args['gcReason'] == 'IdleGC':
-      return 'idle'
-    return None  # Unknown
-
-  def DumpMetric(name, values, unit):
-    if values[name]:
-      results.AddMeasurement(name, unit, values[name])
-      results.AddMeasurement(name + '_max', unit, max(values[name]))
-      results.AddMeasurement(name + '_total', unit, sum(values[name]))
-
-  events = thread.all_slices
-  async_slices = [s for s in thread.async_slices
-                  if s.name == 'BlinkGCTimeMeasurement']
-
-  # Prepare
-  values = {}
-  for reason in _GC_REASONS:
-    for stage in _GC_STAGES:
-      values['oilpan_%s_%s' % (reason, stage)] = []
-
-  # Parse trace events
-  reason = None
-  mark_time = 0
-  lazy_sweep_time = 0
-  complete_sweep_time = 0
-  for event in events:
-    duration = event.thread_duration or event.duration
-    if event.name == 'BlinkGC.AtomicPhaseMarking':
-      if reason is not None:
-        values['oilpan_%s_mark' % reason].append(mark_time)
-        values['oilpan_%s_lazy_sweep' % reason].append(lazy_sweep_time)
-        values['oilpan_%s_complete_sweep' % reason].append(complete_sweep_time)
-
-      reason = GetGcReason(event, async_slices)
-      mark_time = duration
-      lazy_sweep_time = 0
-      complete_sweep_time = 0
-      continue
-    if event.name == 'BlinkGC.LazySweepInIdle':
-      lazy_sweep_time += duration
-      continue
-    if event.name == 'BlinkGC.CompleteSweep':
-      complete_sweep_time += duration
-      continue
-
-  if reason is not None:
-    values['oilpan_%s_mark' % reason].append(mark_time)
-    values['oilpan_%s_lazy_sweep' % reason].append(lazy_sweep_time)
-    values['oilpan_%s_complete_sweep' % reason].append(complete_sweep_time)
-
-  unit = 'ms'
-
-  # Dump each metric
-  for reason in _GC_REASONS:
-    for stage in _GC_STAGES:
-      DumpMetric('oilpan_%s_%s' % (reason, stage), values, unit)
-
-  # Summarize each stage
-  for stage in _GC_STAGES:
-    total_time = 0
-    for reason in _GC_REASONS:
-      total_time += sum(values['oilpan_%s_%s' % (reason, stage)])
-    results.AddMeasurement('oilpan_%s' % stage, unit, total_time)
-
-  # Summarize sweeping time
-  total_sweep_time = 0
-  for stage in ['lazy_sweep', 'complete_sweep']:
-    sweep_time = 0
-    for reason in _GC_REASONS:
-      sweep_time += sum(values['oilpan_%s_%s' % (reason, stage)])
-    key = 'oilpan_%s' % stage
-    results.AddMeasurement(key, unit, sweep_time)
-    total_sweep_time += sweep_time
-  results.AddMeasurement('oilpan_sweep', unit, total_sweep_time)
-
-  gc_time = 0
-  for key in values:
-    gc_time += sum(values[key])
-  results.AddMeasurement('oilpan_gc', unit, gc_time)
-
-
-class _OilpanGCTimesBase(legacy_page_test.LegacyPageTest):
-
-  def WillNavigateToPage(self, page, tab):
-    del page  # unused
-    # FIXME: Remove webkit.console when blink.console lands in chromium and
-    # the ref builds are updated. crbug.com/386847
-    config = tracing_config.TracingConfig()
-    for c in ['webkit.console', 'blink.console', 'blink_gc']:
-      config.chrome_trace_config.category_filter.AddIncludedCategory(c)
-    config.enable_chrome_trace = True
-    tab.browser.platform.tracing_controller.StartTracing(config, timeout=1000)
-
-  def ValidateAndMeasurePage(self, page, tab, results):
-    del page  # unused
-    timeline_data = tab.browser.platform.tracing_controller.StopTracing()
-    timeline_model = TimelineModel(timeline_data)
-    threads = timeline_model.GetAllThreads()
-    for thread in threads:
-      if thread.name == _CR_RENDERER_MAIN:
-        _AddTracingResults(thread, results)
-
-  def DidRunPage(self, platform):
-    if platform.tracing_controller.is_tracing_running:
-      platform.tracing_controller.StopTracing()
-
-
-class OilpanGCTimesForSmoothness(_OilpanGCTimesBase):
-
-  def __init__(self):
-    super(OilpanGCTimesForSmoothness, self).__init__()
-    self._interaction = None
-
-  def DidNavigateToPage(self, page, tab):
-    del page  # unused
-    self._interaction = tab.action_runner.CreateInteraction(_RUN_SMOOTH_ACTIONS)
-    self._interaction.Begin()
-
-  def ValidateAndMeasurePage(self, page, tab, results):
-    self._interaction.End()
-    super(OilpanGCTimesForSmoothness, self).ValidateAndMeasurePage(
-        page, tab, results)
-
-
-class OilpanGCTimesForBlinkPerf(_OilpanGCTimesBase):
-
-  def __init__(self):
-    super(OilpanGCTimesForBlinkPerf, self).__init__()
-    with open(os.path.join(os.path.dirname(__file__), '..', '..', 'benchmarks',
-                           'blink_perf.js'), 'r') as f:
-      self._blink_perf_js = f.read()
-
-  def WillNavigateToPage(self, page, tab):
-    page.script_to_evaluate_on_commit = self._blink_perf_js
-    super(OilpanGCTimesForBlinkPerf, self).WillNavigateToPage(page, tab)
-
-  def ValidateAndMeasurePage(self, page, tab, results):
-    tab.WaitForJavaScriptCondition('testRunner.isDone', timeout=600)
-    super(OilpanGCTimesForBlinkPerf, self).ValidateAndMeasurePage(
-        page, tab, results)
-
-
-class OilpanGCTimesForInternals(OilpanGCTimesForBlinkPerf):
-
-  def __init__(self):
-    super(OilpanGCTimesForInternals, self).__init__()
-
-  @classmethod
-  def CustomizeBrowserOptions(cls, options):
-    # 'expose-internals-for-testing' can be enabled on content shell.
-    assert 'content-shell' in options.browser_type
-    options.AppendExtraBrowserArgs(['--expose-internals-for-testing',
-                                    '--js-flags=--expose-gc'])
diff --git a/tools/perf/contrib/oilpan/oilpan_gc_times_unittest.py b/tools/perf/contrib/oilpan/oilpan_gc_times_unittest.py
deleted file mode 100644
index 1dc9339..0000000
--- a/tools/perf/contrib/oilpan/oilpan_gc_times_unittest.py
+++ /dev/null
@@ -1,277 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import shutil
-import tempfile
-
-from contrib.oilpan import oilpan_gc_times
-
-from telemetry import decorators
-from telemetry.internal.results import page_test_results
-from telemetry.page import page as page_module
-from telemetry.testing import options_for_unittests
-from telemetry.testing import page_test_test_case
-from telemetry.timeline import model
-from telemetry.timeline import slice as slice_data
-
-import mock  # pylint: disable=import-error
-
-
-class TestOilpanGCTimesPage(page_module.Page):
-
-  def __init__(self, page_set):
-    super(TestOilpanGCTimesPage, self).__init__(
-        'file://blank.html', page_set, page_set.base_dir, name='blank.html')
-
-  def RunPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction'):
-      action_runner.ScrollPage()
-
-
-class OilpanGCTimesTestData(object):
-
-  def __init__(self, page, thread_name):
-    self._page = page
-    self._model = model.TimelineModel()
-    self._renderer_process = self._model.GetOrCreateProcess(1)
-    self._renderer_thread = self._renderer_process.GetOrCreateThread(2)
-    self._renderer_thread.name = thread_name
-
-  def AddSlice(self, name, timestamp, duration, args):
-    new_slice = slice_data.Slice(
-        None,
-        'category',
-        name,
-        timestamp,
-        duration,
-        timestamp,
-        duration,
-        args)
-    self._renderer_thread.all_slices.append(new_slice)
-    return new_slice
-
-  def AddAsyncSlice(self, name, timestamp, duration, args):
-    new_slice = slice_data.Slice(
-        None,
-        'category',
-        name,
-        timestamp,
-        duration,
-        timestamp,
-        duration,
-        args)
-    self._renderer_thread.async_slices.append(new_slice)
-    return new_slice
-
-  def RunMeasurement(self):
-    # pylint: disable=protected-access
-    measurement = oilpan_gc_times._OilpanGCTimesBase()
-    results = page_test_results.PageTestResults()
-    tab = mock.MagicMock()
-    with mock.patch(
-        'contrib.oilpan.oilpan_gc_times.TimelineModel') as MockTimelineModel:
-      MockTimelineModel.return_value = self._model
-      results.WillRunPage(self._page)
-      try:
-        measurement.ValidateAndMeasurePage(self._page, tab, results)
-      finally:
-        results.DidRunPage(self._page)
-    return results
-
-
-class OilpanGCTimesTest(page_test_test_case.PageTestTestCase):
-  """Smoke test for Oilpan GC pause time measurements.
-
-     Runs OilpanGCTimes measurement on some simple pages and verifies
-     that all metrics were added to the results.  The test is purely functional,
-     i.e. it only checks if the metrics are present and non-zero.
-  """
-  _KEY_MARK = 'BlinkGC.AtomicPhaseMarking'
-  _KEY_LAZY_SWEEP = 'BlinkGC.LazySweepInIdle'
-  _KEY_COMPLETE_SWEEP = 'BlinkGC.CompleteSweep'
-  _KEY_MEASURE = 'BlinkGCTimeMeasurement'
-  # Do not add 'forced' in reasons to measure.
-  _GC_REASONS = ['precise', 'conservative', 'idle']
-
-  def setUp(self):
-    self._options = options_for_unittests.GetRunOptions(
-        output_dir=tempfile.mkdtemp())
-
-  def tearDowmn(self):
-    shutil.rmtree(self._options.output_dir)
-
-  # Disable for accessing private API of _OilpanGCTimesBase.
-  # pylint: disable=protected-access
-  @decorators.Disabled('all')  # crbug.com/1011787
-  def testForParsingOldFormat(self):
-    def getMetric(results, name):
-      metrics = results.FindAllPageSpecificValuesNamed(name)
-      self.assertEquals(1, len(metrics))
-      return metrics[0].values
-
-    data = self._GenerateDataForParsingOldFormat()
-    results = data.RunMeasurement()
-    self.assertEquals(3, len(getMetric(results, 'oilpan_precise_mark')))
-    self.assertEquals(3, len(getMetric(results, 'oilpan_precise_lazy_sweep')))
-    self.assertEquals(3, len(getMetric(results,
-                                       'oilpan_precise_complete_sweep')))
-    self.assertEquals(1, len(getMetric(results, 'oilpan_conservative_mark')))
-    self.assertEquals(1, len(getMetric(results,
-                                       'oilpan_conservative_lazy_sweep')))
-    self.assertEquals(1, len(getMetric(results,
-                                       'oilpan_conservative_complete_sweep')))
-    self.assertEquals(2, len(getMetric(results, 'oilpan_forced_mark')))
-    self.assertEquals(2, len(getMetric(results, 'oilpan_forced_lazy_sweep')))
-    self.assertEquals(2, len(getMetric(results,
-                                       'oilpan_forced_complete_sweep')))
-
-  # Disable for accessing private API of _OilpanGCTimesBase.
-  # pylint: disable=protected-access
-  @decorators.Disabled('all')  # crbug.com/1011787
-  def testForParsing(self):
-    def getMetric(results, name):
-      metrics = results.FindAllPageSpecificValuesNamed(name)
-      self.assertEquals(1, len(metrics))
-      return metrics[0].values
-
-    data = self._GenerateDataForParsing()
-    results = data.RunMeasurement()
-    self.assertEquals(4, len(getMetric(results, 'oilpan_precise_mark')))
-    self.assertEquals(4, len(getMetric(results, 'oilpan_precise_lazy_sweep')))
-    self.assertEquals(4, len(getMetric(results,
-                                       'oilpan_precise_complete_sweep')))
-    self.assertEquals(5, len(getMetric(results, 'oilpan_conservative_mark')))
-    self.assertEquals(5, len(getMetric(results,
-                                       'oilpan_conservative_lazy_sweep')))
-    self.assertEquals(5, len(getMetric(results,
-                                       'oilpan_conservative_complete_sweep')))
-    self.assertEquals(1, len(getMetric(results, 'oilpan_forced_mark')))
-    self.assertEquals(1, len(getMetric(results, 'oilpan_forced_lazy_sweep')))
-    self.assertEquals(1, len(getMetric(results,
-                                       'oilpan_forced_complete_sweep')))
-    self.assertEquals(2, len(getMetric(results, 'oilpan_idle_mark')))
-    self.assertEquals(2, len(getMetric(results, 'oilpan_idle_lazy_sweep')))
-    self.assertEquals(2, len(getMetric(results,
-                                       'oilpan_idle_complete_sweep')))
-
-  @decorators.Disabled('all')
-  def testForSmoothness(self):
-    story_set = self.CreateStorySetFromFileInUnittestDataDir(
-        'create_many_objects.html')
-    measurement = oilpan_gc_times.OilpanGCTimesForSmoothness()
-    results = self.RunMeasurement(
-        measurement, story_set, run_options=self._options)
-    self.assertFalse(results.had_failures)
-
-    gc_events = []
-    for gc_reason in self._GC_REASONS:
-      label = 'oilpan_%s_mark' % gc_reason
-      gc_events.extend(results.FindAllPageSpecificValuesNamed(label))
-    self.assertLess(0, len(gc_events))
-
-  @decorators.Disabled('all')
-  def testForBlinkPerf(self):
-    story_set = self.CreateStorySetFromFileInUnittestDataDir(
-        'create_many_objects.html')
-    measurement = oilpan_gc_times.OilpanGCTimesForBlinkPerf()
-    results = self.RunMeasurement(
-        measurement, story_set, run_options=self._options)
-    self.assertFalse(results.had_failures)
-
-    gc_events = []
-    for gc_reason in self._GC_REASONS:
-      label = 'oilpan_%s_mark' % gc_reason
-      gc_events.extend(results.FindAllPageSpecificValuesNamed(label))
-    self.assertLess(0, len(gc_events))
-
-  def _GenerateDataForEmptyPageSet(self):
-    page_set = self.CreateEmptyPageSet()
-    page = TestOilpanGCTimesPage(page_set)
-    page_set.AddStory(page)
-
-    return OilpanGCTimesTestData(page, 'CrRendererMain')
-
-  def _GenerateDataForParsingOldFormat(self):
-    data = self._GenerateDataForEmptyPageSet()
-    data.AddSlice(self._KEY_MARK, 1, 1, {'precise': True, 'forced': False})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 2, 2, {})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 7, 4, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 16, 6, {})
-    data.AddSlice(self._KEY_MARK, 22, 7, {'precise': True, 'forced': False})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 29, 8, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 46, 10, {})
-    data.AddSlice(self._KEY_MARK, 56, 11, {'precise': False, 'forced': False})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 67, 12, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 92, 14, {})
-    data.AddSlice(self._KEY_MARK, 106, 15, {'precise': True, 'forced': False})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 121, 16, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 154, 18, {})
-    data.AddSlice(self._KEY_MARK, 172, 19, {'precise': False, 'forced': True})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 211, 21, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 232, 22, {})
-    data.AddSlice(self._KEY_MARK, 254, 23, {'precise': True, 'forced': True})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 301, 25, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 326, 26, {})
-    return data
-
-  def _GenerateDataForParsing(self):
-    data = self._GenerateDataForEmptyPageSet()
-    data.AddSlice(self._KEY_MARK, 1, 1,
-                  {'lazySweeping': True, 'gcReason': 'ConservativeGC'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 2, 2, {})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 7, 4, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 16, 6, {})
-    data.AddSlice(self._KEY_MARK, 22, 7,
-                  {'lazySweeping': True, 'gcReason': 'PreciseGC'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 29, 8, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 46, 10, {})
-    data.AddSlice(self._KEY_MARK, 56, 11,
-                  {'lazySweeping': False, 'gcReason': 'ConservativeGC'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 67, 12, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 92, 14, {})
-    data.AddSlice(self._KEY_MARK, 106, 15,
-                  {'lazySweeping': False, 'gcReason': 'PreciseGC'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 121, 16, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 154, 18, {})
-    data.AddSlice(self._KEY_MARK, 172, 19,
-                  {'lazySweeping': False, 'gcReason': 'ForcedGCForTesting'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 211, 21, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 232, 22, {})
-    data.AddSlice(self._KEY_MARK, 254, 23,
-                  {'lazySweeping': False, 'gcReason': 'IdleGC'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 301, 25, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 326, 26, {})
-
-    # Following events are covered with 'BlinkGCTimeMeasurement' event.
-    first_measure = data.AddSlice(self._KEY_MARK, 352, 27,
-        {'lazySweeping': False, 'gcReason': 'ConservativeGC'})
-    data.AddSlice(self._KEY_MARK, 380, 28,
-                  {'lazySweeping': True, 'gcReason': 'ConservativeGC'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 408, 29, {})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 437, 30, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 467, 31, {})
-    data.AddSlice(self._KEY_MARK, 498, 32,
-                  {'lazySweeping': True, 'gcReason': 'PreciseGC'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 530, 33, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 563, 34, {})
-    data.AddSlice(self._KEY_MARK, 597, 35,
-                  {'lazySweeping': False, 'gcReason': 'ConservativeGC'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 632, 36, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 667, 37, {})
-    data.AddSlice(self._KEY_MARK, 704, 38,
-                  {'lazySweeping': False, 'gcReason': 'PreciseGC'})
-    data.AddSlice(self._KEY_LAZY_SWEEP, 742, 39, {})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 781, 40, {})
-    data.AddSlice(self._KEY_MARK, 821, 41,
-                  {'lazySweeping': False, 'gcReason': 'ForcedGCForTesting'})
-    data.AddSlice(self._KEY_COMPLETE_SWEEP, 862, 42, {})
-    data.AddSlice(self._KEY_MARK, 904, 43,
-                  {'lazySweeping': False, 'gcReason': 'IdleGC'})
-    last_measure = data.AddSlice(self._KEY_COMPLETE_SWEEP, 947, 44, {})
-
-    # Async event
-    async_dur = last_measure.end - first_measure.start
-    data.AddAsyncSlice(self._KEY_MEASURE, first_measure.start, async_dur, {})
-
-    return data
diff --git a/tools/perf/core/results_processor/processor.py b/tools/perf/core/results_processor/processor.py
index d16a0c7..4e22cd5f 100644
--- a/tools/perf/core/results_processor/processor.py
+++ b/tools/perf/core/results_processor/processor.py
@@ -20,6 +20,7 @@
 from core.results_processor import formatters
 from core.results_processor import util
 
+from tracing.trace_data import trace_data
 from tracing.value.diagnostics import generic_set
 from tracing.value.diagnostics import reserved_infos
 from tracing.value import histogram_set
@@ -46,7 +47,7 @@
   intermediate_results = _LoadIntermediateResults(
       os.path.join(options.intermediate_dir, TELEMETRY_RESULTS))
 
-  _AggregateTraces(intermediate_results)
+  AggregateTraces(intermediate_results)
 
   UploadArtifacts(
       intermediate_results, options.upload_bucket, options.results_label)
@@ -99,7 +100,7 @@
   return results
 
 
-def _AggregateTraces(intermediate_results):
+def AggregateTraces(intermediate_results):
   """Replace individual traces with an aggregate one for each test result.
 
   For each test run with traces, generates an aggregate HTML trace. Removes
@@ -109,10 +110,16 @@
     artifacts = result.get('outputArtifacts', {})
     traces = [name for name in artifacts if name.startswith('trace/')]
     if len(traces) > 0:
-      # For now, the html trace is generated by Telemetry, so it should be there
-      # already. All we need to do is remove individual traces from the dict.
-      # TODO(crbug.com/981349): replace this with actual aggregation code.
-      assert compute_metrics.HTML_TRACE_NAME in artifacts
+      if compute_metrics.HTML_TRACE_NAME not in artifacts:
+        trace_files = [artifacts[name]['filePath'] for name in traces]
+        html_path = os.path.join(
+            os.path.dirname(os.path.commonprefix(trace_files)),
+            compute_metrics.HTML_TRACE_NAME)
+        trace_data.SerializeAsHtml(trace_files, html_path)
+        artifacts[compute_metrics.HTML_TRACE_NAME] = {
+          'filePath': html_path,
+          'contentType': 'text/html',
+        }
       for trace in traces:
         del artifacts[trace]
 
diff --git a/tools/perf/core/results_processor/processor_test.py b/tools/perf/core/results_processor/processor_test.py
index a755845..b25893d4 100644
--- a/tools/perf/core/results_processor/processor_test.py
+++ b/tools/perf/core/results_processor/processor_test.py
@@ -24,6 +24,7 @@
 from core.results_processor import processor
 from core.results_processor import testing
 
+from tracing.value.diagnostics import generic_set
 from tracing.value import histogram
 from tracing.value import histogram_set
 from tracing_build import render_histograms_viewer
@@ -268,12 +269,45 @@
 
     out_histograms = histogram_set.HistogramSet()
     out_histograms.ImportDicts(results)
-    self.assertEqual(len(out_histograms), 4)
-    self.assertIsNotNone(out_histograms.GetHistogramNamed('foo'))
 
-    diag_values = [list(v) for v in  out_histograms.shared_diagnostics]
-    self.assertEqual(len(diag_values), 1)
-    self.assertIn(['gs://trace.html'], diag_values)
+    # sampleMetric records a histogram with the name 'foo'.
+    hist = out_histograms.GetHistogramNamed('foo')
+    self.assertIsNotNone(hist)
+    self.assertEqual(hist.diagnostics['traceUrls'],
+                     generic_set.GenericSet(['gs://trace.html']))
+
+  def testHistogramsOutputNoAggregatedTrace(self):
+    json_trace = os.path.join(self.output_dir, 'trace.json')
+    with open(json_trace, 'w') as f:
+      json.dump({'traceEvents': []}, f)
+
+    self.SerializeIntermediateResults(
+        test_results=[
+            testing.TestResult(
+                'benchmark/story',
+                output_artifacts={'trace/json': testing.Artifact(json_trace)},
+                tags=['tbmv2:sampleMetric'],
+            ),
+        ],
+    )
+
+    processor.main([
+        '--output-format', 'histograms',
+        '--output-dir', self.output_dir,
+        '--intermediate-dir', self.intermediate_dir,
+    ])
+
+    with open(os.path.join(
+        self.output_dir, histograms_output.OUTPUT_FILENAME)) as f:
+      results = json.load(f)
+
+    out_histograms = histogram_set.HistogramSet()
+    out_histograms.ImportDicts(results)
+
+    # sampleMetric records a histogram with the name 'foo'.
+    hist = out_histograms.GetHistogramNamed('foo')
+    self.assertIsNotNone(hist)
+    self.assertIn('traceUrls', hist.diagnostics)
 
   def testHtmlOutput(self):
     hist_file = os.path.join(self.output_dir,
diff --git a/tools/perf/core/results_processor/processor_unittest.py b/tools/perf/core/results_processor/processor_unittest.py
index 192f37e..8878f0f4 100644
--- a/tools/perf/core/results_processor/processor_unittest.py
+++ b/tools/perf/core/results_processor/processor_unittest.py
@@ -4,6 +4,7 @@
 
 """Unit tests for results_processor methods."""
 
+import os
 import unittest
 
 import mock
@@ -94,3 +95,55 @@
             'src_abc_123_20191001T120000_54321/benchmark/story/trace.html',
             '/trace.html'
         )
+
+  def testAggregateTraces(self):
+    in_results = testing.IntermediateResults(
+        test_results=[
+            testing.TestResult(
+                'benchmark/story1',
+                output_artifacts={
+                    'trace/1.json': testing.Artifact(
+                        os.path.join('test_run', 'story1', 'trace', '1.json')),
+                },
+            ),
+            testing.TestResult(
+                'benchmark/story2',
+                output_artifacts={
+                    'trace/1.json': testing.Artifact(
+                        os.path.join('test_run', 'story2', 'trace', '1.json')),
+                    'trace/2.json': testing.Artifact(
+                        os.path.join('test_run', 'story2', 'trace', '2.json')),
+                },
+            ),
+        ],
+    )
+
+    with mock.patch('tracing.trace_data.trace_data.SerializeAsHtml') as patch:
+      processor.AggregateTraces(in_results)
+
+    call_list = [list(call[0]) for call in patch.call_args_list]
+    self.assertEqual(len(call_list), 2)
+    for call in call_list:
+      call[0] = set(call[0])
+    self.assertIn(
+        [
+            set([os.path.join('test_run', 'story1', 'trace', '1.json')]),
+            os.path.join('test_run', 'story1', 'trace', 'trace.html'),
+        ],
+        call_list
+    )
+    self.assertIn(
+        [
+            set([
+                os.path.join('test_run', 'story2', 'trace', '1.json'),
+                os.path.join('test_run', 'story2', 'trace', '2.json'),
+            ]),
+            os.path.join('test_run', 'story2', 'trace', 'trace.html'),
+        ],
+        call_list
+    )
+
+    for result in in_results['testResults']:
+      artifacts = result['outputArtifacts']
+      self.assertEqual(len(artifacts), 1)
+      self.assertEqual(artifacts.keys()[0], 'trace.html')
diff --git a/tools/perf/core/tbmv3/OWNERS b/tools/perf/core/tbmv3/OWNERS
new file mode 100644
index 0000000..1ce6b42
--- /dev/null
+++ b/tools/perf/core/tbmv3/OWNERS
@@ -0,0 +1,2 @@
+perezju@chromium.org
+dproy@chromium.org
diff --git a/tools/perf/core/tbmv3/README.md b/tools/perf/core/tbmv3/README.md
new file mode 100644
index 0000000..1603f92
--- /dev/null
+++ b/tools/perf/core/tbmv3/README.md
@@ -0,0 +1,9 @@
+<!-- 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.
+-->
+
+# TBMv3 [Experimental]
+
+This directory contains files for TBMv3, an experimental new metric authoring
+platform based on Perfetto.
diff --git a/tools/perf/core/tbmv3/__init__.py b/tools/perf/core/tbmv3/__init__.py
new file mode 100644
index 0000000..4a12e35
--- /dev/null
+++ b/tools/perf/core/tbmv3/__init__.py
@@ -0,0 +1,3 @@
+# 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.
diff --git a/tools/perf/core/tbmv3/metrics/console_error_metric.proto b/tools/perf/core/tbmv3/metrics/console_error_metric.proto
new file mode 100644
index 0000000..c1bc593
--- /dev/null
+++ b/tools/perf/core/tbmv3/metrics/console_error_metric.proto
@@ -0,0 +1,19 @@
+// Copyright 2019 Google LLC.
+// SPDX-License-Identifier: Apache-2.0
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+import "protos/perfetto/metrics/metrics.proto";
+
+message ConsoleErrorMetric {
+  optional int64 all = 1;
+  optional int64 js = 2;
+  optional int64 network = 3;
+}
+
+extend TraceMetrics {
+  optional ConsoleErrorMetric console_error_metric = 450;
+}
diff --git a/tools/perf/core/tbmv3/metrics/console_error_metric.sql b/tools/perf/core/tbmv3/metrics/console_error_metric.sql
new file mode 100644
index 0000000..3047540b
--- /dev/null
+++ b/tools/perf/core/tbmv3/metrics/console_error_metric.sql
@@ -0,0 +1,32 @@
+-- Copyright 2019 Google LLC.
+-- SPDX-License-Identifier: Apache-2.0
+
+CREATE VIEW console_error_events AS
+SELECT args.string_value as source
+from slices
+inner join args using(arg_set_id)
+where slices.name = "ConsoleMessage::Error"
+  and slices.category = "blink.console"
+  and args.flat_key = "debug.source"
+UNION ALL
+-- Can't find a trace with v8 console errors so this path is untested.
+SELECT "JS" AS source
+FROM slices
+WHERE slices.category = 'v8.console' AND (
+  slices.name = 'V8ConsoleMessage::Exception' OR
+  slices.name = 'V8ConsoleMessage::Error' OR
+  slices.name = 'V8ConsoleMessage::Assert'
+);
+
+CREATE VIEW console_error_metric AS
+SELECT
+  (SELECT COUNT(*) FROM console_error_events) as all_errors,
+  (SELECT COUNT(*) FROM console_error_events where source = "JS") as js,
+  (SELECT COUNT(*) FROM console_error_events where source = "Network") as network;
+
+CREATE VIEW console_error_metric_output AS
+SELECT ConsoleErrorMetric(
+  'all', all_errors,
+  'js', js,
+  'network', network)
+FROM console_error_metric
diff --git a/tools/perf/core/tbmv3/run_tbmv3_metric.py b/tools/perf/core/tbmv3/run_tbmv3_metric.py
new file mode 100755
index 0000000..5228d90
--- /dev/null
+++ b/tools/perf/core/tbmv3/run_tbmv3_metric.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env vpython
+# 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 argparse
+import json
+import os
+import subprocess
+import sys
+
+from collections import namedtuple
+
+
+_CHROMIUM_SRC_PATH  = os.path.join(
+    os.path.dirname(__file__), '..', '..', '..', '..')
+_DEFAULT_TP_PATH = os.path.abspath(os.path.join(
+    _CHROMIUM_SRC_PATH, 'out', 'Debug', 'trace_processor_shell'))
+_METRICS_PATH = os.path.join(os.path.dirname(__file__), 'metrics')
+
+MetricFiles = namedtuple('MetricFiles', ('sql', 'proto'))
+
+
+class MetricFileNotFound(Exception):
+  pass
+
+
+class TraceProcessorNotFound(Exception):
+  pass
+
+
+class TraceProcessorError(Exception):
+  pass
+
+
+def _CheckFilesExist(trace_processor_path, metric_files):
+  if not os.path.exists(trace_processor_path):
+    raise TraceProcessorNotFound("Could not find trace processor shell at %s"
+                                 % trace_processor_path)
+
+  # Currently assuming all metric files live in tbmv3/metrics directory. We will
+  # revise this decision later.
+  for filetype, path in metric_files._asdict().iteritems():
+    if not os.path.exists(path):
+      raise MetricFileNotFound("metric %s file not found at %s"
+                               % (filetype, path))
+
+
+def Main():
+  parser = argparse.ArgumentParser(
+    description='[Experimental] Runs TBMv3 metrics on local traces.')
+  parser.add_argument('--trace', required=True,
+                      help='Trace file you want to compute metric on')
+  parser.add_argument('--metric', required=True,
+                      help=('Name of the metric you want to run'))
+  parser.add_argument('--trace_processor_path', default=_DEFAULT_TP_PATH,
+                      help='Path to trace processor shell. '
+                      'Default: %(default)s')
+  args = parser.parse_args()
+
+  metric_files = MetricFiles(
+    sql=os.path.join(_METRICS_PATH, args.metric + '.sql'),
+    proto=os.path.join(_METRICS_PATH, args.metric + '.proto')
+  )
+  _CheckFilesExist(args.trace_processor_path, metric_files)
+
+  trace_processor_args = [args.trace_processor_path,
+                          args.trace,
+                          '--run-metrics', metric_files.sql,
+                          '--metrics-output=json',
+                          '--extra-metrics', _METRICS_PATH]
+
+  try:
+    json_output = subprocess.check_output(trace_processor_args)
+  except subprocess.CalledProcessError:
+    raise TraceProcessorError("Failed to compute metrics. " +
+                              "Check trace processor logs.")
+
+  json_result = json.loads(json_output)
+  print "Metric result:"
+  print json_result
+
+
+if __name__ == '__main__':
+  sys.exit(Main())
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 4490ef1..4e75173 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -219,14 +219,6 @@
 crbug.com/865400 [ android-pixel-2 android-webview ] loading.mobile/VoiceMemos_cold_3g [ Skip ]
 crbug.com/919191 [ android-nexus-5x android-webview ] loading.mobile/OLX_3g [ Skip ]
 
-# Benchmark: oilpan_gc_times.key_silk_cases
-crbug.com/446332 oilpan_gc_times.key_silk_cases/slide_drawer [ Skip ]
-crbug.com/507865 oilpan_gc_times.key_silk_cases/polymer_topeka [ Skip ]
-crbug.com/338838 oilpan_gc_times.key_silk_cases/basic_stream [ Skip ]
-
-# Benchmark: oilpan_gc_times.sync_scroll.key_mobile_sites_smooth
-crbug.com/756119 oilpan_gc_times.sync_scroll.key_mobile_sites_smooth/digg [ Skip ]
-
 # Benchmark: rendering.desktop
 crbug.com/755556 [ mac ] rendering.desktop/mix_blend_mode_animation_difference [ Skip ]
 crbug.com/755556 [ mac ] rendering.desktop/mix_blend_mode_animation_hue [ Skip ]
diff --git a/tools/vscode/launch.json5 b/tools/vscode/launch.json5
index 8591577..efb6eee30 100644
--- a/tools/vscode/launch.json5
+++ b/tools/vscode/launch.json5
@@ -34,7 +34,7 @@
     "targetArchitecture": "x64",
     "program": "${workspaceRoot}/out/Debug/unit_tests",
     "args": ["--gtest_filter=*",
-              "--single_process",
+              "--single-process-tests",
               "--ui-test-action-max-timeout=1000000",
               "--test-launcher-timeout=1000000"],
     "preLaunchTask": "5-build_test_debug",
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.cc b/ui/views/bubble/bubble_dialog_delegate_view.cc
index 36b4dd6b..4238c02 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.cc
+++ b/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -154,11 +154,6 @@
   return false;
 }
 
-ClientView* BubbleDialogDelegateView::CreateClientView(Widget* widget) {
-  DialogClientView* client = new DialogClientView(widget, GetContentsView());
-  return client;
-}
-
 NonClientFrameView* BubbleDialogDelegateView::CreateNonClientFrameView(
     Widget* widget) {
   BubbleFrameView* frame = new BubbleDialogFrameView(title_margins_);
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.h b/ui/views/bubble/bubble_dialog_delegate_view.h
index 97e965a..9a2c6b9 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.h
+++ b/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -59,7 +59,6 @@
   // DialogDelegateView:
   BubbleDialogDelegateView* AsBubbleDialogDelegate() override;
   bool ShouldShowCloseButton() const override;
-  ClientView* CreateClientView(Widget* widget) override;
   NonClientFrameView* CreateNonClientFrameView(Widget* widget) override;
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
 
diff --git a/ui/views/test/widget_test.h b/ui/views/test/widget_test.h
index c96a091..cac487c 100644
--- a/ui/views/test/widget_test.h
+++ b/ui/views/test/widget_test.h
@@ -112,6 +112,12 @@
   // Returns the set of all Widgets that currently have a NativeWindow.
   static Widget::Widgets GetAllWidgets();
 
+  // Waits for system app activation events, if any, to have happened. This is
+  // necessary on macOS 10.15+, where the system will attempt to find and
+  // activate a window owned by the app shortly after app startup, if there is
+  // one. See https://crbug.com/998868 for details.
+  static void WaitForSystemAppActivation();
+
  private:
   DISALLOW_COPY_AND_ASSIGN(WidgetTest);
 };
diff --git a/ui/views/test/widget_test_aura.cc b/ui/views/test/widget_test_aura.cc
index 970fe6a..e1d6b9b8 100644
--- a/ui/views/test/widget_test_aura.cc
+++ b/ui/views/test/widget_test_aura.cc
@@ -175,5 +175,8 @@
   return all_widgets;
 }
 
+// static
+void WidgetTest::WaitForSystemAppActivation() {}
+
 }  // namespace test
 }  // namespace views
diff --git a/ui/views/test/widget_test_mac.mm b/ui/views/test/widget_test_mac.mm
index a160d81..643dc32 100644
--- a/ui/views/test/widget_test_mac.mm
+++ b/ui/views/test/widget_test_mac.mm
@@ -6,10 +6,12 @@
 
 #include <Cocoa/Cocoa.h>
 
+#include "base/mac/mac_util.h"
 #import "base/mac/scoped_nsobject.h"
 #import "base/mac/scoped_objc_class_swizzler.h"
 #include "base/macros.h"
 #import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
+#import "ui/base/test/windowed_nsnotification_observer.h"
 #include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
 #include "ui/views/widget/native_widget_mac.h"
 #include "ui/views/widget/root_view.h"
@@ -107,5 +109,22 @@
   return all_widgets;
 }
 
+// static
+void WidgetTest::WaitForSystemAppActivation() {
+  if (base::mac::IsAtMostOS10_14())
+    return;
+
+  // This seems to be only necessary on 10.15+ but it's obscure why. Shortly
+  // after launching an app, the system sends ApplicationDidFinishLaunching
+  // (which is normal), which causes AppKit on 10.15 to try to find a window to
+  // activate. If it finds one it will makeKeyAndOrderFront: it, which breaks
+  // tests that are deliberately creating inactive windows.
+  base::scoped_nsobject<WindowedNSNotificationObserver> observer(
+      [[WindowedNSNotificationObserver alloc]
+          initForNotification:NSApplicationDidFinishLaunchingNotification
+                       object:NSApp]);
+  [observer wait];
+}
+
 }  // namespace test
 }  // namespace views
diff --git a/ui/views/widget/desktop_aura/OWNERS b/ui/views/widget/desktop_aura/OWNERS
index 9069e120..3d8482e 100644
--- a/ui/views/widget/desktop_aura/OWNERS
+++ b/ui/views/widget/desktop_aura/OWNERS
@@ -1,2 +1,3 @@
 per-file *x11*=thomasanderson@chromium.org
 per-file window_event_filter*=thomasanderson@chromium.org
+per-file *linux*=thomasanderson@chromium.org
diff --git a/ui/views/widget/native_widget_mac_interactive_uitest.mm b/ui/views/widget/native_widget_mac_interactive_uitest.mm
index f152729..f8cf2390 100644
--- a/ui/views/widget/native_widget_mac_interactive_uitest.mm
+++ b/ui/views/widget/native_widget_mac_interactive_uitest.mm
@@ -116,6 +116,7 @@
 
 // Test that ShowInactive does not take keyWindow status.
 TEST_P(NativeWidgetMacInteractiveUITest, ShowInactiveIgnoresKeyStatus) {
+  WidgetTest::WaitForSystemAppActivation();
   Widget* widget = MakeWidget();
   NSWindow* widget_window = widget->GetNativeWindow().GetNativeNSWindow();
 
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc
index 1edf2ab..49a2fa49 100644
--- a/ui/views/widget/widget_interactive_uitest.cc
+++ b/ui/views/widget/widget_interactive_uitest.cc
@@ -1260,6 +1260,7 @@
 }
 
 TEST_F(WidgetTestInteractive, ShowInactive) {
+  WidgetTest::WaitForSystemAppActivation();
   Widget* widget = CreateTopLevelPlatformWidget();
 
   ShowInactiveSync(widget);
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc
index 533cfbe..46dd3ab 100644
--- a/ui/views/window/dialog_client_view.cc
+++ b/ui/views/window/dialog_client_view.cc
@@ -318,10 +318,6 @@
   if (!ShouldShow(extra_view_) || !(ok_button_ || cancel_button_))
     return 0;
 
-  int extra_view_padding = 0;
-  if (GetDialogDelegate()->GetExtraViewPadding(&extra_view_padding))
-    return extra_view_padding;
-
   return LayoutProvider::Get()->GetDistanceMetric(
       views::DISTANCE_RELATED_BUTTON_HORIZONTAL);
 }
diff --git a/ui/views/window/dialog_client_view.h b/ui/views/window/dialog_client_view.h
index fb557cb..462b670 100644
--- a/ui/views/window/dialog_client_view.h
+++ b/ui/views/window/dialog_client_view.h
@@ -102,7 +102,7 @@
   void UpdateDialogButton(LabelButton** member, ui::DialogButton type);
 
   // Returns the spacing between the extra view and the ok/cancel buttons. 0 if
-  // no extra view. Otherwise uses GetExtraViewPadding() or the default padding.
+  // no extra view. Otherwise uses the default padding.
   int GetExtraViewSpacing() const;
 
   // Returns Views in the button row, as they should appear in the layout. If
diff --git a/ui/views/window/dialog_client_view_unittest.cc b/ui/views/window/dialog_client_view_unittest.cc
index 354adea..8aa6bf85 100644
--- a/ui/views/window/dialog_client_view_unittest.cc
+++ b/ui/views/window/dialog_client_view_unittest.cc
@@ -59,10 +59,6 @@
   gfx::Size CalculatePreferredSize() const override { return preferred_size_; }
   gfx::Size GetMinimumSize() const override { return min_size_; }
   gfx::Size GetMaximumSize() const override { return max_size_; }
-  ClientView* CreateClientView(Widget* widget) override {
-    client_view_ = new DialogClientView(widget, this);
-    return client_view_;
-  }
 
   void DeleteDelegate() override {
     // DialogDelegateView would delete this, but |this| is owned by the test.
@@ -72,12 +68,6 @@
     return std::move(next_extra_view_);
   }
 
-  bool GetExtraViewPadding(int* padding) override {
-    if (extra_view_padding_)
-      *padding = *extra_view_padding_;
-    return extra_view_padding_.get() != nullptr;
-  }
-
   int GetDialogButtons() const override { return dialog_buttons_; }
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override {
     return button == ui::DIALOG_BUTTON_CANCEL && !cancel_label_.empty()
@@ -87,9 +77,9 @@
 
  protected:
   gfx::Rect GetUpdatedClientBounds() {
-    client_view_->SizeToPreferredSize();
-    client_view_->Layout();
-    return client_view_->bounds();
+    client_view()->SizeToPreferredSize();
+    client_view()->Layout();
+    return client_view()->bounds();
   }
 
   // Makes sure that the content view is sized correctly. Width must be at least
@@ -119,13 +109,6 @@
     EXPECT_FALSE(next_extra_view_);
   }
 
-  // Sets the extra view padding.
-  void SetExtraViewPadding(int padding) {
-    DCHECK(!extra_view_padding_);
-    extra_view_padding_ = std::make_unique<int>(padding);
-    DialogModelChanged();
-  }
-
   void SetSizeConstraints(const gfx::Size& min_size,
                           const gfx::Size& preferred_size,
                           const gfx::Size& max_size) {
@@ -148,7 +131,9 @@
     cancel_label_ = base::ASCIIToUTF16("Cancel Cancel Cancel");
   }
 
-  DialogClientView* client_view() { return client_view_; }
+  DialogClientView* client_view() {
+    return static_cast<DialogClientView*>(widget_->client_view());
+  }
 
   Widget* widget() { return widget_; }
 
@@ -156,17 +141,12 @@
   // The dialog Widget.
   Widget* widget_ = nullptr;
 
-  // The DialogClientView that's being tested. Owned by |widget_|.
-  DialogClientView* client_view_;
-
   // The bitmask of buttons to show in the dialog.
   int dialog_buttons_ = ui::DIALOG_BUTTON_NONE;
 
   // Set and cleared in SetExtraView().
   std::unique_ptr<View> next_extra_view_;
 
-  std::unique_ptr<int> extra_view_padding_;
-
   gfx::Size preferred_size_;
   gfx::Size min_size_;
   gfx::Size max_size_;
@@ -302,22 +282,17 @@
   SetExtraView(extra_view);
   CheckContentsIsSetToPreferredSize();
   EXPECT_GT(client_view()->bounds().height(), no_extra_view_size.height());
-  const int width_of_dialog_small_padding = client_view()->width();
 
-  // Try with an adjusted padding for the extra view.
-  SetExtraViewPadding(250);
-  CheckContentsIsSetToPreferredSize();
-  EXPECT_GT(client_view()->bounds().width(), width_of_dialog_small_padding);
-
+  // The dialog is bigger with the extra view than without it.
   const gfx::Size with_extra_view_size = client_view()->size();
   EXPECT_NE(no_extra_view_size, with_extra_view_size);
 
-  // Hiding the extra view removes it as well as the extra padding.
+  // Hiding the extra view removes it.
   extra_view->SetVisible(false);
   CheckContentsIsSetToPreferredSize();
   EXPECT_EQ(no_extra_view_size, client_view()->size());
 
-  // Making it visible again adds it all back.
+  // Making it visible again adds it back.
   extra_view->SetVisible(true);
   CheckContentsIsSetToPreferredSize();
   EXPECT_EQ(with_extra_view_size, client_view()->size());
diff --git a/ui/views/window/dialog_delegate.cc b/ui/views/window/dialog_delegate.cc
index d0832c3..db5ac3b 100644
--- a/ui/views/window/dialog_delegate.cc
+++ b/ui/views/window/dialog_delegate.cc
@@ -143,10 +143,6 @@
   return nullptr;
 }
 
-bool DialogDelegate::GetExtraViewPadding(int* padding) {
-  return false;
-}
-
 std::unique_ptr<View> DialogDelegate::CreateFootnoteView() {
   return nullptr;
 }
diff --git a/ui/views/window/dialog_delegate.h b/ui/views/window/dialog_delegate.h
index 48d436f..9787d33 100644
--- a/ui/views/window/dialog_delegate.h
+++ b/ui/views/window/dialog_delegate.h
@@ -95,12 +95,6 @@
   // Overrides may construct the view; this will only be called once per dialog.
   virtual std::unique_ptr<View> CreateExtraView();
 
-  // Override this function to adjust the padding between the extra view and
-  // the confirm/cancel buttons. Note that if there are no buttons, this will
-  // not be used.
-  // If a custom padding should be used, returns true and populates |padding|.
-  virtual bool GetExtraViewPadding(int* padding);
-
   // Override this function to display a footnote view below the buttons.
   // Overrides may construct the view; this will only be called once per dialog.
   virtual std::unique_ptr<View> CreateFootnoteView();