diff --git a/AUTHORS b/AUTHORS
index a2fb30aa..3b001fca 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -787,6 +787,7 @@
 Magnus Danielsson <fuzzac@gmail.com>
 Mahesh Kulkarni <mahesh.kk@samsung.com>
 Mahesh Machavolu <mahesh.ma@samsung.com>
+Mahmoud Ahmed <mahmoudaahmedd@gmail.com>
 Maksim Kolesin <mkolesin@gmail.com>
 Maksim Sisov <maksim.sisov@intel.com>
 Malcolm Wang <malcolm.2.wang@gmail.com>
diff --git a/DEPS b/DEPS
index 34055282..c49111b 100644
--- a/DEPS
+++ b/DEPS
@@ -304,15 +304,15 @@
   # 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': '5f8bbade2b02c720b6348deeed13bc9e780dbdd1',
+  'skia_revision': '001ba6e28f99744d3413797e0dc38667e985b6ab',
   # 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': 'd9558caecd52c32944d54ed2ff126b29e74d976e',
+  'v8_revision': 'a21017d7f85a6993b07b422bd8266594674c8a5d',
   # 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': 'fc7cb00e99475c0093cde8d39efe9b811d1f5889',
+  'angle_revision': '21ffb23a58c8f69b3575299cede7f0a3df301ddd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -320,7 +320,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '1233727e1f81bca977ee92d4c6284e2828f76a1e',
+  'pdfium_revision': 'f3d0f929f461effa86ac27716bd304ba7d534445',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -391,7 +391,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '23a3cce74f0e8efdc54210e38eab9a2e5c8b4ed3',
+  'devtools_frontend_revision': '51ff36b012d74b8b9c997a7a898eccb4e96632cb',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -431,11 +431,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': '8e414572be8c970db605f8fb04bae214c819d52e',
+  'dawn_revision': '947a7deb99687a270f12540c41ec9ade9489b57b',
   # 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': 'b3fe8cfa820d3ea5404e166d7b00bd90f18c7c77',
+  'quiche_revision': '8bb742f3ebefdbcad6bdd157248b30233bbf839d',
   # 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.
@@ -467,7 +467,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'cros_components_revision': 'c1cc4ae57ac3688608297f44c97d8b0afdf7f791',
+  'cros_components_revision': '1a1975f288260230a62d47806598bba68959d43f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -495,7 +495,7 @@
 
   # If you change this, also update the libc++ revision in
   # //buildtools/deps_revisions.gni.
-  'libcxx_revision':       '26ace673c4b9c7a352fa9db182256bb341b6c44f',
+  'libcxx_revision':       'e0dca93272081cf3b2d04fcf83f5b5804c3730de',
 
   # GN CIPD package version.
   'gn_version': 'git_revision:41fef642de70ecdcaaa26be96d56a0398f95abd4',
@@ -504,10 +504,6 @@
   # https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja
   # This has to stay in sync with the version in src/third_party/ninja/README.chromium.
   'ninja_version': 'version:2@1.11.1.chromium.6',
-
-  # Used for src-internal deps into src migration.
-  # TODO(1409738): Remove this post migration.
-  'checkout_chromeos_assistant': False,
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -794,7 +790,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'b2bb3567d161df5f3e4e20b0f110a66c41b1a50c',
+    '78bd8562a9b498d7dea47cd75d21314d0b422b37',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -803,12 +799,12 @@
   },
 
   'src/ios/third_party/earl_grey2/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '740b64276df73d896a9db6011a3515d20eac30cc',
+      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '3935b4ad113fdc8de7246240a9eb586a76ff0c55',
       'condition': 'checkout_ios',
   },
 
   'src/ios/third_party/edo/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '51058a369f943064dc6db4f38dca32263d584ea5',
+      'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '73ba9dad3db53e20bf1c410089ef56dc72e45d9f',
       'condition': 'checkout_ios',
   },
 
@@ -904,7 +900,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': 'GXdygJ5Lqx05fwk4gzmN04ydfOcnrBySGlK_fc5s2pcC',
+          'version': '6pvDQ7H-ZiRchmzb2nVXcXLpLZbm1W4v-fSg5kA8ABsC',
         },
       ],
       'dep_type': 'cipd',
@@ -915,7 +911,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/windows-amd64',
-          'version': 'sJ-03ctmnf-O_OKaRdFJ2es8jg1DIs96Vv4tMNx6t58C',
+          'version': 'TGqVebSVBEeYTMwYqHH9JcJyl4tTtrTEYZrSx1Q95cUC',
         },
       ],
       'dep_type': 'cipd',
@@ -983,7 +979,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'zvyRaq_hY1gg3vn5ByQj77DzD8tJ1oEHIci-xNgOCVoC',
+          'version': 'q-4EGT6m1jFTmhGIBcb9baxf_vf5jExDN7FYNlNp5DwC',
       },
     ],
     'condition': 'checkout_android',
@@ -1120,7 +1116,7 @@
     Var('chromium_git') + '/angle/angle.git' + '@' +  Var('angle_revision'),
 
   'src/third_party/content_analysis_sdk/src':
-    Var('chromium_git') + '/external/github.com/chromium/content_analysis_sdk.git' + '@' + 'dbcaea90641fab03fb7f157a200f53cf148e4542',
+    Var('chromium_git') + '/external/github.com/chromium/content_analysis_sdk.git' + '@' + '81759c87866fcd3453438dfbd281e06dab24fe20',
 
   'src/third_party/dav1d/libdav1d':
     Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + 'd426d1c91075b9c552b12dd052af1cd0368f05a2',
@@ -1202,7 +1198,7 @@
   # Tools used when building Chrome for Chrome OS. This affects both the Simple
   # Chrome workflow, as well as the chromeos-chrome ebuild.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8b9b1646b44ebf6946de4392abeaf6d7e14c15a0',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'dcf8d6706480b3fe2ccbf38ebf1fd7e066f471d1',
       'condition': 'checkout_chromeos',
   },
 
@@ -1220,7 +1216,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '5fe262ce9b4307f17c9c930eb40092705ce62861',
+      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '0b2e66c2960fed10e70492262c8dd0afb8ac492e',
       'condition': 'checkout_linux',
   },
 
@@ -1234,13 +1230,13 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'f724f296b75b193032693636aee9f6ce71b6ea5d',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4a7343007c7c6f45124eb4e01f8a4fddaec79a11',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '02f6bcb6f5a55673143cea79666c880825428f15',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'b57805a9500a15468fc6911bd3fa6fdea4c6ac9d',
     'condition': 'checkout_src_internal',
   },
 
@@ -1706,7 +1702,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c44cab035c6fa258837e947ebc06e4683249d3b2',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'ad418a3f70f33f6b50cd008b565360ef95446063',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1746,7 +1742,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': 'BTs9W6pUBDK8YTePjjF3Q0-ZQo1snO7GBCT6frWMIj8C',
+              'version': '0AAkHl3ztCss8QvTqGZbCU0Wy2W-0CIoWwCYZnYg7j0C',
           },
       ],
       'condition': 'checkout_android',
@@ -1851,7 +1847,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@e8749b36413750d99fc7bdecaba222cd1ff77235',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@312fd30e3f3d7b7ee83425897c2051ba503df8d6',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1891,7 +1887,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'fd777c3d00dce755d04cbe5da9a407a2f06ff008',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '58b049373ee4c9ec97d93d2cbe303bde0c4e5045',
+    Var('webrtc_git') + '/src.git' + '@' + 'f01e97063a00eca067b4b1442dd88cf1e6f796ae',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -1921,6 +1917,19 @@
   'src/tools/page_cycler/acid3':
     Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + '6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
 
+  'src/third_party/libei': {
+
+    'packages': [
+      {
+        'package': 'chromium/third_party/libei/linux-amd64',
+        'version': 'PQz4zG5Q3SXoAaCYq3RK99W3wg_v0NoOu1OzTSvA_oIC',
+      },
+    ],
+
+    'condition': 'checkout_linux',
+    'dep_type': 'cipd',
+  },
+
   'src/tools/skia_goldctl/linux': {
       'packages': [
         {
@@ -1968,7 +1977,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': Var('chrome_git') + '/chrome/src-internal.git@b1836a9316bf57b92f1211cd0c644c175025967a',
+    'url': Var('chrome_git') + '/chrome/src-internal.git@a2801d57a7a1aab1373553d28ca9ec09b58130a8',
     'condition': 'checkout_src_internal',
   },
 
@@ -2676,17 +2685,6 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/android_deps/libs/com_google_android_gms_play_services_fido': {
-      'packages': [
-          {
-              'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_fido',
-              'version': 'version:2@19.0.0-beta.cr1',
-          },
-      ],
-      'condition': 'checkout_android',
-      'dep_type': 'cipd',
-  },
-
   'src/third_party/android_deps/libs/com_google_android_gms_play_services_flags': {
       'packages': [
           {
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index f906ae1..9127c725 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -5988,7 +5988,6 @@
     unnecessary_screenshots = []
     missing_sha1 = []
     missing_sha1_modified = []
-    invalid_sha1 = []
     unnecessary_sha1_files = []
 
     # This checks verifies that the ICU syntax of messages this CL touched is
@@ -5998,24 +5997,18 @@
     # break message extraction for translation, hence would block Chromium
     # translations until they are fixed.
     icu_syntax_errors = []
-    sha1_pattern = input_api.re.compile(r'^[a-fA-F0-9]{40}$',
-                                        input_api.re.MULTILINE)
 
     def _CheckScreenshotAdded(screenshots_dir, message_id):
         sha1_path = input_api.os_path.join(screenshots_dir,
                                            message_id + '.png.sha1')
         if sha1_path not in new_or_added_paths:
             missing_sha1.append(sha1_path)
-        elif not sha1_pattern.search(input_api.ReadFile(sha1_path)):
-            invalid_sha1.append(sha1_path)
 
     def _CheckScreenshotModified(screenshots_dir, message_id):
         sha1_path = input_api.os_path.join(screenshots_dir,
                                            message_id + '.png.sha1')
         if sha1_path not in new_or_added_paths:
             missing_sha1_modified.append(sha1_path)
-        elif not sha1_pattern.search(input_api.ReadFile(sha1_path)):
-            invalid_sha1.append(sha1_path)
 
     def _CheckScreenshotRemoved(screenshots_dir, message_id):
         sha1_path = input_api.os_path.join(screenshots_dir,
@@ -6213,8 +6206,14 @@
                 modified_ids.add(key)
             elif old_id_to_msg_map[key].attrs['meaning'] != \
                 new_id_to_msg_map[key].attrs['meaning']:
-                # The message meaning changed. We later check for a screenshot.
-                modified_ids.add(key)
+                # The message meaning changed. Ensure there is a screenshot for it.
+                sha1_path = input_api.os_path.join(screenshots_dir,
+                                                   key + '.png.sha1')
+                if sha1_path not in new_or_added_paths and not \
+                    input_api.os_path.exists(sha1_path):
+                    # There is neither a previous screenshot nor is a new one added now.
+                    # Require a screenshot.
+                    modified_ids.add(key)
 
         if run_screenshot_check:
             # Check the screenshot directory for .png files. Warn if there is any.
@@ -6255,13 +6254,6 @@
                     '(https://g.co/chrome/translation) and add these files to your '
                     'changelist:', sorted(missing_sha1)))
 
-        if invalid_sha1:
-            results.append(
-                output_api.PresubmitError(
-                    'The following files do not seem to contain valid sha1 hashes. '
-                    'Make sure they contain hashes created by '
-                    'tools/translate/upload_screenshots.py:', sorted(invalid_sha1)))
-
         if missing_sha1_modified:
             results.append(
                 output_api.PresubmitError(
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py
index ea7797d..8437775 100755
--- a/PRESUBMIT_test.py
+++ b/PRESUBMIT_test.py
@@ -3467,7 +3467,6 @@
         '</message>',
     '</grit-part>')
 
-  VALID_SHA1 = ('0000000000000000000000000000000000000000',)
   DO_NOT_UPLOAD_PNG_MESSAGE = ('Do not include actual screenshots in the '
                                'changelist. Run '
                                'tools/translate/upload_screenshots.py to '
@@ -3482,9 +3481,6 @@
   ICU_SYNTAX_ERROR_MESSAGE = ('ICU syntax errors were found in the following '
                               'strings (problems or feedback? Contact '
                               'rainhard@chromium.org):')
-  SHA1_FORMAT_MESSAGE = ('The following files do not seem to contain valid sha1 '
-                         'hashes. Make sure they contain hashes created by '
-                         'tools/translate/upload_screenshots.py:')
 
   def makeInputApi(self, files):
     input_api = MockInputApi()
@@ -3553,7 +3549,7 @@
       MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3,
                        self.NEW_GRDP_CONTENTS4, action='M'),
       MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
-               self.VALID_SHA1, action='A')])
+               'binary', action='A')])
     warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
     self.assertEqual(0, len(warnings))
 
@@ -3572,20 +3568,10 @@
       MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
                        self.NEW_GRDP_CONTENTS6, action='M'),
       MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
-               self.VALID_SHA1, action='A')])
+               'binary', action='A')])
     warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
     self.assertEqual(0, len(warnings))
 
-  def testModifiedIntroducedInvalidSha1(self):
-    # CL modified a message and the sha1 file changed to invalid
-    input_api = self.makeInputApi([
-        MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS5,
-                         self.NEW_GRDP_CONTENTS6, action='M'),
-        MockAffectedFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
-                         ('some invalid sha1',), self.VALID_SHA1, action='M')])
-    warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
-    self.assertEqual(1, len(warnings))
-
   def testPngAddedSha1NotAdded(self):
     # CL added one new message in a grd file and added the png file associated
     # with it, but did not add the corresponding sha1 file. This should warn
@@ -3651,7 +3637,6 @@
                       os.path.join('test_grd', 'IDS_TEST1.png.sha1')],
                       warnings[1].items)
 
-
   def testScreenshotsWithSha1(self):
     # CL added four messages (two each in a grd and grdp) and their
     # corresponding .sha1 files. No warnings.
@@ -3670,64 +3655,24 @@
         # Added files:
         MockFile(
             os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
-            self.VALID_SHA1,
+            'binary',
             action='A'),
         MockFile(
             os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
-            ('0000000000000000000000000000000000000000', ''),
+            'binary',
             action='A'),
         MockFile(
             os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
-            self.VALID_SHA1,
+            'binary',
             action='A'),
         MockFile(
             os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
-            self.VALID_SHA1,
+            'binary',
             action='A'),
     ])
     warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
     self.assertEqual([], warnings)
 
-
-  def testScreenshotsWithInvalidSha1(self):
-    input_api = self.makeInputApi([
-        # Modified files:
-        MockAffectedFile(
-            'test.grd',
-            self.NEW_GRD_CONTENTS2,
-            self.OLD_GRD_CONTENTS,
-            action='M'),
-        MockAffectedFile(
-            'part.grdp',
-            self.NEW_GRDP_CONTENTS2,
-            self.OLD_GRDP_CONTENTS,
-            action='M'),
-        # Added files:
-        MockFile(
-            os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
-            self.VALID_SHA1,
-            action='A'),
-        MockFile(
-            os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
-            ('‰PNG', 'test'),
-            action='A'),
-        MockFile(
-            os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
-            self.VALID_SHA1,
-            action='A'),
-        MockFile(
-            os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
-            self.VALID_SHA1,
-            action='A'),
-    ])
-    warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
-    self.assertEqual(1, len(warnings))
-    self.assertEqual('error', warnings[0].type)
-    self.assertEqual(self.SHA1_FORMAT_MESSAGE, warnings[0].message)
-    self.assertEqual([os.path.join('test_grd', 'IDS_TEST2.png.sha1')],
-                     warnings[0].items)
-
-
   def testScreenshotsRemovedWithSha1(self):
     # Replace new contents with old contents in grd and grp files, removing
     # IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
@@ -3745,14 +3690,12 @@
             self.NEW_GRDP_CONTENTS2, # old_contents
             action='M'),
         # Unmodified files:
-        MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
-                 self.VALID_SHA1, ''),
-        MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
-                 self.VALID_SHA1, ''),
+        MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
+        MockFile(os.path.join('test_grd', 'IDS_TEST2.png.sha1'), 'binary', ''),
         MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
-                 self.VALID_SHA1, ''),
+                 'binary', ''),
         MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
-                 self.VALID_SHA1, '')
+                 'binary', '')
     ])
     warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
     self.assertEqual(1, len(warnings))
@@ -3779,10 +3722,9 @@
             self.NEW_GRDP_CONTENTS2, # old_contents
             action='M'),
         # Unmodified files:
-        MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
-                 self.VALID_SHA1, ''),
+        MockFile(os.path.join('test_grd', 'IDS_TEST1.png.sha1'), 'binary', ''),
         MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
-                 self.VALID_SHA1, ''),
+                 'binary', ''),
         # Deleted files:
         MockAffectedFile(
             os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
@@ -3819,19 +3761,19 @@
         # Deleted files:
         MockFile(
             os.path.join('test_grd', 'IDS_TEST1.png.sha1'),
-            self.VALID_SHA1,
+            'binary',
             action='D'),
         MockFile(
             os.path.join('test_grd', 'IDS_TEST2.png.sha1'),
-            self.VALID_SHA1,
+            'binary',
             action='D'),
         MockFile(
             os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'),
-            self.VALID_SHA1,
+            'binary',
             action='D'),
         MockFile(
             os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'),
-            self.VALID_SHA1,
+            'binary',
             action='D')
     ])
     warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi())
diff --git a/android_webview/browser/tracing/aw_tracing_delegate.cc b/android_webview/browser/tracing/aw_tracing_delegate.cc
index 0df8f96db..1ab7baf 100644
--- a/android_webview/browser/tracing/aw_tracing_delegate.cc
+++ b/android_webview/browser/tracing/aw_tracing_delegate.cc
@@ -37,8 +37,9 @@
 }
 
 bool AwTracingDelegate::IsAllowedToBeginBackgroundScenario(
-    const content::BackgroundTracingConfig& config,
-    bool requires_anonymized_data) {
+    const std::string& scenario_name,
+    bool requires_anonymized_data,
+    bool is_crash_scenario) {
   // If the background tracing is specified on the command-line, we allow
   // any scenario to be traced and uploaded.
   if (IsBackgroundTracingCommandLine())
@@ -67,7 +68,7 @@
 
   // Check the trace limit both when starting and ending a scenario
   // because there is no point starting a trace that can't be uploaded.
-  if (state.DidRecentlyUploadForScenario(config)) {
+  if (state.DidRecentlyUploadForScenario(scenario_name)) {
     tracing::RecordDisallowedMetric(
         tracing::TracingFinalizationDisallowedReason::kTraceUploadedRecently);
     return false;
@@ -78,7 +79,7 @@
 }
 
 bool AwTracingDelegate::IsAllowedToEndBackgroundScenario(
-    const content::BackgroundTracingConfig& config,
+    const std::string& scenario_name,
     bool requires_anonymized_data,
     bool is_crash_scenario) {
   // If the background tracing is specified on the command-line, we allow
@@ -92,13 +93,13 @@
 
   // Check the trace limit both when starting and ending a scenario
   // because there is no point starting a trace that can't be uploaded.
-  if (state.DidRecentlyUploadForScenario(config)) {
+  if (state.DidRecentlyUploadForScenario(scenario_name)) {
     tracing::RecordDisallowedMetric(
         tracing::TracingFinalizationDisallowedReason::kTraceUploadedRecently);
     return false;
   }
 
-  state.OnScenarioUploaded(config.scenario_name());
+  state.OnScenarioUploaded(scenario_name);
   return true;
 }
 
diff --git a/android_webview/browser/tracing/aw_tracing_delegate.h b/android_webview/browser/tracing/aw_tracing_delegate.h
index 3c968f4..c9fe585 100644
--- a/android_webview/browser/tracing/aw_tracing_delegate.h
+++ b/android_webview/browser/tracing/aw_tracing_delegate.h
@@ -24,13 +24,12 @@
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
   // content::TracingDelegate implementation:
-  bool IsAllowedToBeginBackgroundScenario(
-      const content::BackgroundTracingConfig& config,
-      bool requires_anonymized_data) override;
-  bool IsAllowedToEndBackgroundScenario(
-      const content::BackgroundTracingConfig& config,
-      bool requires_anonymized_data,
-      bool is_crash_scenario) override;
+  bool IsAllowedToBeginBackgroundScenario(const std::string& scenario_name,
+                                          bool requires_anonymized_data,
+                                          bool is_crash_scenario) override;
+  bool IsAllowedToEndBackgroundScenario(const std::string& scenario_name,
+                                        bool requires_anonymized_data,
+                                        bool is_crash_scenario) override;
   absl::optional<base::Value::Dict> GenerateMetadataDict() override;
 };
 
diff --git a/android_webview/browser/tracing/aw_tracing_delegate_unittest.cc b/android_webview/browser/tracing/aw_tracing_delegate_unittest.cc
index 6603a385..318b66f 100644
--- a/android_webview/browser/tracing/aw_tracing_delegate_unittest.cc
+++ b/android_webview/browser/tracing/aw_tracing_delegate_unittest.cc
@@ -70,9 +70,10 @@
   auto config = CreateValidConfig();
 
   EXPECT_TRUE(delegate_.IsAllowedToBeginBackgroundScenario(
-      *config, /*requires_anonymized_data=*/false));
+      config->scenario_name(), /*requires_anonymized_data=*/false,
+      /*is_crash_scenario=*/false));
   EXPECT_TRUE(delegate_.IsAllowedToEndBackgroundScenario(
-      *config, /*requires_anonymized_data=*/false,
+      config->scenario_name(), /*requires_anonymized_data=*/false,
       /*is_crash_scenario=*/false));
 }
 
@@ -86,7 +87,8 @@
   auto config = CreateValidConfig();
 
   EXPECT_FALSE(delegate_.IsAllowedToBeginBackgroundScenario(
-      *config, /*requires_anonymized_data=*/false));
+      config->scenario_name(), /*requires_anonymized_data=*/false,
+      /*is_crash_scenario=*/false));
 }
 
 TEST_F(AwTracingDelegateTest, IsAllowedToBeginRecentlyUploaded) {
@@ -96,7 +98,8 @@
 
   auto config = CreateValidConfig();
   EXPECT_FALSE(delegate_.IsAllowedToBeginBackgroundScenario(
-      *config, /*requires_anonymized_data=*/false));
+      config->scenario_name(), /*requires_anonymized_data=*/false,
+      /*is_crash_scenario=*/false));
 }
 
 TEST_F(AwTracingDelegateTest, IsAllowedToEndRecentlyUploaded) {
@@ -106,8 +109,8 @@
 
   auto config = CreateValidConfig();
   EXPECT_FALSE(delegate_.IsAllowedToEndBackgroundScenario(
-      *config, /*requires_anonymized_data=*/false,
-      /*is_crash_scenario*/ false));
+      config->scenario_name(), /*requires_anonymized_data=*/false,
+      /*is_crash_scenario=*/false));
 }
 
 }  // namespace android_webview
\ No newline at end of file
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index f3a307f..157474b9 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1075,10 +1075,6 @@
     "style/color_util.h",
     "style/dark_light_mode_controller_impl.cc",
     "style/dark_light_mode_controller_impl.h",
-    "style/dark_light_mode_nudge.cc",
-    "style/dark_light_mode_nudge.h",
-    "style/dark_light_mode_nudge_controller.cc",
-    "style/dark_light_mode_nudge_controller.h",
     "style/default_color_constants.h",
     "style/default_colors.cc",
     "style/default_colors.h",
@@ -2265,6 +2261,8 @@
     "wm/float/scoped_window_tucker.h",
     "wm/float/tablet_mode_float_window_resizer.cc",
     "wm/float/tablet_mode_float_window_resizer.h",
+    "wm/float/tablet_mode_tuck_education.cc",
+    "wm/float/tablet_mode_tuck_education.h",
     "wm/fullscreen_window_finder.cc",
     "wm/fullscreen_window_finder.h",
     "wm/gestures/back_gesture/back_gesture_affordance.cc",
@@ -3100,7 +3098,6 @@
     "style/color_palette_controller_unittest.cc",
     "style/color_util_unittest.cc",
     "style/dark_light_mode_controller_unittests.cc",
-    "style/dark_light_mode_nudge_controller_unittests.cc",
     "style/system_components_unittests.cc",
     "system/accessibility/accessibility_detailed_view_unittest.cc",
     "system/accessibility/accessibility_feature_pod_controller_unittest.cc",
diff --git a/ash/ambient/ambient_video_ui_launcher.cc b/ash/ambient/ambient_video_ui_launcher.cc
index 6613b825..7bdd3c7 100644
--- a/ash/ambient/ambient_video_ui_launcher.cc
+++ b/ash/ambient/ambient_video_ui_launcher.cc
@@ -5,6 +5,7 @@
 #include "ash/ambient/ambient_video_ui_launcher.h"
 
 #include "ash/ambient/ambient_ui_settings.h"
+#include "ash/ambient/ui/ambient_video_utils.h"
 #include "ash/ambient/ui/ambient_video_view.h"
 #include "ash/public/cpp/personalization_app/time_of_day_paths.h"
 #include "base/check.h"
@@ -22,27 +23,13 @@
 namespace ash {
 namespace {
 
-base::FilePath GetVideoFilePath(AmbientVideo video) {
-  base::StringPiece ambient_video_name;
-  switch (video) {
-    case AmbientVideo::kNewMexico:
-      ambient_video_name = personalization_app::kTimeOfDayNewMexicoVideo;
-      break;
-    case AmbientVideo::kClouds:
-      ambient_video_name = personalization_app::kTimeOfDayCloudsVideo;
-      break;
-  }
-  return personalization_app::GetTimeOfDayVideosDir().Append(
-      ambient_video_name);
-}
-
 base::FilePath GetVideoHtmlPath() {
   return personalization_app::GetTimeOfDaySrcDir().Append(
       personalization_app::kAmbientVideoHtml);
 }
 
 void VerifyVideoExistsOnDisc(AmbientVideo video) {
-  bool all_resources_exists = base::PathExists(GetVideoFilePath(video)) &&
+  bool all_resources_exists = base::PathExists(GetAmbientVideoPath(video)) &&
                               base::PathExists(GetVideoHtmlPath());
   // Currently, all resources are shipped with the OTA and reside on rootfs, so
   // this should never be true unless there is a major bug.
@@ -56,7 +43,7 @@
   // getting downloaded at run-time.
   if (!all_resources_exists) {
     LOG(ERROR) << "Ambient video resources do not exist on disc. video="
-               << GetVideoFilePath(video) << " src=" << GetVideoHtmlPath();
+               << GetAmbientVideoPath(video) << " src=" << GetVideoHtmlPath();
   }
 }
 
@@ -88,7 +75,7 @@
 
 std::unique_ptr<views::View> AmbientVideoUiLauncher::CreateView() {
   CHECK(is_active_);
-  return std::make_unique<AmbientVideoView>(GetVideoFilePath(current_video_),
+  return std::make_unique<AmbientVideoView>(GetAmbientVideoPath(current_video_),
                                             GetVideoHtmlPath());
 }
 
diff --git a/ash/ambient/backdrop/ambient_backend_controller_impl.h b/ash/ambient/backdrop/ambient_backend_controller_impl.h
index 74149aa6..c75793b 100644
--- a/ash/ambient/backdrop/ambient_backend_controller_impl.h
+++ b/ash/ambient/backdrop/ambient_backend_controller_impl.h
@@ -35,14 +35,8 @@
       OnScreenUpdateInfoFetchedCallback callback) override;
   void FetchPreviewImages(const gfx::Size& preview_size,
                           OnPreviewImagesFetchedCallback callback) override;
-  void GetSettings(GetSettingsCallback callback) override;
   void UpdateSettings(const AmbientSettings& settings,
                       UpdateSettingsCallback callback) override;
-  void FetchPersonalAlbums(int banner_width,
-                           int banner_height,
-                           int num_albums,
-                           const std::string& resume_token,
-                           OnPersonalAlbumsFetchedCallback callback) override;
   void FetchSettingsAndAlbums(
       int banner_width,
       int banner_height,
@@ -53,6 +47,11 @@
 
  private:
   using BackdropClientConfig = chromeos::ambient::BackdropClientConfig;
+  using GetSettingsCallback =
+      base::OnceCallback<void(const absl::optional<AmbientSettings>& settings)>;
+  using OnPersonalAlbumsFetchedCallback =
+      base::OnceCallback<void(PersonalAlbums)>;
+
   void RequestAccessToken(AmbientClient::GetAccessTokenCallback callback);
 
   void FetchScreenUpdateInfoInternal(int num_topics,
@@ -67,6 +66,7 @@
       std::unique_ptr<BackdropURLLoader> backdrop_url_loader,
       std::unique_ptr<std::string> response);
 
+  void GetSettings(GetSettingsCallback callback);
   void StartToGetSettings(GetSettingsCallback callback,
                           const std::string& gaia_id,
                           const std::string& access_token);
@@ -85,6 +85,12 @@
                         std::unique_ptr<BackdropURLLoader> backdrop_url_loader,
                         std::unique_ptr<std::string> response);
 
+  void FetchPersonalAlbums(int banner_width,
+                           int banner_height,
+                           int num_albums,
+                           const std::string& resume_token,
+                           OnPersonalAlbumsFetchedCallback callback);
+
   void FetchPersonalAlbumsInternal(int banner_width,
                                    int banner_height,
                                    int num_albums,
diff --git a/ash/app_list/views/app_list_view_pixeltest.cc b/ash/app_list/views/app_list_view_pixeltest.cc
index dda73129..6b71d6287 100644
--- a/ash/app_list/views/app_list_view_pixeltest.cc
+++ b/ash/app_list/views/app_list_view_pixeltest.cc
@@ -10,6 +10,8 @@
 #include "ash/app_list/views/apps_container_view.h"
 #include "ash/app_list/views/apps_grid_view_test_api.h"
 #include "ash/app_list/views/search_box_view.h"
+#include "ash/assistant/test/assistant_ash_test_base.h"
+#include "ash/public/cpp/style/dark_light_mode_controller.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_navigation_widget.h"
 #include "ash/shell.h"
@@ -186,19 +188,44 @@
       GetPrimaryShelf()->navigation_widget()));
 }
 
+class LauncherSearchIphParams {
+ public:
+  LauncherSearchIphParams(bool rtl, bool dark_theme)
+      : rtl_(rtl), dark_theme_(dark_theme) {}
+
+  static std::string ToTestSuffix(
+      const testing::TestParamInfo<LauncherSearchIphParams>& info) {
+    std::string suffix;
+    suffix.append(info.param.rtl() ? "rtl" : "ltr");
+    suffix.append("_");
+    suffix.append(info.param.dark_theme() ? "dark" : "light");
+    return suffix;
+  }
+
+  bool rtl() const { return rtl_; }
+  bool dark_theme() const { return dark_theme_; }
+
+ private:
+  bool rtl_;
+  bool dark_theme_;
+};
+
 class AppListViewLauncherSearchIphTest
-    : public AshTestBase,
-      public testing::WithParamInterface</*rtl=*/bool> {
+    : public AssistantAshTestBase,
+      public testing::WithParamInterface<LauncherSearchIphParams> {
  public:
   absl::optional<pixel_test::InitParams> CreatePixelTestInitParams()
       const override {
     pixel_test::InitParams init_params;
-    init_params.under_rtl = GetParam();
+    init_params.under_rtl = GetParam().rtl();
     return init_params;
   }
 
   void SetUp() override {
-    AshTestBase::SetUp();
+    AssistantAshTestBase::SetUp();
+
+    DarkLightModeController::Get()->SetDarkModeEnabledForTest(
+        GetParam().dark_theme());
 
     AppListTestHelper* test_helper = GetAppListTestHelper();
     test_helper->ShowAppList();
@@ -210,7 +237,11 @@
 
 INSTANTIATE_TEST_SUITE_P(RTL,
                          AppListViewLauncherSearchIphTest,
-                         testing::Bool());
+                         testing::Values(LauncherSearchIphParams(false, false),
+                                         LauncherSearchIphParams(false, true),
+                                         LauncherSearchIphParams(true, false),
+                                         LauncherSearchIphParams(true, true)),
+                         &LauncherSearchIphParams::ToTestSuffix);
 
 TEST_P(AppListViewLauncherSearchIphTest, Basic) {
   // Wait re-layout for adding IPH view.
diff --git a/ash/app_list/views/launcher_search_iph_view.cc b/ash/app_list/views/launcher_search_iph_view.cc
index 173ad97..37c7921 100644
--- a/ash/app_list/views/launcher_search_iph_view.cc
+++ b/ash/app_list/views/launcher_search_iph_view.cc
@@ -8,11 +8,17 @@
 #include <string>
 #include <utility>
 
+#include "ash/assistant/ui/main_stage/chip_view.h"
 #include "ash/public/cpp/app_list/app_list_client.h"
+#include "ash/style/ash_color_id.h"
 #include "ash/style/pill_button.h"
+#include "ash/style/typography.h"
 #include "base/functional/bind.h"
+#include "base/i18n/rtl.h"
+#include "ui/color/color_id.h"
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/text_constants.h"
+#include "ui/views/background.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
@@ -23,9 +29,6 @@
 constexpr int kVerticalInset = 20;
 constexpr int kHorizontalInset = 24;
 
-constexpr int kTitleTextFontSize = 20;
-constexpr int kDescriptionTextFontSize = 16;
-
 constexpr int kMainLayoutBetweenChildSpacing = 16;
 constexpr int kActionContainerBetweenChildSpacing = 8;
 
@@ -37,6 +40,17 @@
 constexpr char16_t kChipThreeQueryPlaceholder[] = u"5 cm in inches";
 
 constexpr char16_t kAssistantButtonPlaceholder[] = u"Assistant";
+
+constexpr views::Radii kBackgroundRadiiLTR = {.top_left = 16.0f,
+                                              .top_right = 4.0f,
+                                              .bottom_right = 16.0f,
+                                              .bottom_left = 16.0f};
+
+constexpr views::Radii kBackgroundRadiiRTL = {.top_left = 4.0f,
+                                              .top_right = 16.0f,
+                                              .bottom_right = 16.0f,
+                                              .bottom_left = 16.0f};
+
 }  // namespace
 
 LauncherSearchIphView::LauncherSearchIphView(
@@ -64,18 +78,23 @@
 
   raw_ptr<views::Label> title_label = text_container->AddChildView(
       std::make_unique<views::Label>(kTitleTextPlaceholder));
-  title_label->SetFontList(gfx::FontList().DeriveWithSizeDelta(
-      kTitleTextFontSize - gfx::FontList().GetFontSize()));
-  title_label->SetLineHeight(kTitleTextFontSize);
   title_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_TO_HEAD);
+  title_label->SetEnabledColorId(kColorAshTextColorPrimary);
 
   raw_ptr<views::Label> description_label = text_container->AddChildView(
       std::make_unique<views::Label>(kDescriptionTextPlaceholder));
-  description_label->SetFontList(gfx::FontList().DeriveWithSizeDelta(
-      kDescriptionTextFontSize - gfx::FontList().GetFontSize()));
-  description_label->SetLineHeight(kDescriptionTextFontSize);
   description_label->SetHorizontalAlignment(
       gfx::HorizontalAlignment::ALIGN_TO_HEAD);
+  description_label->SetEnabledColorId(kColorAshTextColorPrimary);
+
+  raw_ptr<const TypographyProvider> typography_provider =
+      TypographyProvider::Get();
+  DCHECK(typography_provider) << "TypographyProvider must not be null";
+  if (typography_provider) {
+    typography_provider->StyleLabel(TypographyToken::kCrosTitle1, *title_label);
+    typography_provider->StyleLabel(TypographyToken::kCrosBody2,
+                                    *description_label);
+  }
 
   raw_ptr<views::BoxLayoutView> actions_container =
       AddChildView(std::make_unique<views::BoxLayoutView>());
@@ -87,11 +106,12 @@
   for (const std::u16string& query :
        {kChipOneQueryPlaceholder, kChipTwoQueryPlaceholder,
         kChipThreeQueryPlaceholder}) {
-    raw_ptr<ash::PillButton> chip =
-        actions_container->AddChildView(std::make_unique<ash::PillButton>(
-            base::BindRepeating(&LauncherSearchIphView::RunLauncherSearchQuery,
-                                weak_ptr_factory_.GetWeakPtr(), query),
-            query));
+    raw_ptr<ChipView> chip = actions_container->AddChildView(
+        std::make_unique<ChipView>(ChipView::Type::kLarge));
+    chip->SetText(query);
+    chip->SetCallback(
+        base::BindRepeating(&LauncherSearchIphView::RunLauncherSearchQuery,
+                            weak_ptr_factory_.GetWeakPtr(), query));
     chip->SetID(query_chip_view_id);
     query_chip_view_id++;
   }
@@ -106,6 +126,13 @@
                               weak_ptr_factory_.GetWeakPtr()),
           kAssistantButtonPlaceholder));
   assistant_button->SetID(ViewId::kAssistant);
+  assistant_button->SetPillButtonType(
+      PillButton::Type::kDefaultLargeWithoutIcon);
+
+  SetBackground(views::CreateThemedRoundedRectBackground(
+      kColorAshControlBackgroundColorInactive,
+      base::i18n::IsRTL() ? kBackgroundRadiiRTL : kBackgroundRadiiLTR,
+      /*for_border_thickness=*/0));
 }
 
 LauncherSearchIphView::~LauncherSearchIphView() = default;
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc
index d930db5..698d2e4 100644
--- a/ash/app_list/views/search_box_view.cc
+++ b/ash/app_list/views/search_box_view.cc
@@ -30,6 +30,7 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/style/ash_color_id.h"
 #include "ash/style/ash_color_provider.h"
+#include "base/i18n/rtl.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
@@ -54,6 +55,7 @@
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/background.h"
 #include "ui/views/border.h"
 #include "ui/views/context_menu_controller.h"
 #include "ui/views/controls/button/image_button.h"
@@ -104,6 +106,20 @@
     SearchBoxView::PlaceholderTextType::kGames,
 };
 
+constexpr views::Radii kAssistantButtonBackgroundRadiiLTR = {
+    .top_left = 18.0f,
+    .top_right = 18.0f,
+    .bottom_right = 4.0f,
+    .bottom_left = 18.0f,
+};
+
+constexpr views::Radii kAssistantButtonBackgroundRadiiRTL = {
+    .top_left = 18.0f,
+    .top_right = 18.0f,
+    .bottom_right = 18.0f,
+    .bottom_left = 4.0f,
+};
+
 bool IsTrimmedQueryEmpty(const std::u16string& query) {
   std::u16string trimmed_query;
   base::TrimWhitespace(query, base::TrimPositions::TRIM_ALL, &trimmed_query);
@@ -1223,15 +1239,25 @@
                              ->search_model()
                              ->search_box()
                              ->show_assistant_button());
+
+  // `LauncherSearchIphView` and an Assistant button have synchronized
+  // backgrounds. The IPH UI is integrated with the Assistant button. We don't
+  // show an IPH if Assistant is disabled. Both `LauncherSearchIphView` and the
+  // Assistant button are hosted by `SearchBoxViewBase`.
+  UpdateIphViewVisibility();
 }
 
 void SearchBoxView::UpdateIphViewVisibility() {
+  const bool show_assistant_button = AppListModelProvider::Get()
+                                         ->search_model()
+                                         ->search_box()
+                                         ->show_assistant_button();
   const bool would_trigger_iph =
       AppListModelProvider::Get()->search_model()->would_trigger_iph();
   const bool is_iph_showing = iph_view() != nullptr;
 
-  const bool should_show_iph =
-      is_iph_allowed_ && (would_trigger_iph || is_iph_showing);
+  const bool should_show_iph = show_assistant_button && is_iph_allowed_ &&
+                               (would_trigger_iph || is_iph_showing);
 
   if (should_show_iph == is_iph_showing) {
     return;
@@ -1246,8 +1272,15 @@
 
     SetIphView(std::make_unique<LauncherSearchIphView>(
         std::move(scoped_iph_session), /*delegate=*/this));
+
+    assistant_button()->SetBackground(views::CreateThemedRoundedRectBackground(
+        kColorAshControlBackgroundColorInactive,
+        base::i18n::IsRTL() ? kAssistantButtonBackgroundRadiiRTL
+                            : kAssistantButtonBackgroundRadiiLTR,
+        /*for_border_thickness=*/0));
   } else {
     DeleteIphView();
+    assistant_button()->SetBackground(nullptr);
   }
 }
 
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 082a6fc..29337b0c 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -6462,6 +6462,11 @@
 
 To shut down the device, press and hold the power button on the device again.
       </message>
-    </messages>
-  </release>
+
+       <!-- Tuck Education -->
+      <message name="IDS_ASH_TUCK_EDUCATIONAL_NUDGE_LABEL" desc="The text shown to users when a window is floated in tablet mode to indicate the tuck gesture." >
+        Swipe to hide your floating window
+      </message>
+     </messages>
+    </release>
 </grit>
diff --git a/ash/ash_strings_grd/IDS_ASH_TUCK_EDUCATIONAL_NUDGE_LABEL.png.sha1 b/ash/ash_strings_grd/IDS_ASH_TUCK_EDUCATIONAL_NUDGE_LABEL.png.sha1
new file mode 100644
index 0000000..e0cd5fa
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_TUCK_EDUCATIONAL_NUDGE_LABEL.png.sha1
@@ -0,0 +1 @@
+0050a11809ee6464fa630187e23b8ffb4a77113f
\ No newline at end of file
diff --git a/ash/assistant/ui/main_stage/chip_view.cc b/ash/assistant/ui/main_stage/chip_view.cc
index 0bb3b13..0fcd9ac 100644
--- a/ash/assistant/ui/main_stage/chip_view.cc
+++ b/ash/assistant/ui/main_stage/chip_view.cc
@@ -9,6 +9,7 @@
 #include "ash/assistant/ui/assistant_ui_constants.h"
 #include "ash/assistant/ui/assistant_view_ids.h"
 #include "ash/style/ash_color_id.h"
+#include "ash/style/typography.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_provider.h"
@@ -33,10 +34,11 @@
 
 constexpr int kIconMarginDip = 8;
 constexpr int kChipPaddingDip = 16;
-constexpr int kPreferredHeightDip = 32;
+constexpr int kPreferredHeightDipDefault = 32;
+constexpr int kPreferredHeightDipLarge = 36;
 }  // namespace
 
-ChipView::ChipView() {
+ChipView::ChipView(Type type) : type_(type) {
   // Focus.
   // 1. Dark light mode is OFF
   // We change background color of a suggestion chip view. No focus ring is
@@ -77,9 +79,25 @@
   text_view_->SetID(kSuggestionChipViewLabel);
   text_view_->SetAutoColorReadabilityEnabled(false);
   text_view_->SetSubpixelRenderingEnabled(false);
-  const gfx::FontList& font_list = assistant::ui::GetDefaultFontList();
-  text_view_->SetFontList(font_list.Derive(
-      /*size_delta=*/1, font_list.GetFontStyle(), gfx::Font::Weight::MEDIUM));
+
+  switch (type_) {
+    case Type::kDefault: {
+      const gfx::FontList& font_list = assistant::ui::GetDefaultFontList();
+      text_view_->SetFontList(font_list.Derive(
+          /*size_delta=*/1, font_list.GetFontStyle(),
+          gfx::Font::Weight::MEDIUM));
+      break;
+    }
+    case Type::kLarge: {
+      raw_ptr<const TypographyProvider> typography_provider =
+          TypographyProvider::Get();
+      DCHECK(typography_provider) << "TypographyProvider must not be null";
+      if (typography_provider) {
+        typography_provider->StyleLabel(TypographyToken::kCrosButton1,
+                                        *text_view_);
+      }
+    } break;
+  }
 }
 
 ChipView::~ChipView() = default;
@@ -90,7 +108,8 @@
 }
 
 int ChipView::GetHeightForWidth(int width) const {
-  return kPreferredHeightDip;
+  return type_ == Type::kDefault ? kPreferredHeightDipDefault
+                                 : kPreferredHeightDipLarge;
 }
 
 void ChipView::ChildVisibilityChanged(views::View* child) {
diff --git a/ash/assistant/ui/main_stage/chip_view.h b/ash/assistant/ui/main_stage/chip_view.h
index 0f91d94..d208a2c 100644
--- a/ash/assistant/ui/main_stage/chip_view.h
+++ b/ash/assistant/ui/main_stage/chip_view.h
@@ -17,9 +17,11 @@
 
 class COMPONENT_EXPORT(ASSISTANT_UI) ChipView : public views::Button {
  public:
+  enum Type { kDefault, kLarge };
+
   static constexpr int kIconSizeDip = 16;
 
-  ChipView();
+  explicit ChipView(Type type);
   ~ChipView() override;
 
   // views::View:
@@ -42,6 +44,7 @@
   METADATA_HEADER(ChipView);
 
  private:
+  const Type type_;
   raw_ptr<views::BoxLayout> layout_manager_;
   raw_ptr<views::ImageView> icon_view_;
   raw_ptr<views::Label> text_view_;
diff --git a/ash/assistant/ui/main_stage/suggestion_chip_view.cc b/ash/assistant/ui/main_stage/suggestion_chip_view.cc
index 4da49ec8..bd19d93b 100644
--- a/ash/assistant/ui/main_stage/suggestion_chip_view.cc
+++ b/ash/assistant/ui/main_stage/suggestion_chip_view.cc
@@ -20,7 +20,9 @@
 
 SuggestionChipView::SuggestionChipView(AssistantViewDelegate* delegate,
                                        const AssistantSuggestion& suggestion)
-    : delegate_(delegate), suggestion_id_(suggestion.id) {
+    : ChipView(Type::kDefault),
+      delegate_(delegate),
+      suggestion_id_(suggestion.id) {
   SetText(base::UTF8ToUTF16(suggestion.text));
 
   const GURL& url = suggestion.icon_url;
diff --git a/ash/clipboard/clipboard_history_controller_impl.cc b/ash/clipboard/clipboard_history_controller_impl.cc
index 9070a1a9..bb7a7f0c 100644
--- a/ash/clipboard/clipboard_history_controller_impl.cc
+++ b/ash/clipboard/clipboard_history_controller_impl.cc
@@ -344,6 +344,8 @@
   if (active_menu_instance)
     active_menu_instance->Cancel(views::MenuController::ExitType::kAll);
 
+  last_menu_source_ = show_source;
+
   // `Unretained()` is safe because `this` owns `context_menu_`.
   context_menu_ = ClipboardHistoryMenuModelAdapter::Create(
       menu_delegate_.get(), std::move(callback),
@@ -544,7 +546,8 @@
           base::BindOnce(
               &ClipboardHistoryControllerImpl::PasteClipboardHistoryItem,
               weak_ptr_factory_.GetWeakPtr(), active_window, item,
-              ClipboardHistoryPasteType::kRichTextVirtualKeyboard));
+              ClipboardHistoryPasteType::kRichTextVirtualKeyboard,
+              last_menu_source_));
       return true;
     }
   }
@@ -756,13 +759,14 @@
       FROM_HERE,
       base::BindOnce(&ClipboardHistoryControllerImpl::PasteClipboardHistoryItem,
                      weak_ptr_factory_.GetWeakPtr(), active_window,
-                     selected_item, paste_type));
+                     selected_item, paste_type, last_menu_source_));
 }
 
 void ClipboardHistoryControllerImpl::PasteClipboardHistoryItem(
     aura::Window* intended_window,
     ClipboardHistoryItem item,
-    ClipboardHistoryPasteType paste_type) {
+    ClipboardHistoryPasteType paste_type,
+    crosapi::mojom::ClipboardHistoryControllerShowSource paste_source) {
   // It's possible that the window could change or we could enter a disabled
   // mode after posting the `PasteClipboardHistoryItem()` task.
   if (!intended_window || intended_window != window_util::GetActiveWindow() ||
@@ -839,6 +843,8 @@
 
   clipboard_history_util::RecordClipboardHistoryItemPasted(item);
   base::UmaHistogramEnumeration("Ash.ClipboardHistory.PasteType", paste_type);
+  base::UmaHistogramEnumeration("Ash.ClipboardHistory.PasteSource",
+                                paste_source);
 
   for (auto& observer : observers_)
     observer.OnClipboardHistoryPasted();
diff --git a/ash/clipboard/clipboard_history_controller_impl.h b/ash/clipboard/clipboard_history_controller_impl.h
index 934fc154..4c6cf85 100644
--- a/ash/clipboard/clipboard_history_controller_impl.h
+++ b/ash/clipboard/clipboard_history_controller_impl.h
@@ -190,13 +190,16 @@
   // Paste the clipboard data of the menu item specified by `command_id`.
   void PasteMenuItemData(int command_id, ClipboardHistoryPasteType paste_type);
 
-  // Pastes the specified clipboard history item, if |intended_window| matches
-  // the active window. `paste_type` indicates the source of the paste for
+  // Pastes the specified clipboard history item, if `intended_window` matches
+  // the active window. `paste_type` indicates the mode of paste execution for
   // metrics tracking as well as whether plain text should be pasted instead of
-  // the full, rich-text clipboard data.
-  void PasteClipboardHistoryItem(aura::Window* intended_window,
-                                 ClipboardHistoryItem item,
-                                 ClipboardHistoryPasteType paste_type);
+  // the full, rich-text clipboard data. `paste_source` indicates how the user
+  // triggered the menu from which `item` was selected.
+  void PasteClipboardHistoryItem(
+      aura::Window* intended_window,
+      ClipboardHistoryItem item,
+      ClipboardHistoryPasteType paste_type,
+      crosapi::mojom::ClipboardHistoryControllerShowSource paste_source);
 
   // Delete the menu item being selected and its corresponding data. If no item
   // is selected, do nothing.
@@ -236,6 +239,9 @@
   // Controller that shows contextual nudges for multipaste.
   std::unique_ptr<ClipboardNudgeController> nudge_controller_;
 
+  // How the user last caused `context_menu_` to show.
+  crosapi::mojom::ClipboardHistoryControllerShowSource last_menu_source_;
+
   // Whether a paste is currently being performed.
   bool currently_pasting_ = false;
 
diff --git a/ash/clipboard/clipboard_history_controller_unittest.cc b/ash/clipboard/clipboard_history_controller_unittest.cc
index b988dbf..5aa782c 100644
--- a/ash/clipboard/clipboard_history_controller_unittest.cc
+++ b/ash/clipboard/clipboard_history_controller_unittest.cc
@@ -36,6 +36,7 @@
 #include "ui/views/controls/button/label_button.h"
 
 namespace ash {
+using crosapi::mojom::ClipboardHistoryControllerShowSource;
 
 namespace {
 
@@ -86,6 +87,18 @@
                                    expected_bitmap));
 }
 
+std::vector<ClipboardHistoryControllerShowSource>
+GetClipboardHistoryShowSources() {
+  std::vector<ClipboardHistoryControllerShowSource> sources;
+  for (int i =
+           static_cast<int>(ClipboardHistoryControllerShowSource::kMinValue);
+       i <= static_cast<int>(ClipboardHistoryControllerShowSource::kMaxValue);
+       ++i) {
+    sources.push_back(static_cast<ClipboardHistoryControllerShowSource>(i));
+  }
+  return sources;
+}
+
 }  // namespace
 
 class ClipboardHistoryControllerTest : public AshTestBase {
@@ -235,84 +248,6 @@
       "Ash.ClipboardHistory.ContextMenu.UserJourneyTime", 2);
 }
 
-// Tests that `ShowMenu()` returns whether the menu was shown successfully.
-TEST_F(ClipboardHistoryControllerTest, ShowMenuReturnsSuccess) {
-  // Try to show the menu without populating the clipboard. The menu should not
-  // show.
-  EXPECT_FALSE(GetClipboardHistoryController()->ShowMenu(
-      gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE,
-      crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown));
-  EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing());
-
-  // Copy something to enable the clipboard history menu.
-  WriteTextToClipboardAndConfirm(u"test");
-
-  // Try to show the menu with the screen locked. The menu should not show.
-  auto* session_controller = Shell::Get()->session_controller();
-  session_controller->LockScreen();
-  GetSessionControllerClient()->FlushForTest();
-  EXPECT_TRUE(session_controller->IsScreenLocked());
-
-  EXPECT_FALSE(GetClipboardHistoryController()->ShowMenu(
-      gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE,
-      crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown));
-  EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing());
-
-  session_controller->HideLockScreen();
-  GetSessionControllerClient()->FlushForTest();
-  EXPECT_FALSE(session_controller->IsScreenLocked());
-
-  // Show the menu.
-  EXPECT_TRUE(GetClipboardHistoryController()->ShowMenu(
-      gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE,
-      crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown));
-  EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing());
-
-  // Try to show the menu again without closing the active menu. The menu should
-  // still be showing, but this attempt should fail.
-  EXPECT_FALSE(GetClipboardHistoryController()->ShowMenu(
-      gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE,
-      crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown));
-  EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing());
-}
-
-// Tests that the client-provided `OnMenuClosingCallback` runs before the menu
-// closes.
-TEST_F(ClipboardHistoryControllerTest, OnMenuClosingCallback) {
-  base::test::RepeatingTestFuture<bool> on_menu_closing_future;
-  // Copy something to enable the clipboard history menu.
-  WriteTextToClipboardAndConfirm(u"test");
-
-  gfx::Rect test_window_rect(100, 100, 100, 100);
-  std::unique_ptr<aura::Window> window(CreateTestWindow(test_window_rect));
-
-  // Show the menu with an `OnMenuClosingCallback`.
-  GetClipboardHistoryController()->ShowMenu(
-      test_window_rect, ui::MenuSourceType::MENU_SOURCE_NONE,
-      crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown,
-      on_menu_closing_future.GetCallback());
-  EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing());
-  EXPECT_TRUE(on_menu_closing_future.IsEmpty());
-
-  // Hide the menu. The callback should indicate that nothing will be pasted.
-  PressAndReleaseKey(ui::VKEY_ESCAPE);
-  EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing());
-  EXPECT_FALSE(on_menu_closing_future.Take());
-
-  // Show the menu again.
-  GetClipboardHistoryController()->ShowMenu(
-      test_window_rect, ui::MenuSourceType::MENU_SOURCE_NONE,
-      crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown,
-      on_menu_closing_future.GetCallback());
-  EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing());
-  EXPECT_TRUE(on_menu_closing_future.IsEmpty());
-
-  // Toggle the menu closed. The callback should indicate a pending paste.
-  PressAndReleaseKey(ui::VKEY_V, ui::EF_COMMAND_DOWN);
-  EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing());
-  EXPECT_TRUE(on_menu_closing_future.Take());
-}
-
 // Verifies that the clipboard history is disabled in some user modes, which
 // means that the clipboard history should not be recorded and meanwhile the
 // menu view should not show (https://crbug.com/1100739).
@@ -555,6 +490,112 @@
   TestEnteringLockScreen();
 }
 
+class ClipboardHistoryControllerShowSourceTest
+    : public ClipboardHistoryControllerTest,
+      public testing::WithParamInterface<ClipboardHistoryControllerShowSource> {
+ public:
+  ClipboardHistoryControllerShowSource GetSource() const { return GetParam(); }
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         ClipboardHistoryControllerShowSourceTest,
+                         testing::ValuesIn(GetClipboardHistoryShowSources()));
+
+// Tests that `ShowMenu()` returns whether the menu was shown successfully.
+TEST_P(ClipboardHistoryControllerShowSourceTest, ShowMenuReturnsSuccess) {
+  base::HistogramTester histogram_tester;
+
+  // Try to show the menu without populating the clipboard. The menu should not
+  // show.
+  EXPECT_FALSE(GetClipboardHistoryController()->ShowMenu(
+      gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE, GetSource()));
+  EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing());
+  histogram_tester.ExpectTotalCount("Ash.ClipboardHistory.ContextMenu.ShowMenu",
+                                    /*expected_count=*/0);
+
+  // Copy something to enable the clipboard history menu.
+  WriteTextToClipboardAndConfirm(u"test");
+
+  // Try to show the menu with the screen locked. The menu should not show.
+  auto* session_controller = Shell::Get()->session_controller();
+  session_controller->LockScreen();
+  GetSessionControllerClient()->FlushForTest();
+  EXPECT_TRUE(session_controller->IsScreenLocked());
+
+  EXPECT_FALSE(GetClipboardHistoryController()->ShowMenu(
+      gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE, GetSource()));
+  EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing());
+  histogram_tester.ExpectTotalCount("Ash.ClipboardHistory.ContextMenu.ShowMenu",
+                                    /*expected_count=*/0);
+
+  session_controller->HideLockScreen();
+  GetSessionControllerClient()->FlushForTest();
+  EXPECT_FALSE(session_controller->IsScreenLocked());
+
+  // Show the menu.
+  EXPECT_TRUE(GetClipboardHistoryController()->ShowMenu(
+      gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE, GetSource()));
+  EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing());
+  histogram_tester.ExpectUniqueSample(
+      "Ash.ClipboardHistory.ContextMenu.ShowMenu", GetSource(),
+      /*expected_bucket_count=*/1);
+
+  // Try to show the menu again without closing the active menu. The menu should
+  // still be showing, but this attempt should fail.
+  EXPECT_FALSE(GetClipboardHistoryController()->ShowMenu(
+      gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE, GetSource()));
+  EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing());
+  histogram_tester.ExpectUniqueSample(
+      "Ash.ClipboardHistory.ContextMenu.ShowMenu", GetSource(),
+      /*expected_bucket_count=*/1);
+}
+
+// Tests that the client-provided `OnMenuClosingCallback` runs before the menu
+// closes.
+TEST_P(ClipboardHistoryControllerShowSourceTest, OnMenuClosingCallback) {
+  base::test::RepeatingTestFuture<bool> on_menu_closing_future;
+  base::HistogramTester histogram_tester;
+
+  // Copy something to enable the clipboard history menu.
+  WriteTextToClipboardAndConfirm(u"test");
+
+  gfx::Rect test_window_rect(100, 100, 100, 100);
+  std::unique_ptr<aura::Window> window(CreateTestWindow(test_window_rect));
+
+  // Show the menu with an `OnMenuClosingCallback`.
+  GetClipboardHistoryController()->ShowMenu(
+      test_window_rect, ui::MenuSourceType::MENU_SOURCE_NONE, GetSource(),
+      on_menu_closing_future.GetCallback());
+  EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing());
+  EXPECT_TRUE(on_menu_closing_future.IsEmpty());
+
+  // Hide the menu. The callback should indicate that nothing will be pasted.
+  PressAndReleaseKey(ui::VKEY_ESCAPE);
+  EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing());
+  EXPECT_FALSE(on_menu_closing_future.Take());
+
+  FlushMessageLoop();
+  histogram_tester.ExpectTotalCount("Ash.ClipboardHistory.PasteSource",
+                                    /*expected_count=*/0);
+
+  // Show the menu again.
+  GetClipboardHistoryController()->ShowMenu(
+      test_window_rect, ui::MenuSourceType::MENU_SOURCE_NONE, GetSource(),
+      on_menu_closing_future.GetCallback());
+  EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing());
+  EXPECT_TRUE(on_menu_closing_future.IsEmpty());
+
+  // Toggle the menu closed. The callback should indicate a pending paste.
+  PressAndReleaseKey(ui::VKEY_V, ui::EF_COMMAND_DOWN);
+  EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing());
+  EXPECT_TRUE(on_menu_closing_future.Take());
+
+  FlushMessageLoop();
+  histogram_tester.ExpectUniqueSample("Ash.ClipboardHistory.PasteSource",
+                                      GetSource(),
+                                      /*expected_bucket_count=*/1);
+}
+
 // Base class for tests of Clipboard History parameterized by whether the
 // `kClipboardHistoryRefresh` feature flag is enabled.
 class ClipboardHistoryControllerRefreshTest
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 9cc8deb2..9470ea4 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -2016,7 +2016,7 @@
 // Enables the alternative emulator for the Terminal app.
 BASE_FEATURE(kTerminalAlternativeEmulator,
              "TerminalAlternativeEmulator",
-             base::FEATURE_ENABLED_BY_DEFAULT);
+             base::FEATURE_DISABLED_BY_DEFAULT);
 //
 // Enables Terminal System App to load from Downloads for developer testing.
 // Only works in dev and canary channels.
@@ -2228,7 +2228,7 @@
 // on ChromeOS.
 BASE_FEATURE(kDeviceActiveClient28DayActiveCheckIn,
              "DeviceActiveClient28DayActiveCheckIn",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Enables or disables PSM CheckMembership for 28 day device active pings
 // on ChromeOS.
diff --git a/ash/constants/ash_pref_names.cc b/ash/constants/ash_pref_names.cc
index 152996d..2ea15d5 100644
--- a/ash/constants/ash_pref_names.cc
+++ b/ash/constants/ash_pref_names.cc
@@ -760,15 +760,6 @@
 // color palette. It is an ARGB 32-bit unsigned integer stored as a uint64.
 const char kDynamicColorSeedColor[] = "ash.dynamic_color.seed_color";
 
-// An integer pref storing the number of times that dark/light mode educational
-// can still be shown. It will be initialized to the maximum number of times
-// that the nudge can be shown. And will be set to 0 if the user toggled the
-// entry points of dark/light mode ("Dark theme" inside quick settings or
-// personalization hub), which means the user already knows how to change the
-// color mode of the system.
-const char kDarkLightModeNudgeLeftToShowCount[] =
-    "ash.dark_light_mode.educational_nudge";
-
 // An integer pref storing the type of automatic scheduling of turning on and
 // off the dark mode feature similar to `kNightLightScheduleType`, but
 // custom scheduling (2) is the same as sunset to sunrise scheduling (1)
diff --git a/ash/constants/ash_pref_names.h b/ash/constants/ash_pref_names.h
index d904df68..34fc6177 100644
--- a/ash/constants/ash_pref_names.h
+++ b/ash/constants/ash_pref_names.h
@@ -367,8 +367,6 @@
 
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kAmbientColorEnabled[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kDarkModeEnabled[];
-COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const char kDarkLightModeNudgeLeftToShowCount[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kDarkModeScheduleType[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kNightLightEnabled[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kNightLightTemperature[];
diff --git a/ash/constants/ash_switches.cc b/ash/constants/ash_switches.cc
index 77f01f3..17762e6 100644
--- a/ash/constants/ash_switches.cc
+++ b/ash/constants/ash_switches.cc
@@ -791,6 +791,10 @@
 const char kOobeLargeScreenSpecialScaling[] =
     "oobe-large-screen-special-scaling";
 
+// When present, prints the time it takes for OOBE's frontend to load.
+// See go/oobe-frontend-trace-timings for details.
+const char kOobePrintFrontendLoadTimings[] = "oobe-print-frontend-load-timings";
+
 // Specifies directory for screenshots taken with OOBE UI Debugger.
 const char kOobeScreenshotDirectory[] = "oobe-screenshot-dir";
 
diff --git a/ash/constants/ash_switches.h b/ash/constants/ash_switches.h
index ad835de7..5289bc7 100644
--- a/ash/constants/ash_switches.h
+++ b/ash/constants/ash_switches.h
@@ -257,6 +257,8 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kOobeForceTabletFirstRun[];
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kOobeLargeScreenSpecialScaling[];
+COMPONENT_EXPORT(ASH_CONSTANTS)
+extern const char kOobePrintFrontendLoadTimings[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kOobeScreenshotDirectory[];
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kOobeShowAccessibilityButtonOnMarketingOptInForTesting[];
diff --git a/ash/public/cpp/ambient/ambient_backend_controller.h b/ash/public/cpp/ambient/ambient_backend_controller.h
index 198cd42..c9ca979f 100644
--- a/ash/public/cpp/ambient/ambient_backend_controller.h
+++ b/ash/public/cpp/ambient/ambient_backend_controller.h
@@ -96,11 +96,7 @@
       base::OnceCallback<void(const ScreenUpdate&)>;
   using OnPreviewImagesFetchedCallback =
       base::OnceCallback<void(const std::vector<GURL>& preview_urls)>;
-  using GetSettingsCallback =
-      base::OnceCallback<void(const absl::optional<AmbientSettings>& settings)>;
   using UpdateSettingsCallback = base::OnceCallback<void(bool success)>;
-  using OnPersonalAlbumsFetchedCallback =
-      base::OnceCallback<void(PersonalAlbums)>;
   // TODO(wutao): Make |settings| move only.
   using OnSettingsAndAlbumsFetchedCallback =
       base::OnceCallback<void(const absl::optional<AmbientSettings>& settings,
@@ -134,19 +130,10 @@
   virtual void FetchPreviewImages(const gfx::Size& preview_size,
                                   OnPreviewImagesFetchedCallback callback) = 0;
 
-  // Get ambient mode Settings from server.
-  virtual void GetSettings(GetSettingsCallback callback) = 0;
-
   // Update ambient mode Settings to server.
   virtual void UpdateSettings(const AmbientSettings& settings,
                               UpdateSettingsCallback callback) = 0;
 
-  virtual void FetchPersonalAlbums(int banner_width,
-                                   int banner_height,
-                                   int num_albums,
-                                   const std::string& resume_token,
-                                   OnPersonalAlbumsFetchedCallback) = 0;
-
   // Fetch the Settings and albums as one API.
   virtual void FetchSettingsAndAlbums(int banner_width,
                                       int banner_height,
diff --git a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc
index e445e48..b0cd549 100644
--- a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc
+++ b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc
@@ -138,13 +138,6 @@
       FROM_HERE, base::BindOnce(std::move(callback), urls));
 }
 
-void FakeAmbientBackendControllerImpl::GetSettings(
-    GetSettingsCallback callback) {
-  // Pretend to respond asynchronously.
-  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), CreateFakeSettings()));
-}
-
 void FakeAmbientBackendControllerImpl::UpdateSettings(
     const AmbientSettings& settings,
     UpdateSettingsCallback callback) {
@@ -153,17 +146,6 @@
   pending_update_callback_ = std::move(callback);
 }
 
-void FakeAmbientBackendControllerImpl::FetchPersonalAlbums(
-    int banner_width,
-    int banner_height,
-    int num_albums,
-    const std::string& resume_token,
-    OnPersonalAlbumsFetchedCallback callback) {
-  // Pretend to respond asynchronously.
-  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), CreateFakeAlbums()));
-}
-
 void FakeAmbientBackendControllerImpl::FetchSettingsAndAlbums(
     int banner_width,
     int banner_height,
diff --git a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h
index ec450170..cacb2be 100644
--- a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h
+++ b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h
@@ -33,14 +33,8 @@
       OnScreenUpdateInfoFetchedCallback callback) override;
   void FetchPreviewImages(const gfx::Size& preview_size,
                           OnPreviewImagesFetchedCallback callback) override;
-  void GetSettings(GetSettingsCallback callback) override;
   void UpdateSettings(const AmbientSettings& settings,
                       UpdateSettingsCallback callback) override;
-  void FetchPersonalAlbums(int banner_width,
-                           int banner_height,
-                           int num_albums,
-                           const std::string& resume_token,
-                           OnPersonalAlbumsFetchedCallback callback) override;
   void FetchSettingsAndAlbums(
       int banner_width,
       int banner_height,
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 56d4f967..067efb5 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -57,6 +57,7 @@
 #include "ash/wm/container_finder.h"
 #include "ash/wm/desks/desks_controller.h"
 #include "ash/wm/desks/desks_util.h"
+#include "ash/wm/float/float_controller.h"
 #include "ash/wm/fullscreen_window_finder.h"
 #include "ash/wm/lock_action_handler_layout_manager.h"
 #include "ash/wm/lock_layout_manager.h"
@@ -338,6 +339,9 @@
   for (auto* desk_container : desks_util::GetDesksContainers(root)) {
     SetWorkspaceController(desk_container, nullptr);
   }
+  if (auto* float_controller = Shell::Get()->float_controller()) {
+    float_controller->ClearWorkspaceEventHandler(root);
+  }
 }
 
 class RootWindowTargeter : public aura::WindowTargeter {
diff --git a/ash/search_box/search_box_view_base.cc b/ash/search_box/search_box_view_base.cc
index 1a19bc7a..a8f7814 100644
--- a/ash/search_box/search_box_view_base.cc
+++ b/ash/search_box/search_box_view_base.cc
@@ -40,6 +40,7 @@
 #include "ui/views/layout/box_layout_view.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/layout/layout_provider.h"
+#include "ui/views/view.h"
 #include "ui/views/view_class_properties.h"
 #include "ui/views/widget/widget.h"
 
@@ -77,6 +78,8 @@
 // The duration for the button fade in animation.
 constexpr base::TimeDelta kButtonFadeInDuration = base::Milliseconds(100);
 
+constexpr int kIphViewHorizontalMargin = 10;
+
 void SetupLabelView(views::Label* label,
                     const gfx::FontList& font_list,
                     gfx::Insets border_insets) {
@@ -347,13 +350,14 @@
   const int between_child_spacing =
       kInnerPadding - views::LayoutProvider::Get()->GetDistanceMetric(
                           views::DISTANCE_TEXTFIELD_HORIZONTAL_TEXT_PADDING);
-  iph_container_ = AddChildView(std::make_unique<views::BoxLayoutView>());
-  iph_container_->SetOrientation(views::BoxLayout::Orientation::kVertical);
-  iph_container_->SetMainAxisAlignment(
+  raw_ptr<views::BoxLayoutView> main_container =
+      AddChildView(std::make_unique<views::BoxLayoutView>());
+  main_container->SetOrientation(views::BoxLayout::Orientation::kVertical);
+  main_container->SetMainAxisAlignment(
       views::BoxLayout::MainAxisAlignment::kCenter);
 
   content_container_ =
-      iph_container_->AddChildView(std::make_unique<views::BoxLayoutView>());
+      main_container->AddChildView(std::make_unique<views::BoxLayoutView>());
   content_container_->SetCrossAxisAlignment(
       views::BoxLayout::CrossAxisAlignment::kCenter);
   content_container_->SetMinimumCrossAxisSize(kSearchBoxPreferredHeight);
@@ -437,6 +441,12 @@
       std::make_unique<views::FillLayout>());
   content_container_->SetFlexForView(search_box_button_container_, 0,
                                      /*use_min_size=*/true);
+
+  iph_holder_ = main_container->AddChildView(std::make_unique<views::View>());
+  iph_holder_->SetLayoutManager(std::make_unique<views::FillLayout>());
+  iph_holder_->SetBorder(
+      views::CreateEmptyBorder(gfx::Insets::VH(0, kIphViewHorizontalMargin)));
+  iph_holder_->SetVisible(false);
 }
 
 SearchBoxViewBase::~SearchBoxViewBase() = default;
@@ -511,11 +521,13 @@
     DeleteIphView();
   }
 
-  iph_view_tracker_.SetView(iph_container_->AddChildView(std::move(view)));
+  iph_holder_->SetVisible(true);
+  iph_view_tracker_.SetView(iph_holder_->AddChildView(std::move(view)));
 }
 
 void SearchBoxViewBase::DeleteIphView() {
-  iph_container_->RemoveChildViewT(iph_view());
+  iph_holder_->RemoveChildViewT(iph_view());
+  iph_holder_->SetVisible(false);
 }
 
 void SearchBoxViewBase::MaybeSetAutocompleteGhostText(
diff --git a/ash/search_box/search_box_view_base.h b/ash/search_box/search_box_view_base.h
index 8cb5fb8..e98835cf 100644
--- a/ash/search_box/search_box_view_base.h
+++ b/ash/search_box/search_box_view_base.h
@@ -223,7 +223,7 @@
   void OnEnabledChanged();
 
   // Owned by views hierarchy.
-  raw_ptr<views::BoxLayoutView> iph_container_;
+  raw_ptr<views::View> iph_holder_;
   views::BoxLayoutView* content_container_;
   SearchIconImageView* search_icon_ = nullptr;
   SearchBoxImageButton* assistant_button_ = nullptr;
diff --git a/ash/style/dark_light_mode_controller_impl.cc b/ash/style/dark_light_mode_controller_impl.cc
index ecd65d0..6cd7557c 100644
--- a/ash/style/dark_light_mode_controller_impl.cc
+++ b/ash/style/dark_light_mode_controller_impl.cc
@@ -13,7 +13,6 @@
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
 #include "ash/style/color_util.h"
-#include "ash/style/dark_light_mode_nudge_controller.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
 #include "components/account_id/account_id.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -70,8 +69,7 @@
     : ScheduledFeature(prefs::kDarkModeEnabled,
                        prefs::kDarkModeScheduleType,
                        std::string(),
-                       std::string()),
-      nudge_controller_(std::make_unique<DarkLightModeNudgeController>()) {
+                       std::string()) {
   DCHECK(!g_instance);
   g_instance = this;
 
@@ -118,8 +116,6 @@
 
   registry->RegisterBooleanPref(prefs::kDarkModeEnabled,
                                 kDefaultDarkModeEnabled);
-  registry->RegisterIntegerPref(prefs::kDarkLightModeNudgeLeftToShowCount,
-                                kDarkLightModeNudgeMaxShownCount);
 }
 
 void DarkLightModeControllerImpl::SetAutoScheduleEnabled(bool enabled) {
@@ -140,11 +136,6 @@
                                         !IsDarkModeEnabled());
   active_user_pref_service_->CommitPendingWrite();
   NotifyColorModeChanges();
-  SystemNudgeController::RecordNudgeAction(NudgeCatalogName::kDarkLightMode);
-
-  // Updates showing logic of educational nudge on toggling the entry points of
-  // dark/light mode.
-  nudge_controller_->ToggledByUser();
 }
 
 void DarkLightModeControllerImpl::AddObserver(ColorModeObserver* observer) {
@@ -271,14 +262,6 @@
   }
 
   RefreshColorsOnColorMode(IsDarkModeEnabled());
-
-  if (state == session_manager::SessionState::ACTIVE) {
-    nudge_controller_->MaybeShowNudge();
-  }
-}
-
-void DarkLightModeControllerImpl::SetShowNudgeForTesting(bool value) {
-  nudge_controller_->set_show_nudge_for_testing(value);  // IN-TEST
 }
 
 void DarkLightModeControllerImpl::RefreshFeatureState() {}
diff --git a/ash/style/dark_light_mode_controller_impl.h b/ash/style/dark_light_mode_controller_impl.h
index 788b14a..0da6be14 100644
--- a/ash/style/dark_light_mode_controller_impl.h
+++ b/ash/style/dark_light_mode_controller_impl.h
@@ -21,12 +21,10 @@
 namespace ash {
 
 class ColorModeObserver;
-class DarkLightModeNudgeController;
 
 // Controls the behavior of dark/light mode. Turns on the dark mode at sunset
 // and off at sunrise if auto schedule is set (custom start and end for
-// scheduling is not supported). And determine whether to show the educational
-// nudge for users on login.
+// scheduling is not supported).
 class ASH_EXPORT DarkLightModeControllerImpl
     : public DarkLightModeController,
       public LoginDataDispatcher::Observer,
@@ -72,8 +70,6 @@
   void OnActiveUserPrefServiceChanged(PrefService* prefs) override;
   void OnSessionStateChanged(session_manager::SessionState state) override;
 
-  void SetShowNudgeForTesting(bool value);
-
  protected:
   // ScheduledFeature:
   void RefreshFeatureState() override;
@@ -94,8 +90,6 @@
   base::ScopedClosureRunner GetNotifyOnDarkModeChangeClosure();
   void NotifyIfDarkModeChanged(bool old_is_dark_mode_enabled);
 
-  std::unique_ptr<DarkLightModeNudgeController> nudge_controller_;
-
   // The default color is DARK when the DarkLightMode feature is disabled. But
   // we can also override it to LIGHT through ScopedLightModeAsDefault. This is
   // done to help keeping some of the UI elements as LIGHT by default before
diff --git a/ash/style/dark_light_mode_nudge.cc b/ash/style/dark_light_mode_nudge.cc
deleted file mode 100644
index c2d6723..0000000
--- a/ash/style/dark_light_mode_nudge.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/style/dark_light_mode_nudge.h"
-
-#include "ash/constants/notifier_catalogs.h"
-#include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/style/ash_color_provider.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/compositor/layer.h"
-#include "ui/views/controls/label.h"
-
-namespace ash {
-
-namespace {
-
-// The size of the dark light mode icon.
-constexpr int kIconSize = 20;
-
-// The minimum width of the label.
-constexpr int kMinLabelWidth = 200;
-
-// The spacing between the icon and label in the nudge view.
-constexpr int kIconLabelSpacing = 16;
-
-// The padding which separates the nudge's border with its inner contents.
-constexpr int kNudgePadding = 16;
-
-constexpr char kDarkLightModeNudgeName[] = "DarkLightModeEducationalNudge";
-
-}  // namespace
-
-DarkLightModeNudge::DarkLightModeNudge()
-    : SystemNudge(kDarkLightModeNudgeName,
-                  NudgeCatalogName::kDarkLightMode,
-                  kIconSize,
-                  kIconLabelSpacing,
-                  kNudgePadding) {}
-
-DarkLightModeNudge::~DarkLightModeNudge() = default;
-
-std::unique_ptr<SystemNudgeLabel> DarkLightModeNudge::CreateLabelView() const {
-  return std::make_unique<SystemNudgeLabel>(GetAccessibilityText(),
-                                            kMinLabelWidth);
-}
-
-const gfx::VectorIcon& DarkLightModeNudge::GetIcon() const {
-  return kUnifiedMenuDarkModeIcon;
-}
-
-std::u16string DarkLightModeNudge::GetAccessibilityText() const {
-  return l10n_util::GetStringUTF16(
-      TabletMode::Get()->InTabletMode()
-          ? IDS_ASH_DARK_LIGHT_MODE_EDUCATIONAL_NUDGE_IN_TABLET_MODE
-          : IDS_ASH_DARK_LIGHT_MODE_EDUCATIONAL_NUDGE_IN_CLAMSHELL_MODE);
-}
-
-}  // namespace ash
diff --git a/ash/style/dark_light_mode_nudge.h b/ash/style/dark_light_mode_nudge.h
deleted file mode 100644
index 91c43e4..0000000
--- a/ash/style/dark_light_mode_nudge.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_STYLE_DARK_LIGHT_MODE_NUDGE_H_
-#define ASH_STYLE_DARK_LIGHT_MODE_NUDGE_H_
-
-#include "ash/system/tray/system_nudge.h"
-
-namespace ash {
-
-// Implements an educational nudge for dark light mode.
-class DarkLightModeNudge : public SystemNudge {
- public:
-  DarkLightModeNudge();
-  DarkLightModeNudge(const DarkLightModeNudge&) = delete;
-  DarkLightModeNudge& operator=(const DarkLightModeNudge&) = delete;
-  ~DarkLightModeNudge() override;
-
- protected:
-  // SystemNudge:
-  std::unique_ptr<SystemNudgeLabel> CreateLabelView() const override;
-  const gfx::VectorIcon& GetIcon() const override;
-  std::u16string GetAccessibilityText() const override;
-};
-
-}  // namespace ash
-
-#endif  // ASH_STYLE_DARK_LIGHT_MODE_NUDGE_H_
diff --git a/ash/style/dark_light_mode_nudge_controller.cc b/ash/style/dark_light_mode_nudge_controller.cc
deleted file mode 100644
index 9615610..0000000
--- a/ash/style/dark_light_mode_nudge_controller.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/style/dark_light_mode_nudge_controller.h"
-
-#include "ash/constants/ash_pref_names.h"
-#include "ash/constants/ash_switches.h"
-#include "ash/session/session_controller_impl.h"
-#include "ash/shell.h"
-#include "ash/style/dark_light_mode_controller_impl.h"
-#include "ash/style/dark_light_mode_nudge.h"
-#include "base/command_line.h"
-#include "chromeos/constants/chromeos_features.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
-
-namespace ash {
-
-namespace {
-
-PrefService* GetActiveUserPrefService() {
-  return DarkLightModeControllerImpl::Get()->active_user_pref_service();
-}
-
-void SetRemainingShownCount(int count) {
-  PrefService* prefs = GetActiveUserPrefService();
-  if (prefs)
-    prefs->SetInteger(prefs::kDarkLightModeNudgeLeftToShowCount, count);
-}
-
-}  // namespace
-
-DarkLightModeNudgeController::DarkLightModeNudgeController() = default;
-
-DarkLightModeNudgeController::~DarkLightModeNudgeController() = default;
-
-// static
-int DarkLightModeNudgeController::GetRemainingShownCount() {
-  const PrefService* prefs = GetActiveUserPrefService();
-  return prefs ? prefs->GetInteger(prefs::kDarkLightModeNudgeLeftToShowCount)
-               : 0;
-}
-
-void DarkLightModeNudgeController::MaybeShowNudge() {
-  if (!ShouldShowNudge())
-    return;
-
-  const int shown_count = GetRemainingShownCount();
-  ShowNudge();
-  SetRemainingShownCount(shown_count - 1);
-}
-
-void DarkLightModeNudgeController::ToggledByUser() {
-  SetRemainingShownCount(0);
-}
-
-std::unique_ptr<SystemNudge> DarkLightModeNudgeController::CreateSystemNudge() {
-  return std::make_unique<DarkLightModeNudge>();
-}
-
-bool DarkLightModeNudgeController::ShouldShowNudge() const {
-  if (!chromeos::features::IsDarkLightModeEnabled())
-    return false;
-
-  // Do not show the nudge if it is set to be hidden in the tests.
-  if (hide_nudge_for_testing_)
-    return false;
-
-  // Do not show if the command line flag to hide nudges is set.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshNoNudges))
-    return false;
-
-  auto* session_controller = Shell::Get()->session_controller();
-  if (!session_controller->IsActiveUserSessionStarted())
-    return false;
-
-  absl::optional<user_manager::UserType> user_type =
-      session_controller->GetUserType();
-  // Must have a `user_type` because of the active user session check above.
-  DCHECK(user_type);
-  switch (*user_type) {
-    case user_manager::USER_TYPE_REGULAR:
-    case user_manager::USER_TYPE_CHILD:
-      // We only allow regular and child accounts to see the nudge.
-      break;
-    case user_manager::USER_TYPE_GUEST:
-    case user_manager::USER_TYPE_PUBLIC_ACCOUNT:
-    case user_manager::USER_TYPE_KIOSK_APP:
-    case user_manager::USER_TYPE_ARC_KIOSK_APP:
-    case user_manager::USER_TYPE_WEB_KIOSK_APP:
-    case user_manager::USER_TYPE_ACTIVE_DIRECTORY:
-    case user_manager::NUM_USER_TYPES:
-      return false;
-  }
-
-  return GetRemainingShownCount() > 0;
-}
-
-}  // namespace ash
diff --git a/ash/style/dark_light_mode_nudge_controller.h b/ash/style/dark_light_mode_nudge_controller.h
deleted file mode 100644
index 9075265..0000000
--- a/ash/style/dark_light_mode_nudge_controller.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_STYLE_DARK_LIGHT_MODE_NUDGE_CONTROLLER_H_
-#define ASH_STYLE_DARK_LIGHT_MODE_NUDGE_CONTROLLER_H_
-
-#include "ash/ash_export.h"
-#include "ash/system/tray/system_nudge_controller.h"
-
-namespace ash {
-
-class SystemNudge;
-
-// Controls the showing and hiding of the dark/light mode educational nudge.
-// SystemNudgeController will control the animation, time duration etc of the
-// nudge.
-class ASH_EXPORT DarkLightModeNudgeController : public SystemNudgeController {
- public:
-  DarkLightModeNudgeController();
-  DarkLightModeNudgeController(const DarkLightModeNudgeController&) = delete;
-  DarkLightModeNudgeController& operator=(const DarkLightModeNudgeController&) =
-      delete;
-  ~DarkLightModeNudgeController() override;
-
-  // Gets the remaining number of times that the educational nudge can be shown.
-  static int GetRemainingShownCount();
-
-  // If possible, this will show the nudge that educates the user how to switch
-  // between the dark and light mode.
-  void MaybeShowNudge();
-
-  // Called when the feature's state is toggled manually by the user.
-  void ToggledByUser();
-
-  void set_show_nudge_for_testing(bool value) {
-    hide_nudge_for_testing_ = !value;
-  }
-
- protected:
-  // SystemNudgeController:
-  std::unique_ptr<SystemNudge> CreateSystemNudge() override;
-
- private:
-  // Returns true if the educational nudge should be shown.
-  bool ShouldShowNudge() const;
-
-  // Used to indicate whether to hide the nudge in tests. Will be initialized to
-  // hide for ash tests through `set_show_nudge_for_testing` above. See
-  // AshTestHelper::SetUp for more details.
-  bool hide_nudge_for_testing_ = false;
-};
-
-}  // namespace ash
-
-#endif  // ASH_STYLE_DARK_LIGHT_MODE_NUDGE_CONTROLLER_H_
diff --git a/ash/style/dark_light_mode_nudge_controller_unittests.cc b/ash/style/dark_light_mode_nudge_controller_unittests.cc
deleted file mode 100644
index 82fab05..0000000
--- a/ash/style/dark_light_mode_nudge_controller_unittests.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/style/dark_light_mode_nudge_controller.h"
-
-#include "ash/constants/ash_constants.h"
-#include "ash/constants/ash_switches.h"
-#include "ash/shell.h"
-#include "ash/style/dark_light_mode_controller_impl.h"
-#include "ash/system/dark_mode/dark_mode_feature_pod_controller.h"
-#include "ash/system/unified/unified_system_tray.h"
-#include "ash/system/unified/unified_system_tray_bubble.h"
-#include "ash/test/ash_test_base.h"
-#include "base/command_line.h"
-#include "base/test/scoped_feature_list.h"
-#include "chromeos/constants/chromeos_features.h"
-
-namespace ash {
-
-namespace {
-
-const char kUser[] = "user@gmail.com";
-const AccountId account_id = AccountId::FromUserEmailGaiaId(kUser, kUser);
-
-}  // namespace
-
-class DarkLightModeNudgeControllerTest : public NoSessionAshTestBase {
- public:
-  DarkLightModeNudgeControllerTest() {
-    scoped_feature_list_.InitAndEnableFeature(
-        chromeos::features::kDarkLightMode);
-  }
-  DarkLightModeNudgeControllerTest(const DarkLightModeNudgeControllerTest&) =
-      delete;
-  DarkLightModeNudgeControllerTest& operator=(
-      const DarkLightModeNudgeControllerTest&) = delete;
-  ~DarkLightModeNudgeControllerTest() override = default;
-
-  // NoSessionAshTestBase:
-  void SetUp() override {
-    NoSessionAshTestBase::SetUp();
-    Shell::Get()->dark_light_mode_controller()->SetShowNudgeForTesting(true);
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_F(DarkLightModeNudgeControllerTest, NoNudgeInGuestSession) {
-  SimulateGuestLogin();
-  EXPECT_EQ(kDarkLightModeNudgeMaxShownCount,
-            DarkLightModeNudgeController::GetRemainingShownCount());
-}
-
-TEST_F(DarkLightModeNudgeControllerTest, NoNudgeWhenSkippedByCommandLineFlag) {
-  // Unit tests run with a scoped command line, so directly set the flag.
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kAshNoNudges);
-  SimulateUserLogin(account_id);
-  EXPECT_EQ(kDarkLightModeNudgeMaxShownCount,
-            DarkLightModeNudgeController::GetRemainingShownCount());
-}
-
-TEST_F(DarkLightModeNudgeControllerTest, NoNudgeInLockScreen) {
-  SimulateUserLogin(account_id);
-  EXPECT_EQ(kDarkLightModeNudgeMaxShownCount - 1,
-            DarkLightModeNudgeController::GetRemainingShownCount());
-
-  // Switch to lock screen should not show the nudge again.
-  GetSessionControllerClient()->LockScreen();
-  EXPECT_EQ(kDarkLightModeNudgeMaxShownCount - 1,
-            DarkLightModeNudgeController::GetRemainingShownCount());
-}
-
-TEST_F(DarkLightModeNudgeControllerTest, NudgeShownCount) {
-  // Login `kDarkLightModeNudgeMaxShownCount` times and verity the remaining
-  // nudge shown count.
-  for (int i = kDarkLightModeNudgeMaxShownCount; i > 0; i--) {
-    SimulateUserLogin(account_id);
-    EXPECT_EQ(i - 1, DarkLightModeNudgeController::GetRemainingShownCount());
-    ClearLogin();
-  }
-  // The remaining nudge shown count should be 0 after
-  // `kDarkLightModeNudgeMaxShownCount` times login, which means the nudge will
-  // not be shown again in next time login.
-  EXPECT_EQ(0, DarkLightModeNudgeController::GetRemainingShownCount());
-}
-
-// Flaky. https://crbug.com/1325224
-TEST_F(DarkLightModeNudgeControllerTest,
-       DISABLED_NoNudgeAfterColorModeToggled) {
-  SimulateUserLogin(account_id);
-  UnifiedSystemTray* system_tray = GetPrimaryUnifiedSystemTray();
-  system_tray->ShowBubble();
-  std::unique_ptr<DarkModeFeaturePodController>
-      dark_mode_feature_pod_controller =
-          std::make_unique<DarkModeFeaturePodController>(
-              system_tray->bubble()->unified_system_tray_controller());
-
-  EXPECT_EQ(kDarkLightModeNudgeMaxShownCount - 1,
-            DarkLightModeNudgeController::GetRemainingShownCount());
-  EXPECT_GT(DarkLightModeNudgeController::GetRemainingShownCount(), 0);
-  // Toggle the "Dark theme" feature pod button inside quick settings.
-  dark_mode_feature_pod_controller->CreateButton();
-  dark_mode_feature_pod_controller->OnIconPressed();
-  // The remaining nudge shown count should be 0 after toggling the "Dark theme"
-  // feature pod button to switch color mode. Even though the nudge hasn't been
-  // shown `kDarkLightModeNudgeMaxShownCount` yet.
-  EXPECT_EQ(0, DarkLightModeNudgeController::GetRemainingShownCount());
-}
-
-}  // namespace ash
diff --git a/ash/style/rounded_label.cc b/ash/style/rounded_label.cc
index 97993ea..5929358 100644
--- a/ash/style/rounded_label.cc
+++ b/ash/style/rounded_label.cc
@@ -6,6 +6,7 @@
 
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/style/color_provider.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "ui/compositor/layer.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
@@ -60,7 +61,9 @@
   if (features::IsDarkLightModeEnabled()) {
     views::HighlightBorder::PaintBorderToCanvas(
         canvas, *this, GetLocalBounds(), gfx::RoundedCornersF(rounding_dp_),
-        views::HighlightBorder::Type::kHighlightBorder2,
+        chromeos::features::IsJellyrollEnabled()
+            ? views::HighlightBorder::Type::kHighlightBorderNoShadow
+            : views::HighlightBorder::Type::kHighlightBorder2,
         /*use_light_colors=*/false);
   }
 }
diff --git a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc
index 4cb4e4c..bd4e1012 100644
--- a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc
+++ b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc
@@ -13,6 +13,7 @@
 #include "ash/wm/desks/desks_util.h"
 #include "base/containers/contains.h"
 #include "base/functional/bind.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_provider.h"
@@ -64,7 +65,10 @@
       : views::LabelButton(pressed_callback, name) {
     SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_CENTER);
     SetBorder(std::make_unique<views::HighlightBorder>(
-        0, views::HighlightBorder::Type::kHighlightBorder1,
+        0,
+        chromeos::features::IsJellyrollEnabled()
+            ? views::HighlightBorder::Type::kHighlightBorderNoShadow
+            : views::HighlightBorder::Type::kHighlightBorder1,
         /*use_light_color=*/false));
     label()->SetSubpixelRenderingEnabled(false);
     label()->SetFontList(views::Label::GetDefaultFontList().Derive(
diff --git a/ash/style/system_textfield.cc b/ash/style/system_textfield.cc
index 9c00856..445abac 100644
--- a/ash/style/system_textfield.cc
+++ b/ash/style/system_textfield.cc
@@ -94,6 +94,24 @@
 
 SystemTextfield::~SystemTextfield() = default;
 
+void SystemTextfield::SetTextColorId(ui::ColorId color_id) {
+  UpdateColorId(text_color_id_, color_id, /*is_background_color=*/false);
+}
+
+void SystemTextfield::SetSelectedTextColorId(ui::ColorId color_id) {
+  UpdateColorId(selected_text_color_id_, color_id,
+                /*is_background_color=*/false);
+}
+
+void SystemTextfield::SetSelectionBackgroundColorId(ui::ColorId color_id) {
+  UpdateColorId(selection_background_color_id_, color_id,
+                /*is_background_color=*/false);
+}
+
+void SystemTextfield::SetBackgroundColorId(ui::ColorId color_id) {
+  UpdateColorId(background_color_id_, color_id, /*is_background_color=*/true);
+}
+
 void SystemTextfield::SetActive(bool active) {
   if (IsActive() == active) {
     return;
@@ -193,6 +211,21 @@
   SchedulePaint();
 }
 
+void SystemTextfield::UpdateColorId(absl::optional<ui::ColorId>& src,
+                                    ui::ColorId dst,
+                                    bool is_background_color) {
+  if (src && *src == dst) {
+    return;
+  }
+
+  src = dst;
+  if (is_background_color) {
+    UpdateBackground();
+  } else {
+    UpdateTextColor();
+  }
+}
+
 void SystemTextfield::UpdateTextColor() {
   if (!GetWidget()) {
     return;
@@ -207,11 +240,13 @@
   }
 
   // Set text color and selection text and background (highlight part) colors.
-  SetColor(color_provider->GetColor(cros_tokens::kCrosSysOnSurface));
-  render_text->set_selection_color(
-      color_provider->GetColor(cros_tokens::kCrosSysOnSurface));
+  SetColor(color_provider->GetColor(
+      text_color_id_.value_or(cros_tokens::kCrosSysOnSurface)));
+  render_text->set_selection_color(color_provider->GetColor(
+      selected_text_color_id_.value_or(cros_tokens::kCrosSysOnSurface)));
   render_text->set_selection_background_focused_color(
-      color_provider->GetColor(cros_tokens::kCrosSysHighlightText));
+      color_provider->GetColor(selection_background_color_id_.value_or(
+          cros_tokens::kCrosSysHighlightText)));
 }
 
 void SystemTextfield::UpdateBackground() {
@@ -219,7 +254,8 @@
   // textfield or the textfield is focused.
   if (IsMouseHovered() || HasFocus()) {
     SetBackground(views::CreateThemedRoundedRectBackground(
-        cros_tokens::kCrosSysHoverOnSubtle, kCornerRadius));
+        background_color_id_.value_or(cros_tokens::kCrosSysHoverOnSubtle),
+        kCornerRadius));
     return;
   }
 
diff --git a/ash/style/system_textfield.h b/ash/style/system_textfield.h
index ab4231d..56503d4 100644
--- a/ash/style/system_textfield.h
+++ b/ash/style/system_textfield.h
@@ -6,6 +6,7 @@
 #define ASH_STYLE_SYSTEM_TEXTFIELD_H_
 
 #include "ash/ash_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/color/color_id.h"
 #include "ui/views/controls/textfield/textfield.h"
@@ -41,6 +42,13 @@
 
   void set_delegate(Delegate* delegate) { delegate_ = delegate; }
 
+  // Set custom colors of text, selected text, selection background, and
+  // textfield background color.
+  void SetTextColorId(ui::ColorId color_id);
+  void SetSelectedTextColorId(ui::ColorId color_id);
+  void SetSelectionBackgroundColorId(ui::ColorId color_id);
+  void SetBackgroundColorId(ui::ColorId color_id);
+
   // Activates or deactivates the textfield. The textfield can only be edited if
   // it is active.
   void SetActive(bool active);
@@ -62,6 +70,10 @@
  private:
   // Called when the enabled state is changed.
   void OnEnabledStateChanged();
+  // Update custom color ID.
+  void UpdateColorId(absl::optional<ui::ColorId>& src,
+                     ui::ColorId dst,
+                     bool is_background_color);
   // Updates text and selection text colors.
   void UpdateTextColor();
   // Creates themed or transparent background according to the textfield states.
@@ -73,6 +85,14 @@
   Delegate* delegate_ = nullptr;
   // Indicates if the textfield should show focus ring.
   bool show_focus_ring_ = false;
+
+  // custom color IDs for text, selected text, selection background, and
+  // textfield background.
+  absl::optional<ui::ColorId> text_color_id_;
+  absl::optional<ui::ColorId> selected_text_color_id_;
+  absl::optional<ui::ColorId> selection_background_color_id_;
+  absl::optional<ui::ColorId> background_color_id_;
+
   // Enabled state changed callback.
   base::CallbackListSubscription enabled_changed_subscription_;
 };
diff --git a/ash/style/system_toast_style.cc b/ash/style/system_toast_style.cc
index 9431aa4..cce8dc50 100644
--- a/ash/style/system_toast_style.cc
+++ b/ash/style/system_toast_style.cc
@@ -18,6 +18,7 @@
 #include "ash/system/toast/toast_overlay.h"
 #include "ash/wm/work_area_insets.h"
 #include "base/strings/strcat.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
@@ -166,7 +167,10 @@
   const float toast_corner_radius = toast_height / 2.0f;
   layer()->SetRoundedCornerRadius(gfx::RoundedCornersF(toast_corner_radius));
   SetBorder(std::make_unique<views::HighlightBorder>(
-      toast_corner_radius, views::HighlightBorder::Type::kHighlightBorder1,
+      toast_corner_radius,
+      chromeos::features::IsJellyrollEnabled()
+          ? views::HighlightBorder::Type::kHighlightBorderOnShadow
+          : views::HighlightBorder::Type::kHighlightBorder1,
       /*use_light_colors=*/false));
 
   // Since system toast has a very large corner radius, we should use the shadow
diff --git a/ash/system/phonehub/phone_hub_nudge_controller.cc b/ash/system/phonehub/phone_hub_nudge_controller.cc
index b79f61b..9bf3ccec 100644
--- a/ash/system/phonehub/phone_hub_nudge_controller.cc
+++ b/ash/system/phonehub/phone_hub_nudge_controller.cc
@@ -8,12 +8,15 @@
 
 namespace ash {
 
-PhoneHubNudgeController::PhoneHubNudgeController(std::u16string nudge_content)
-    : nudge_content_(nudge_content) {}
+PhoneHubNudgeController::PhoneHubNudgeController() = default;
 PhoneHubNudgeController::~PhoneHubNudgeController() = default;
 
 std::unique_ptr<SystemNudge> PhoneHubNudgeController::CreateSystemNudge() {
+  SetNudgeContent();
   return std::make_unique<PhoneHubNudge>(nudge_content_);
 }
 
+void PhoneHubNudgeController::SetNudgeContent() {
+  nudge_content_ = u"";
+}
 }  // namespace ash
\ No newline at end of file
diff --git a/ash/system/phonehub/phone_hub_nudge_controller.h b/ash/system/phonehub/phone_hub_nudge_controller.h
index c72e467..f74a8b53 100644
--- a/ash/system/phonehub/phone_hub_nudge_controller.h
+++ b/ash/system/phonehub/phone_hub_nudge_controller.h
@@ -8,14 +8,16 @@
 #include "ash/system/tray/system_nudge_controller.h"
 
 namespace ash {
-
+// This class controls showing a nudge when a user is eligible for Phone Hub.
 class ASH_EXPORT PhoneHubNudgeController : public SystemNudgeController {
  public:
-  explicit PhoneHubNudgeController(std::u16string nudge_content_);
+  PhoneHubNudgeController();
   PhoneHubNudgeController(const PhoneHubNudgeController&) = delete;
   PhoneHubNudgeController& operator=(const PhoneHubNudgeController&) = delete;
   ~PhoneHubNudgeController() override;
 
+  void SetNudgeContent();
+
  protected:
   // SystemNudgeController: Creates PhoneHubNudge
   std::unique_ptr<SystemNudge> CreateSystemNudge() override;
diff --git a/ash/system/phonehub/phone_hub_nudge_controller_unittest.cc b/ash/system/phonehub/phone_hub_nudge_controller_unittest.cc
index af5fb33..ee3b223b 100644
--- a/ash/system/phonehub/phone_hub_nudge_controller_unittest.cc
+++ b/ash/system/phonehub/phone_hub_nudge_controller_unittest.cc
@@ -17,14 +17,13 @@
   // AshTestBase:
   void SetUp() override {
     AshTestBase::SetUp();
-    controller_ = std::make_unique<PhoneHubNudgeController>(nudge_content_);
+    controller_ = std::make_unique<PhoneHubNudgeController>();
   }
 
   PhoneHubNudgeController* GetController() { return controller_.get(); }
 
  private:
   std::unique_ptr<PhoneHubNudgeController> controller_;
-  std::u16string nudge_content_;
 };
 
 TEST_F(PhoneHubNudgeControllerTest, PhoneHubNudgeControllerExists) {
diff --git a/ash/system/phonehub/phone_hub_tray.cc b/ash/system/phonehub/phone_hub_tray.cc
index 8c555c3..906844f 100644
--- a/ash/system/phonehub/phone_hub_tray.cc
+++ b/ash/system/phonehub/phone_hub_tray.cc
@@ -60,11 +60,23 @@
 constexpr auto kBubblePadding =
     gfx::Insets::TLBR(0, 0, kBubbleBottomPaddingDip, 0);
 
+bool IsInUserSession() {
+  SessionControllerImpl* session_controller =
+      Shell::Get()->session_controller();
+  return session_controller->GetSessionState() ==
+             session_manager::SessionState::ACTIVE &&
+         !session_controller->IsRunningInAppMode();
+}
+
 }  // namespace
 
 PhoneHubTray::PhoneHubTray(Shelf* shelf)
     : TrayBackgroundView(shelf, TrayBackgroundViewCatalogName::kPhoneHub),
-      ui_controller_(new PhoneHubUiController()) {
+      ui_controller_(new PhoneHubUiController()),
+      phone_hub_nudge_controller_(
+          features::IsPhoneHubNudgeEnabled()
+              ? std::make_unique<PhoneHubNudgeController>()
+              : nullptr) {
   // By default, if the individual buttons did not handle the event consider it
   // as a phone hub icon event.
   SetPressedCallback(base::BindRepeating(&PhoneHubTray::PhoneHubIconActivated,
@@ -385,7 +397,14 @@
 void PhoneHubTray::UpdateVisibility() {
   DCHECK(ui_controller_.get());
   auto ui_state = ui_controller_->ui_state();
-  SetVisiblePreferred(ui_state != PhoneHubUiController::UiState::kHidden);
+  SetVisiblePreferred(ui_state != PhoneHubUiController::UiState::kHidden &&
+                      IsInUserSession());
+  if (features::IsPhoneHubNudgeEnabled() && IsInUserSession()) {
+    if (ui_state == PhoneHubUiController::UiState::kOnboardingWithoutPhone) {
+      phone_hub_nudge_controller_->ShowNudge();
+      // TODO (b/266853434): Animation of icon.
+    }
+  }
 }
 
 void PhoneHubTray::UpdateHeaderVisibility() {
@@ -413,8 +432,11 @@
   // Simply toggle between visible/invisibvle
   if (bubble_ && bubble_->bubble_view()->GetVisible()) {
     CloseBubble();
-  } else {
-    ShowBubble();
+    return;
+  }
+  ShowBubble();
+  if (features::IsPhoneHubNudgeEnabled()) {
+    phone_hub_nudge_controller_->HideNudge();
   }
 }
 
diff --git a/ash/system/phonehub/phone_hub_tray.h b/ash/system/phonehub/phone_hub_tray.h
index 62265ab..d563854d 100644
--- a/ash/system/phonehub/phone_hub_tray.h
+++ b/ash/system/phonehub/phone_hub_tray.h
@@ -10,6 +10,7 @@
 #include "ash/session/session_controller_impl.h"
 #include "ash/system/phonehub/onboarding_view.h"
 #include "ash/system/phonehub/phone_hub_content_view.h"
+#include "ash/system/phonehub/phone_hub_nudge_controller.h"
 #include "ash/system/phonehub/phone_hub_ui_controller.h"
 #include "ash/system/phonehub/phone_status_view.h"
 #include "ash/system/status_area_widget.h"
@@ -112,6 +113,10 @@
     return ui_controller_.get();
   }
 
+  PhoneHubNudgeController* phone_hub_nudge_controller_for_testing() {
+    return phone_hub_nudge_controller_.get();
+  }
+
  private:
   FRIEND_TEST_ALL_PREFIXES(PhoneHubTrayTest, SafeAccessToHeaderView);
 
@@ -163,6 +168,9 @@
   // PhoneHub state.
   std::unique_ptr<PhoneHubUiController> ui_controller_;
 
+  // Controls the behavior of a nudge shown to eligible users.
+  std::unique_ptr<PhoneHubNudgeController> phone_hub_nudge_controller_;
+
   // The bubble that appears after clicking the tray button.
   std::unique_ptr<TrayBubbleWrapper> bubble_;
 
diff --git a/ash/system/phonehub/phone_hub_tray_unittest.cc b/ash/system/phonehub/phone_hub_tray_unittest.cc
index c7096f29..6d024a9 100644
--- a/ash/system/phonehub/phone_hub_tray_unittest.cc
+++ b/ash/system/phonehub/phone_hub_tray_unittest.cc
@@ -61,7 +61,8 @@
     feature_list_.InitWithFeatures(
         /*enabled_features=*/{features::kPhoneHub,
                               features::kPhoneHubCameraRoll,
-                              features::kEcheLauncher, features::kEcheSWA},
+                              features::kEcheLauncher, features::kEcheSWA,
+                              features::kPhoneHubNudge},
         /*disabled_features=*/{});
     auto delegate = std::make_unique<MockNewWindowDelegate>();
     new_window_delegate_ = delegate.get();
@@ -791,4 +792,35 @@
   EXPECT_TRUE(secondary_phone_hub_tray->GetVisible());
 }
 
+TEST_F(PhoneHubTrayTest, ShowNudge) {
+  // Simulate kOnboardingWithoutPhone state.
+  GetFeatureStatusProvider()->SetStatus(
+      phonehub::FeatureStatus::kEligiblePhoneButNotSetUp);
+  GetOnboardingUiTracker()->SetShouldShowOnboardingUi(true);
+  GetSessionControllerClient()->SetSessionState(
+      session_manager::SessionState::ACTIVE);
+
+  PhoneHubNudgeController* nudge_controller =
+      phone_hub_tray_->phone_hub_nudge_controller_for_testing();
+  SystemNudge* nudge = nudge_controller->GetSystemNudgeForTesting();
+  EXPECT_TRUE(nudge);
+}
+
+TEST_F(PhoneHubTrayTest, HideNudge) {
+  GetFeatureStatusProvider()->SetStatus(
+      phonehub::FeatureStatus::kEligiblePhoneButNotSetUp);
+  GetOnboardingUiTracker()->SetShouldShowOnboardingUi(true);
+  GetSessionControllerClient()->SetSessionState(
+      session_manager::SessionState::ACTIVE);
+
+  PhoneHubNudgeController* nudge_controller =
+      phone_hub_tray_->phone_hub_nudge_controller_for_testing();
+  SystemNudge* nudge = nudge_controller->GetSystemNudgeForTesting();
+  EXPECT_TRUE(nudge);
+
+  ClickTrayButton();
+  nudge = nudge_controller->GetSystemNudgeForTesting();
+  EXPECT_FALSE(nudge);
+}
+
 }  // namespace ash
diff --git a/ash/system/tray/system_nudge_controller.cc b/ash/system/tray/system_nudge_controller.cc
index df78e60..1328235 100644
--- a/ash/system/tray/system_nudge_controller.cc
+++ b/ash/system/tray/system_nudge_controller.cc
@@ -109,7 +109,9 @@
 
 void SystemNudgeController::ShowNudge() {
   if (nudge_ && !nudge_->widget()->IsClosed()) {
-    hide_nudge_timer_.AbandonAndStop();
+    if (hide_nudge_timer_) {
+      hide_nudge_timer_->AbandonAndStop();
+    }
     nudge_->Close();
   }
 
@@ -119,10 +121,11 @@
   StartFadeAnimation(/*show=*/true);
   RecordNudgeShown(nudge_->catalog_name());
 
+  hide_nudge_timer_ = std::make_unique<base::OneShotTimer>();
   // Start a timer to close the nudge after a set amount of time.
-  hide_nudge_timer_.Start(FROM_HERE, kNudgeShowTime,
-                          base::BindOnce(&SystemNudgeController::HideNudge,
-                                         weak_ptr_factory_.GetWeakPtr()));
+  hide_nudge_timer_->Start(FROM_HERE, kNudgeShowTime,
+                           base::BindOnce(&SystemNudgeController::HideNudge,
+                                          weak_ptr_factory_.GetWeakPtr()));
 }
 
 void SystemNudgeController::ForceCloseAnimatingNudge() {
@@ -130,7 +133,7 @@
 }
 
 void SystemNudgeController::FireHideNudgeTimerForTesting() {
-  hide_nudge_timer_.FireNow();
+  hide_nudge_timer_->FireNow();
 }
 
 void SystemNudgeController::ResetNudgeRegistryForTesting() {
@@ -150,6 +153,7 @@
 }
 
 void SystemNudgeController::StartFadeAnimation(bool show) {
+  hide_nudge_timer_.reset();
   // Clean any pending animation observer.
   hide_nudge_animation_observer_.reset();
 
@@ -159,6 +163,9 @@
     return;
 
   ui::Layer* layer = nudge_->widget()->GetLayer();
+  if (layer->GetAnimator()->is_animating()) {
+    return;
+  }
   gfx::Rect widget_bounds = layer->bounds();
 
   gfx::Transform scaled_nudge_transform;
diff --git a/ash/system/tray/system_nudge_controller.h b/ash/system/tray/system_nudge_controller.h
index d3e5c17..31c80ed 100644
--- a/ash/system/tray/system_nudge_controller.h
+++ b/ash/system/tray/system_nudge_controller.h
@@ -50,15 +50,15 @@
   // shown.
   void ResetNudgeRegistryForTesting();
 
+  // Hides the nudge widget.
+  void HideNudge();
+
  protected:
   // Concrete subclasses must implement this method to return a
   // SystemNudge that creates a label and specifies an icon specific
   // to the nudge.
   virtual std::unique_ptr<SystemNudge> CreateSystemNudge() = 0;
 
-  // Hides the nudge widget.
-  void HideNudge();
-
  private:
   // Returns the registry which keeps track of when a nudge was last shown.
   static std::vector<std::pair<NudgeCatalogName, base::TimeTicks>>&
@@ -75,7 +75,7 @@
   std::unique_ptr<SystemNudge> nudge_;
 
   // Timer to hide the nudge.
-  base::OneShotTimer hide_nudge_timer_;
+  std::unique_ptr<base::OneShotTimer> hide_nudge_timer_;
 
   std::unique_ptr<ui::ImplicitAnimationObserver> hide_nudge_animation_observer_;
 
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index e216f5c..52b5f9f8 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -319,15 +319,6 @@
   Shell::CreateInstance(std::move(shell_init_params));
   Shell* shell = Shell::Get();
 
-  // The dark/light mode educational nudge is expected to be shown when session
-  // state changed to ACTIVE. This means it might be shown above the shelf in
-  // all the tests with an active user session. This setting here make it will
-  // not be shown by default in tests. As keep it shown will change the
-  // operations needed in many of the tests, e.g, when productive launcher is
-  // shown as well, we need one more click outside of the launcher to dismiss
-  // the nudge first before dismissing the launcher.
-  shell->dark_light_mode_controller()->SetShowNudgeForTesting(false);
-
   chromeos::MultitaskMenuNudgeController::SetSuppressNudgeForTesting(true);
 
   // Set up a test wallpaper controller client before signing in any users. At
diff --git a/ash/webui/common/resources/network/network_config.js b/ash/webui/common/resources/network/network_config.js
index f2cc6a6e..2419c0d 100644
--- a/ash/webui/common/resources/network/network_config.js
+++ b/ash/webui/common/resources/network/network_config.js
@@ -2030,7 +2030,8 @@
       return false;
     }
     // endpoint should be the form of IP:port or hostname:port
-    if (!peer.endpoint || !peer.endpoint.match(/^[a-zA-Z0-9\-\.]+:[0-9]+$/i)) {
+    if (!peer.endpoint ||
+        !peer.endpoint.match(/^\[?[a-zA-Z0-9\-\.:]+\]?:[0-9]+$/i)) {
       return false;
     }
     // allowedIps should be comma-separated list of IP/cidr.
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc
index 8fb7a171..926415ae 100644
--- a/ash/webui/personalization_app/personalization_app_ui.cc
+++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -4,6 +4,8 @@
 
 #include "ash/webui/personalization_app/personalization_app_ui.h"
 
+#include <string>
+
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/ambient/ambient_client.h"
 #include "ash/public/cpp/wallpaper/wallpaper_controller.h"
@@ -38,10 +40,8 @@
 
 namespace {
 
-inline constexpr char kGooglePhotosURL[] = "https://photos.google.com";
-
-GURL GetGooglePhotosURL() {
-  return GURL(kGooglePhotosURL);
+std::u16string GetGooglePhotosURL() {
+  return u"https://photos.google.com";
 }
 
 bool IsAmbientModeAllowed() {
@@ -297,16 +297,18 @@
 
   source->AddLocalizedStrings(kLocalizedStrings);
 
+  source->AddString("googlePhotosURL", GetGooglePhotosURL());
+
   source->AddString(
       "ambientModeAlbumsSubpageGooglePhotosTitle",
       l10n_util::GetStringFUTF16(
           IDS_PERSONALIZATION_APP_AMBIENT_MODE_ALBUMS_SUBPAGE_GOOGLE_PHOTOS_TITLE,
-          base::UTF8ToUTF16(GetGooglePhotosURL().spec())));
+          GetGooglePhotosURL()));
   source->AddString(
       "ambientModeAlbumsSubpageGooglePhotosNoAlbum",
       l10n_util::GetStringFUTF16(
           IDS_PERSONALIZATION_APP_AMBIENT_MODE_ALBUMS_SUBPAGE_GOOGLE_PHOTOS_NO_ALBUM,
-          base::UTF8ToUTF16(GetGooglePhotosURL().spec())));
+          GetGooglePhotosURL()));
 
   source->UseStringsJs();
   source->EnableReplaceI18nInJS();
@@ -420,6 +422,9 @@
 
   source->AddBoolean("isPersonalizationJellyEnabled",
                      features::IsPersonalizationJellyEnabled());
+
+  source->AddBoolean("isUserAvatarCustomizationSelectorsEnabled",
+                     user_provider_->IsCustomizationSelectorsPrefEnabled());
 }
 
 void PersonalizationAppUI::AddIntegers(content::WebUIDataSource* source) {
diff --git a/ash/webui/personalization_app/personalization_app_user_provider.h b/ash/webui/personalization_app/personalization_app_user_provider.h
index 79581934..7c13204 100644
--- a/ash/webui/personalization_app/personalization_app_user_provider.h
+++ b/ash/webui/personalization_app/personalization_app_user_provider.h
@@ -14,6 +14,11 @@
  public:
   virtual void BindInterface(
       mojo::PendingReceiver<mojom::UserProvider> receiver) = 0;
+
+  // Returns value of `kUserAvatarCustomizationSelectorsEnabled` pref. Avatar
+  // customization options that send data to google are only allowed if this
+  // pref is true.
+  virtual bool IsCustomizationSelectorsPrefEnabled() = 0;
 };
 
 }  // namespace ash::personalization_app
diff --git a/ash/webui/personalization_app/resources/css/cros_button_style.css b/ash/webui/personalization_app/resources/css/cros_button_style.css
index dc0b8914..c5c30e4f 100644
--- a/ash/webui/personalization_app/resources/css/cros_button_style.css
+++ b/ash/webui/personalization_app/resources/css/cros_button_style.css
@@ -11,14 +11,15 @@
   border-radius: 16px;
 }
 
+/* TODO: After Jelly launches, most of the cr-button colors can be removed. */
 cr-button.primary {
-  background-color: var(--cros-sys-primary, var(--cros-button-background-color-primary));
+  background-color: var(--cros-button-background-color-primary);
   border: 0;
-  --text-color: var(--cros-sys-on_primary, var(--cros-button-label-color-primary));
-  --ink-color: var(--cros-sys-ripple_primary, var(--cros-button-ripple-color-primary));
-  --hover-bg-color: var(--cros-sys-hover_on_prominent, var(--cros-button-background-color-primary-hover-preblended));
-  --disabled-bg: var(--cros-sys-disabled_container, var(--cros-button-background-color-primary-disabled));
-  --disabled-text-color: var(--cros-sys-disabled, var(--cros-button-label-color-primary-disabled));
+  --text-color: var(--cros-button-label-color-primary);
+  --ink-color: var(--cros-button-ripple-color-primary);
+  --hover-bg-color: var(--cros-button-background-color-primary-hover-preblended);
+  --disabled-bg: var(--cros-button-background-color-primary-disabled);
+  --disabled-text-color: var(--cros-button-label-color-primary-disabled);
 }
 
 cr-button.primary:active {
@@ -30,27 +31,23 @@
 }
 
 cr-button.primary:hover {
-  background-color: var(--cros-sys-hover_on_prominent, var(--cros-button-background-color-primary-hover-preblended));
+  background-color: var(--cros-button-background-color-primary-hover-preblended);
 }
 
 cr-button.secondary {
-  background-color: var(--cros-sys-primary_container, var(--cros-button-background-color-secondary));
+  background-color: var(--cros-button-background-color-secondary);
   border: 1px solid var(--cros-button-stroke-color-secondary);
-  --text-color: var(--cros-sys-on_primary_container, var(--cros-button-label-color-secondary));
+  --text-color: var(--cros-button-label-color-secondary);
   --border-color: var(--cros-button-stroke-color-secondary);
-  --ink-color: var(--cros-sys-ripple_primary, var(--cros-button-ripple-color-secondary));
+  --ink-color: var(--cros-button-ripple-color-secondary);
   --hover-border-color: var(--cros-button-stroke-color-secondary-hover);
-  --hover-bg-color: var(--cros-sys-hover_on_subtle, var(--cros-button-background-color-secondary-hover));
-  --disabled-text-color: var(--cros-sys-disabled, var(--cros-button-label-color-secondary-disabled));
+  --hover-bg-color: var(--cros-button-background-color-secondary-hover);
+  --disabled-text-color: var(--cros-button-label-color-secondary-disabled);
   --disabled-border-color: var(--cros-button-stroke-color-secondary-disabled);
 }
 
-:host-context(body.jelly-enabled) cr-button.secondary {
-  border: none;
-}
-
 cr-button.secondary:hover {
-  background-color: var(--cros-sys-hover_on_subtle, var(--cros-button-background-color-secondary-hover));
+  background-color: var(--cros-button-background-color-secondary-hover);
 }
 
 cr-icon-button:focus-visible,
diff --git a/ash/webui/personalization_app/resources/js/ambient/ambient_preview_large_element.html b/ash/webui/personalization_app/resources/js/ambient/ambient_preview_large_element.html
index d3bf78f..6cd7cf4 100644
--- a/ash/webui/personalization_app/resources/js/ambient/ambient_preview_large_element.html
+++ b/ash/webui/personalization_app/resources/js/ambient/ambient_preview_large_element.html
@@ -347,7 +347,7 @@
         <span class="text" id="turnOnDescription">
           $i18n{ambientModeMainPageEnterpriseUserMessage}
         </span>
-        <cr-button class="primary">
+        <cr-button class="primary action-button">
           <!-- TODO(b/258838122): on-click behavior -->
           <div>$i18n{ambientModeLearnMoreLabel}</div>
         </cr-button>
@@ -389,7 +389,7 @@
               $i18n{ambientModeMainPageZeroStateMessageV2}
             </span>
             <cr-button aria-describedby="turnOnDescription"
-                class="primary"
+                class="primary action-button"
                 on-click="onClickAmbientModeButton_">
               <span>$i18n{ambientModeTurnOnLabel}</span>
             </cr-button>
@@ -473,7 +473,7 @@
             $i18n{ambientModeMainPageZeroStateMessage}
           </span>
           <cr-button aria-describedby="turnOnDescription"
-              class="primary"
+              class="primary action-button"
               on-click="onClickAmbientModeButton_">
             <span>$i18n{ambientModeTurnOnLabel}</span>
           </cr-button>
diff --git a/ash/webui/personalization_app/resources/js/keyboard_backlight/zone_customization_element.html b/ash/webui/personalization_app/resources/js/keyboard_backlight/zone_customization_element.html
index 5fd0e55..ffebbf2 100644
--- a/ash/webui/personalization_app/resources/js/keyboard_backlight/zone_customization_element.html
+++ b/ash/webui/personalization_app/resources/js/keyboard_backlight/zone_customization_element.html
@@ -94,7 +94,8 @@
         on-wallpaper-color-selected="onWallpaperColorSelected_"
         on-preset-color-selected="onPresetColorSelected_">
       <div slot="button-container" class="customization-button-container">
-        <cr-button class="primary" id="dialogCloseButton" on-click="closeZoneCustomizationDialog_">
+        <cr-button class="primary action-button" id="dialogCloseButton"
+            on-click="closeZoneCustomizationDialog_">
           $i18n{dismissButtonText}
         </cr-button>
       </div>
diff --git a/ash/webui/personalization_app/resources/js/load_time_booleans.ts b/ash/webui/personalization_app/resources/js/load_time_booleans.ts
index 4133505a..2d2963a5 100644
--- a/ash/webui/personalization_app/resources/js/load_time_booleans.ts
+++ b/ash/webui/personalization_app/resources/js/load_time_booleans.ts
@@ -46,3 +46,7 @@
 export function isMultiZoneRgbKeyboardSupported() {
   return loadTimeData.getInteger('keyboardBacklightZoneCount') > 1;
 }
+
+export function isUserAvatarCustomizationSelectorsEnabled() {
+  return loadTimeData.getBoolean('isUserAvatarCustomizationSelectorsEnabled');
+}
diff --git a/ash/webui/personalization_app/resources/js/personalization_breadcrumb_element.html b/ash/webui/personalization_app/resources/js/personalization_breadcrumb_element.html
index 3273240..def516b 100644
--- a/ash/webui/personalization_app/resources/js/personalization_breadcrumb_element.html
+++ b/ash/webui/personalization_app/resources/js/personalization_breadcrumb_element.html
@@ -25,6 +25,15 @@
     width: 100%;
   }
 
+  /**
+   * TODO: After Jelly is launched, remove the cr-icon-button-fill-color
+   * references from #homeButton. The color will be inherited from
+   * cros_color_overrides.
+   */
+  :host-context(body.jelly-enabled) #homeButton {
+    --cr-icon-button-fill-color: var(--cros-sys-secondary);
+  }
+
   #homeButton {
     --cr-icon-button-fill-color: var(--cros-text-color-primary);
     --cr-icon-button-size: 36px;
@@ -58,6 +67,11 @@
     text-overflow: ellipsis;
     white-space: nowrap;
   }
+
+  :host-context(body.jelly-enabled) cr-button {
+    --text-color: var(--cros-sys-on_surface);
+    background-color: transparent;
+  }
 </style>
 <nav id="container">
     <iron-a11y-keys id="keys" keys="left right" on-keys-pressed="onKeysPress_">
diff --git a/ash/webui/personalization_app/resources/js/user/avatar_camera_element.html b/ash/webui/personalization_app/resources/js/user/avatar_camera_element.html
index f4ee4a6..8de64df4 100644
--- a/ash/webui/personalization_app/resources/js/user/avatar_camera_element.html
+++ b/ash/webui/personalization_app/resources/js/user/avatar_camera_element.html
@@ -133,13 +133,13 @@
     <div slot="footer">
       <template is="dom-if"
           if="[[showTakePhotoButton_(cameraStream_, previewBlobUrl_, captureInProgress_)]]">
-        <cr-button id="takePhoto" on-click="takePhoto_" class="primary">
+        <cr-button id="takePhoto" on-click="takePhoto_" class="primary action-button">
           <iron-icon icon="[[getTakePhotoIcon_(mode)]]"></iron-icon>
           <span>[[getTakePhotoText_(mode)]]</span>
         </cr-button>
       </template>
       <template is="dom-if" if="[[showLoadingSpinnerButton_(mode, cameraStream_, previewBlobUrl_, captureInProgress_)]]">
-        <cr-button id="loadingButton" class="primary" disabled>
+        <cr-button id="loadingButton" class="primary action-button" disabled>
           <paper-spinner-lite id="loadingButtonSpinner" active></paper-spinner-lite>
           <span>$i18n{webcamCaptureInProgress}</span>
         </cr-button>
@@ -149,7 +149,7 @@
           <iron-icon icon="personalization:refresh"></iron-icon>
           <span>$i18n{rejectWebcamPhoto}</span>
         </cr-button>
-        <cr-button id="confirmPhoto" on-click="confirmPhoto_" class="primary">
+        <cr-button id="confirmPhoto" on-click="confirmPhoto_" class="primary action-button">
           <iron-icon icon="personalization:circle_checkmark"></iron-icon>
           <span>[[getConfirmText_(mode)]]</span>
         </cr-button>
diff --git a/ash/webui/personalization_app/resources/js/user/avatar_list_element.ts b/ash/webui/personalization_app/resources/js/user/avatar_list_element.ts
index b922580..5a766fa 100644
--- a/ash/webui/personalization_app/resources/js/user/avatar_list_element.ts
+++ b/ash/webui/personalization_app/resources/js/user/avatar_list_element.ts
@@ -11,6 +11,7 @@
 import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';
 
 import {DefaultUserImage, UserImage} from '../../personalization_app.mojom-webui.js';
+import {isUserAvatarCustomizationSelectorsEnabled} from '../load_time_booleans.js';
 import {setErrorAction} from '../personalization_actions.js';
 import {WithPersonalizationStore} from '../personalization_store.js';
 import {decodeString16, getCheckmarkIcon, isNonEmptyArray, isSelectionEvent} from '../utils.js';
@@ -97,6 +98,14 @@
         value: null,
       },
 
+      /** Whether custom avatar selectors are enabled. */
+      isCustomizationSelectorsEnabled_: {
+        type: Boolean,
+        value() {
+          return isUserAvatarCustomizationSelectorsEnabled();
+        },
+      },
+
       /**
        * List of options to be displayed to the user.
        */
@@ -116,6 +125,7 @@
   private defaultUserImages_: DefaultUserImage[]|null;
   private profileImage_: Url|null;
   private isCameraPresent_: boolean;
+  private isCustomizationSelectorsEnabled_: boolean;
   private cameraMode_: AvatarCameraMode|null;
   private image_: UserImage|null;
   private lastExternalUserImageUrl_: Url|null;
@@ -149,46 +159,48 @@
       lastExternalUserImageUrl: AvatarList['lastExternalUserImageUrl_'],
       defaultUserImages: AvatarList['defaultUserImages_']) {
     const options: Option[] = [];
-    if (isCameraPresent) {
-      // Add camera and video options.
+    if (this.isCustomizationSelectorsEnabled_) {
+      if (isCameraPresent) {
+        // Add camera and video options.
+        options.push({
+          id: OptionId.OPEN_CAMERA,
+          class: 'avatar-button-container',
+          imgSrc: '',
+          icon: 'personalization:camera',
+          title: this.i18n('takeWebcamPhoto'),
+        });
+        options.push({
+          id: OptionId.OPEN_VIDEO,
+          class: 'avatar-button-container',
+          icon: 'personalization:loop',
+          title: this.i18n('takeWebcamVideo'),
+        });
+      }
+      // Add open folder option.
       options.push({
-        id: OptionId.OPEN_CAMERA,
+        id: OptionId.OPEN_FOLDER,
         class: 'avatar-button-container',
-        imgSrc: '',
-        icon: 'personalization:camera',
-        title: this.i18n('takeWebcamPhoto'),
+        icon: 'personalization:folder',
+        title: this.i18n('chooseAFile'),
       });
-      options.push({
-        id: OptionId.OPEN_VIDEO,
-        class: 'avatar-button-container',
-        icon: 'personalization:loop',
-        title: this.i18n('takeWebcamVideo'),
-      });
-    }
-    // Add open folder option.
-    options.push({
-      id: OptionId.OPEN_FOLDER,
-      class: 'avatar-button-container',
-      icon: 'personalization:folder',
-      title: this.i18n('chooseAFile'),
-    });
-    if (profileImage && profileImage.url) {
-      options.push({
-        id: OptionId.PROFILE_IMAGE,
-        class: 'image-container',
-        imgSrc: profileImage.url,
-        icon: getCheckmarkIcon(),
-        title: this.i18n('googleProfilePhoto'),
-      });
-    }
-    if (lastExternalUserImageUrl) {
-      options.push({
-        id: OptionId.LAST_EXTERNAL_IMAGE,
-        class: 'image-container',
-        imgSrc: lastExternalUserImageUrl.url,
-        icon: getCheckmarkIcon(),
-        title: this.i18n('lastExternalImageTitle'),
-      });
+      if (profileImage && profileImage.url) {
+        options.push({
+          id: OptionId.PROFILE_IMAGE,
+          class: 'image-container',
+          imgSrc: profileImage.url,
+          icon: getCheckmarkIcon(),
+          title: this.i18n('googleProfilePhoto'),
+        });
+      }
+      if (lastExternalUserImageUrl) {
+        options.push({
+          id: OptionId.LAST_EXTERNAL_IMAGE,
+          class: 'image-container',
+          imgSrc: lastExternalUserImageUrl.url,
+          icon: getCheckmarkIcon(),
+          title: this.i18n('lastExternalImageTitle'),
+        });
+      }
     }
     if (isNonEmptyArray(defaultUserImages)) {
       defaultUserImages.forEach(defaultImage => {
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_shared_album_dialog_element.html b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_shared_album_dialog_element.html
index a82c876..33af622 100644
--- a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_shared_album_dialog_element.html
+++ b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_shared_album_dialog_element.html
@@ -22,7 +22,7 @@
     <cr-button id="close" on-click="onClickClose_" class="secondary">
       <span>$i18n{googlePhotosSharedAlbumDialogCloseButton}</span>
     </cr-button>
-    <cr-button id="accept" on-click="onClickAccept_" class="primary">
+    <cr-button id="accept" on-click="onClickAccept_" class="primary action-button">
       <span>$i18n{googlePhotosSharedAlbumDialogAcceptButton}</span>
     </cr-button>
   </div>
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_zero_state_element.html b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_zero_state_element.html
index 6af63e1..49f342a1 100644
--- a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_zero_state_element.html
+++ b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_zero_state_element.html
@@ -7,12 +7,7 @@
     overflow: hidden;
   }
 
-  a {
-    color: var(--cros-link-color);
-    text-decoration: none;
-  }
-
-  div {
+  localized-link {
     color: var(--cros-text-color-secondary);
     font: var(--cros-body-1-font);
     max-width: 236px;
@@ -29,5 +24,5 @@
 </iron-media-query>
 <template is="dom-if" if="[[getMessageLabel_(tab)]]">
   <img src="[[getImageSource_(isDarkModeActive_)]]" aria-hidden="true">
-  <div id="message" inner-h-t-m-l="[[getMessage_(tab)]]"></div>
+  <localized-link id="message" localized-string="[[getMessage_(tab)]]"></localized-link>
 </template>
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_zero_state_element.ts b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_zero_state_element.ts
index 4d4a5c0..b4ae73d 100644
--- a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_zero_state_element.ts
+++ b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_zero_state_element.ts
@@ -6,6 +6,7 @@
  * @fileoverview Polymer element that displays the Google Photos zero state.
  */
 
+import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import '../../css/wallpaper.css.js';
 import '../../css/common.css.js';
 
@@ -59,7 +60,8 @@
     const label = this.getMessageLabel_(tab);
     return this.i18nAdvanced(label, {
       substitutions: [
-        '<a target="_blank" href="https://photos.google.com">photos.google.com</a>',
+        `<a target="_blank" href="${
+            this.i18n('googlePhotosURL')}">photos.google.com</a>`,
       ],
     });
   }
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/time_of_day_wallpaper_dialog_element.html b/ash/webui/personalization_app/resources/js/wallpaper/time_of_day_wallpaper_dialog_element.html
index ad2977c..f7436e5 100644
--- a/ash/webui/personalization_app/resources/js/wallpaper/time_of_day_wallpaper_dialog_element.html
+++ b/ash/webui/personalization_app/resources/js/wallpaper/time_of_day_wallpaper_dialog_element.html
@@ -17,7 +17,7 @@
     <cr-button id="close" on-click="onClickClose_" class="secondary">
       <span>$i18n{timeOfDayWallpaperDialogBackButton}</span>
     </cr-button>
-    <cr-button id="accept" on-click="onClickAccept_" class="primary">
+    <cr-button id="accept" on-click="onClickAccept_" class="primary action-button">
       <span>$i18n{timeOfDayWallpaperDialogConfirmButton}</span>
     </cr-button>
   </div>
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html
index e40321df..d4f4c7f 100644
--- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html
+++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html
@@ -166,7 +166,8 @@
           <p slot="body" id="descriptionDialogBody">[[image_.description.content]]</p>
         </template>
         <div slot="button-container">
-          <cr-button class="primary" id="dialogCloseButton" on-click="closeDescriptionDialog_">
+          <cr-button class="primary action-button" id="dialogCloseButton"
+              on-click="closeDescriptionDialog_">
             $i18n{descriptionDialogClose}
           </cr-button>
         </div>
diff --git a/ash/webui/personalization_app/test/fake_personalization_app_user_provider.cc b/ash/webui/personalization_app/test/fake_personalization_app_user_provider.cc
index 83935f6..3622b648 100644
--- a/ash/webui/personalization_app/test/fake_personalization_app_user_provider.cc
+++ b/ash/webui/personalization_app/test/fake_personalization_app_user_provider.cc
@@ -41,6 +41,10 @@
 void FakePersonalizationAppUserProvider::GetDefaultUserImages(
     GetDefaultUserImagesCallback callback) {}
 
+bool FakePersonalizationAppUserProvider::IsCustomizationSelectorsPrefEnabled() {
+  return true;
+}
+
 void FakePersonalizationAppUserProvider::SelectDefaultImage(int index) {}
 
 void FakePersonalizationAppUserProvider::SelectProfileImage() {}
diff --git a/ash/webui/personalization_app/test/fake_personalization_app_user_provider.h b/ash/webui/personalization_app/test/fake_personalization_app_user_provider.h
index 4fca440b..3a5cfa1 100644
--- a/ash/webui/personalization_app/test/fake_personalization_app_user_provider.h
+++ b/ash/webui/personalization_app/test/fake_personalization_app_user_provider.h
@@ -45,6 +45,7 @@
           observer) override;
   void GetUserInfo(GetUserInfoCallback callback) override;
   void GetDefaultUserImages(GetDefaultUserImagesCallback callback) override;
+  bool IsCustomizationSelectorsPrefEnabled() override;
   void SelectDefaultImage(int index) override;
   void SelectProfileImage() override;
   void SelectCameraImage(::mojo_base::BigBuffer data) override;
diff --git a/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc b/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc
index 326f31c..face4b0 100644
--- a/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc
+++ b/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc
@@ -278,6 +278,8 @@
               (::mojo_base::BigBuffer data),
               (override));
   MOCK_METHOD(void, SelectLastExternalUserImage, (), (override));
+
+  bool IsCustomizationSelectorsPrefEnabled() override { return true; }
 };
 
 }  // namespace
diff --git a/ash/webui/personalization_app/tools/gen_tsconfig.py b/ash/webui/personalization_app/tools/gen_tsconfig.py
index 9b9370b..2d0d4dc 100755
--- a/ash/webui/personalization_app/tools/gen_tsconfig.py
+++ b/ash/webui/personalization_app/tools/gen_tsconfig.py
@@ -91,11 +91,14 @@
             },
         },
         'files': [
-            # Add the .d.ts files.  Type definition only files are not
-            # picked up automatically with `rootDirs`.
+            # Add the .d.ts files.
             normalize_path(out_json_dir, path)
             for path in out_json['files'] if path.endswith('.d.ts')
         ],
+        'include': [
+            # Include every source file underneath the generated tsconfig.json.
+            '**/*'
+        ],
         'references': [{
             'path': normalize_path(out_json_dir, path['path'])
         } for path in out_json['references']],
diff --git a/ash/wm/desks/templates/saved_desk_icon_container.cc b/ash/wm/desks/templates/saved_desk_icon_container.cc
index c0fc761..2450935 100644
--- a/ash/wm/desks/templates/saved_desk_icon_container.cc
+++ b/ash/wm/desks/templates/saved_desk_icon_container.cc
@@ -278,8 +278,9 @@
   int used_width = -kIconSpacingDp;
   base::ranges::for_each(
       icon_views, [&used_width](SavedDeskIconView* icon_view) {
-        if (!icon_view->is_overflow_icon())
+        if (!icon_view->IsOverflowIcon()) {
           used_width += icon_view->GetPreferredSize().width() + kIconSpacingDp;
+        }
       });
 
   // Go through all non-overflow icons from back to front, and hide if:
diff --git a/ash/wm/desks/templates/saved_desk_icon_view.cc b/ash/wm/desks/templates/saved_desk_icon_view.cc
index c05026a2..68a7820 100644
--- a/ash/wm/desks/templates/saved_desk_icon_view.cc
+++ b/ash/wm/desks/templates/saved_desk_icon_view.cc
@@ -77,39 +77,24 @@
 
 // -----------------------------------------------------------------------------
 // SavedDeskIconView:
-SavedDeskIconView::SavedDeskIconView(const std::string& icon_identifier,
-                                     int count,
-                                     size_t sorting_key)
-    : icon_identifier_(icon_identifier),
-      count_(count),
-      sorting_key_(sorting_key) {}
+SavedDeskIconView::SavedDeskIconView(int count, size_t sorting_key)
+    : count_(count), sorting_key_(sorting_key) {}
 
 SavedDeskIconView::~SavedDeskIconView() = default;
 
 gfx::Size SavedDeskIconView::CalculatePreferredSize() const {
-  int width = (icon_view_ ? kIconViewSize : 0);
-  if (count_label_) {
-    if (GetCountToShow()) {
-      width += std::max(kIconViewSize,
-                        count_label_->CalculatePreferredSize().width());
-    }
-  }
-  return gfx::Size(width, kIconViewSize);
-}
+  // The width for the icon. The overflow icon doesn't have an icon so it's
+  // zero.
+  int width = (IsOverflowIcon() ? 0 : kIconViewSize);
 
-void SavedDeskIconView::Layout() {
-  if (icon_view_) {
-    gfx::Size icon_preferred_size = icon_view_->CalculatePreferredSize();
-    icon_view_->SetBoundsRect(gfx::Rect(
-        base::ClampFloor((kIconViewSize - icon_preferred_size.width()) / 2.0),
-        base::ClampFloor((kIconViewSize - icon_preferred_size.height()) / 2.0),
-        icon_preferred_size.width(), icon_preferred_size.height()));
-  }
-  if (count_label_) {
-    count_label_->SetBoundsRect(
-        gfx::Rect(icon_view_ ? kIconViewSize : 0, 0,
-                  width() - (icon_view_ ? kIconViewSize : 0), kIconViewSize));
-  }
+  // Add the label width if the label view exists. The reason for having the max
+  // is to have a minimum width.
+  width += count_label_
+               ? std::max(kIconViewSize,
+                          count_label_->CalculatePreferredSize().width())
+               : 0;
+
+  return gfx::Size(width, kIconViewSize);
 }
 
 void SavedDeskIconView::UpdateCount(int count) {
@@ -145,7 +130,8 @@
     int count,
     size_t sorting_key,
     base::OnceCallback<void(views::View*)> on_icon_loaded)
-    : SavedDeskIconView(icon_identifier, count, sorting_key),
+    : SavedDeskIconView(count, sorting_key),
+      icon_identifier_(icon_identifier),
       on_icon_loaded_(std::move(on_icon_loaded)) {
   if (GetCountToShow()) {
     SetBackground(views::CreateThemedRoundedRectBackground(
@@ -158,6 +144,20 @@
 
 SavedDeskRegularIconView::~SavedDeskRegularIconView() = default;
 
+void SavedDeskRegularIconView::Layout() {
+  DCHECK(icon_view_);
+  gfx::Size icon_preferred_size = icon_view_->CalculatePreferredSize();
+  icon_view_->SetBoundsRect(gfx::Rect(
+      base::ClampFloor((kIconViewSize - icon_preferred_size.width()) / 2.0),
+      base::ClampFloor((kIconViewSize - icon_preferred_size.height()) / 2.0),
+      icon_preferred_size.width(), icon_preferred_size.height()));
+
+  if (count_label_) {
+    count_label_->SetBoundsRect(
+        gfx::Rect(kIconViewSize, 0, width() - kIconViewSize, kIconViewSize));
+  }
+}
+
 void SavedDeskRegularIconView::OnThemeChanged() {
   SavedDeskIconView::OnThemeChanged();
 
@@ -180,6 +180,10 @@
   return count_ - 1;
 }
 
+bool SavedDeskRegularIconView::IsOverflowIcon() const {
+  return false;
+}
+
 void SavedDeskRegularIconView::CreateChildViews(
     const ui::ColorProvider* incognito_window_color_provider,
     const std::string& app_title) {
@@ -276,7 +280,7 @@
 // -----------------------------------------------------------------------------
 // SavedDeskOverflowIconView:
 SavedDeskOverflowIconView::SavedDeskOverflowIconView(int count, bool show_plus)
-    : SavedDeskIconView("", count, kOverflowIconSortingKey) {
+    : SavedDeskIconView(count, kOverflowIconSortingKey) {
   SetBackground(views::CreateThemedRoundedRectBackground(
       cros_tokens::kCrosSysSystemOnBase,
       /*radius=*/kIconViewSize / 2.0f));
@@ -286,6 +290,11 @@
 
 SavedDeskOverflowIconView::~SavedDeskOverflowIconView() = default;
 
+void SavedDeskOverflowIconView::Layout() {
+  DCHECK(count_label_);
+  count_label_->SetBoundsRect(gfx::Rect(0, 0, width(), kIconViewSize));
+}
+
 void SavedDeskOverflowIconView::UpdateCount(int count) {
   DCHECK(count_label_);
   count_ = count;
@@ -306,6 +315,10 @@
   return count_;
 }
 
+bool SavedDeskOverflowIconView::IsOverflowIcon() const {
+  return true;
+}
+
 BEGIN_METADATA(SavedDeskOverflowIconView, views::View)
 END_METADATA
 
diff --git a/ash/wm/desks/templates/saved_desk_icon_view.h b/ash/wm/desks/templates/saved_desk_icon_view.h
index 851f17e9..21a1960 100644
--- a/ash/wm/desks/templates/saved_desk_icon_view.h
+++ b/ash/wm/desks/templates/saved_desk_icon_view.h
@@ -33,30 +33,16 @@
  public:
   METADATA_HEADER(SavedDeskIconView);
 
-  // Create an icon view for an app. Sets `icon_identifier_` to
-  // `icon_identifier` and `count_` to `count` then based on their values
-  // determines what views need to be created and starts loading the icon
-  // specified by `icon_identifier`. `sorting_key` is the key that is used for
-  // sorting by the icon container.
-  SavedDeskIconView(const std::string& icon_identifier,
-                    int count,
-                    size_t sorting_key);
+  // Create an icon view for an app. Sets `count` to `count_`. `sorting_key` is
+  // the key that is used for sorting by the icon container.
+  SavedDeskIconView(int count, size_t sorting_key);
 
   SavedDeskIconView(const SavedDeskIconView&) = delete;
   SavedDeskIconView& operator=(const SavedDeskIconView&) = delete;
   ~SavedDeskIconView() override;
 
-  // TODO(b/256224473): Remove this function and `icon_identifier_`. It seems
-  // that we just use it for unit tests. We could be passing icon_identifier
-  // directly from `SavedDeskRegularIconView` constructor to
-  // `CreateChildViews()` and then we wouldn't need to hold on to this string.
-  const std::string& icon_identifier() const { return icon_identifier_; }
-
-  bool is_overflow_icon() const { return icon_identifier_.empty(); }
-
   // views::View:
   gfx::Size CalculatePreferredSize() const override;
-  void Layout() override;
 
   // Sets `count_` to `count` and updates the `count_label_`. Please note,
   // currently it does not support update on regular icon.
@@ -77,14 +63,14 @@
   // the overflow icon view, this should be `count_`.
   virtual int GetCountToShow() const = 0;
 
+  // Returns true if the icon view is a overflow icon view; otherwise, returns
+  // false;
+  virtual bool IsOverflowIcon() const = 0;
+
  protected:
   // Creates the child view for the count label.
   void CreateCountLabelChildView(bool show_plus, int inset_size);
 
-  // The identifier for an icon. For a favicon, this will be a url. For an app,
-  // this will be an app id. For an overflow icon, it'll be an empty string.
-  std::string icon_identifier_;
-
   // The number of instances of this icon's respective app/url stored in this's
   // respective SavedDesk.
   int count_ = 0;
@@ -95,10 +81,6 @@
   // Owned by the views hierarchy.
   views::Label* count_label_ = nullptr;
 
-  // TODO(b/256224473): It seems like we can make `icon_view_` private in
-  // `SavedDeskRegularIconView`, because only regular icons have this view.
-  RoundedImageView* icon_view_ = nullptr;
-
  private:
   friend class SavedDeskIconViewTestApi;
 
@@ -123,12 +105,17 @@
   ~SavedDeskRegularIconView() override;
 
   bool is_showing_default_icon() const { return is_showing_default_icon_; }
+  const std::string& icon_identifier() const { return icon_identifier_; }
+
+  // views::View:
+  void Layout() override;
 
   // SavedDeskIconView:
   void OnThemeChanged() override;
   size_t GetSortingKey() const override;
   int GetCount() const override;
   int GetCountToShow() const override;
+  bool IsOverflowIcon() const override;
 
  private:
   // Creates the child views for this icon view. Will start the asynchronous
@@ -149,6 +136,12 @@
   // True if this icon view is showing the default (fallback) icon.
   bool is_showing_default_icon_ = false;
 
+  // The identifier for an icon. For a favicon, this will be a url. For an app,
+  // this will be an app id.
+  std::string icon_identifier_;
+
+  RoundedImageView* icon_view_ = nullptr;
+
   // Callback from the icon container that updates the icon order and overflow
   // icon.
   base::OnceCallback<void(views::View*)> on_icon_loaded_;
@@ -171,11 +164,15 @@
       delete;
   ~SavedDeskOverflowIconView() override;
 
+  // views::View:
+  void Layout() override;
+
   // SavedDeskIconView:
   void UpdateCount(int count) override;
   size_t GetSortingKey() const override;
   int GetCount() const override;
   int GetCountToShow() const override;
+  bool IsOverflowIcon() const override;
 };
 
 }  // namespace ash
diff --git a/ash/wm/desks/templates/saved_desk_test_util.h b/ash/wm/desks/templates/saved_desk_test_util.h
index 918127df..0af8fd2 100644
--- a/ash/wm/desks/templates/saved_desk_test_util.h
+++ b/ash/wm/desks/templates/saved_desk_test_util.h
@@ -25,7 +25,6 @@
 class IconButton;
 class OverviewGrid;
 class PillButton;
-class RoundedImageView;
 class SavedDeskPresenter;
 
 // Wrapper for `SavedDeskPresenter` that exposes internal state to test
@@ -135,10 +134,6 @@
     return saved_desk_icon_view_->count_label_;
   }
 
-  const RoundedImageView* icon_view() const {
-    return saved_desk_icon_view_->icon_view_;
-  }
-
   const SavedDeskIconView* saved_desk_icon_view() const {
     return saved_desk_icon_view_;
   }
diff --git a/ash/wm/desks/templates/saved_desk_unittest.cc b/ash/wm/desks/templates/saved_desk_unittest.cc
index ca446db3..f8e57a5 100644
--- a/ash/wm/desks/templates/saved_desk_unittest.cc
+++ b/ash/wm/desks/templates/saved_desk_unittest.cc
@@ -228,6 +228,12 @@
     return overview_grid->GetSaveDeskButtonContainer();
   }
 
+  SavedDeskRegularIconView* GetSavedDeskRegularIconView(
+      SavedDeskIconView* icon_view) {
+    DCHECK(!icon_view->IsOverflowIcon());
+    return static_cast<SavedDeskRegularIconView*>(icon_view);
+  }
+
   // Shows the saved desk library by emulating a click on the library button. It
   // is required to have at least one entry in the desk model for the button to
   // be visible and clickable.
@@ -1335,8 +1341,9 @@
   int previous_id;
   for (size_t i = 0; i < icon_views.size() - 1; ++i) {
     int current_id;
-    ASSERT_TRUE(
-        base::StringToInt(icon_views[i]->icon_identifier(), &current_id));
+    ASSERT_TRUE(base::StringToInt(
+        GetSavedDeskRegularIconView(icon_views[i])->icon_identifier(),
+        &current_id));
 
     if (i)
       EXPECT_TRUE(current_id > previous_id);
@@ -1449,10 +1456,14 @@
   // with the lowest activation indices, i.e. the rest of the tabs from the
   // first browser instance.
   ASSERT_EQ(7u, icon_views.size());
-  EXPECT_EQ(kTabs1[kActiveTabIndex1].spec(), icon_views[0]->icon_identifier());
-  EXPECT_EQ(kTabs2[kActiveTabIndex2].spec(), icon_views[1]->icon_identifier());
-  EXPECT_EQ(kTabs1[0].spec(), icon_views[2]->icon_identifier());
-  EXPECT_EQ(kTabs1[2].spec(), icon_views[3]->icon_identifier());
+  EXPECT_EQ(kTabs1[kActiveTabIndex1].spec(),
+            GetSavedDeskRegularIconView(icon_views[0])->icon_identifier());
+  EXPECT_EQ(kTabs2[kActiveTabIndex2].spec(),
+            GetSavedDeskRegularIconView(icon_views[1])->icon_identifier());
+  EXPECT_EQ(kTabs1[0].spec(),
+            GetSavedDeskRegularIconView(icon_views[2])->icon_identifier());
+  EXPECT_EQ(kTabs1[2].spec(),
+            GetSavedDeskRegularIconView(icon_views[3])->icon_identifier());
 }
 
 // Tests that when two tabs are put into a desk template that have the same
@@ -1496,7 +1507,8 @@
   // The first icon view should have the first url including the query parameter
   // as its identifier, and have a count of 2 because its representing both
   // urls.
-  EXPECT_EQ(kTabs[0].spec(), icon_views[0]->icon_identifier());
+  EXPECT_EQ(kTabs[0].spec(),
+            GetSavedDeskRegularIconView(icon_views[0])->icon_identifier());
   EXPECT_EQ(2, icon_views[0]->GetCount());
   // The second icon view should have a count of 0, because there are no
   // overflow windows.
@@ -1535,7 +1547,7 @@
   // non-zero. It should also be visible and within the bounds of the host
   // SavedDeskItemView.
   SavedDeskIconViewTestApi overflow_icon_view{icon_views.back()};
-  EXPECT_FALSE(overflow_icon_view.icon_view());
+  EXPECT_TRUE(overflow_icon_view.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(overflow_icon_view.count_label());
   EXPECT_EQ(u"+1", overflow_icon_view.count_label()->GetText());
   EXPECT_TRUE(overflow_icon_view.saved_desk_icon_view()->GetVisible());
@@ -1601,7 +1613,7 @@
   // app icons. It should also be visible and within the bounds of the host
   // SavedDeskItemView.
   SavedDeskIconViewTestApi overflow_icon_view{icon_views.back()};
-  EXPECT_FALSE(overflow_icon_view.icon_view());
+  EXPECT_TRUE(overflow_icon_view.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(overflow_icon_view.count_label());
 
   // (3 + 4) * 2 = 14 windows were added to the desk template, from 7 apps with
@@ -1645,36 +1657,36 @@
   // Verify each of the apps' count labels are correct.
   SavedDeskIconViewTestApi icon_view_1(icon_views[0]);
   EXPECT_TRUE(icon_view_1.saved_desk_icon_view()->GetVisible());
-  EXPECT_TRUE(icon_view_1.icon_view());
+  EXPECT_FALSE(icon_view_1.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_FALSE(icon_view_1.count_label());
 
   SavedDeskIconViewTestApi icon_view_2(icon_views[1]);
   EXPECT_TRUE(icon_view_2.saved_desk_icon_view()->GetVisible());
-  EXPECT_TRUE(icon_view_2.icon_view());
+  EXPECT_FALSE(icon_view_2.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_FALSE(icon_view_2.count_label());
 
   SavedDeskIconViewTestApi icon_view_3(icon_views[2]);
   EXPECT_TRUE(icon_view_3.saved_desk_icon_view()->GetVisible());
-  EXPECT_TRUE(icon_view_3.icon_view());
+  EXPECT_FALSE(icon_view_3.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(icon_view_3.count_label());
   EXPECT_EQ(u"+1", icon_view_3.count_label()->GetText());
 
   SavedDeskIconViewTestApi icon_view_4(icon_views[3]);
   EXPECT_FALSE(icon_view_4.saved_desk_icon_view()->GetVisible());
-  EXPECT_TRUE(icon_view_4.icon_view());
+  EXPECT_FALSE(icon_view_4.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(icon_view_4.count_label());
   EXPECT_EQ(u"+1", icon_view_4.count_label()->GetText());
 
   SavedDeskIconViewTestApi icon_view_5(icon_views[4]);
   EXPECT_FALSE(icon_view_5.saved_desk_icon_view()->GetVisible());
-  EXPECT_TRUE(icon_view_5.icon_view());
+  EXPECT_FALSE(icon_view_5.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(icon_view_5.count_label());
   EXPECT_EQ(u"+2", icon_view_5.count_label()->GetText());
 
   // The overflow counter should display the number of excess windows.
   SavedDeskIconViewTestApi overflow_icon_view{icon_views.back()};
   EXPECT_TRUE(overflow_icon_view.saved_desk_icon_view()->GetVisible());
-  EXPECT_FALSE(overflow_icon_view.icon_view());
+  EXPECT_TRUE(overflow_icon_view.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(overflow_icon_view.count_label());
   EXPECT_EQ(u"+5", overflow_icon_view.count_label()->GetText());
 }
@@ -1702,7 +1714,7 @@
 
   // The app's icon view should have a "+99" label.
   SavedDeskIconViewTestApi icon_view(icon_views[0]);
-  EXPECT_TRUE(icon_view.icon_view());
+  EXPECT_FALSE(icon_view.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(icon_view.count_label());
   EXPECT_EQ(u"+99", icon_view.count_label()->GetText());
 
@@ -1762,7 +1774,7 @@
   EXPECT_EQ(3u, icon_views.size());
 
   SavedDeskIconViewTestApi overflow_icon_view{icon_views.back()};
-  EXPECT_FALSE(overflow_icon_view.icon_view());
+  EXPECT_TRUE(overflow_icon_view.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(overflow_icon_view.count_label());
   EXPECT_EQ(u"+2", overflow_icon_view.count_label()->GetText());
 }
@@ -1799,7 +1811,7 @@
   EXPECT_EQ(SavedDeskIconContainer::kMaxIcons + 1, num_of_visibile_icon_views);
 
   SavedDeskIconViewTestApi overflow_icon_view{icon_views.back()};
-  EXPECT_FALSE(overflow_icon_view.icon_view());
+  EXPECT_TRUE(overflow_icon_view.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(overflow_icon_view.count_label());
   EXPECT_EQ(u"+4", overflow_icon_view.count_label()->GetText());
 }
@@ -1830,7 +1842,7 @@
   EXPECT_EQ(1u, icon_views.size());
 
   SavedDeskIconViewTestApi overflow_icon_view{icon_views.back()};
-  EXPECT_FALSE(overflow_icon_view.icon_view());
+  EXPECT_TRUE(overflow_icon_view.saved_desk_icon_view()->IsOverflowIcon());
   EXPECT_TRUE(overflow_icon_view.count_label());
   EXPECT_EQ(u"10", overflow_icon_view.count_label()->GetText());
 }
diff --git a/ash/wm/float/float_controller.cc b/ash/wm/float/float_controller.cc
index b9b67e0..f040e4ce 100644
--- a/ash/wm/float/float_controller.cc
+++ b/ash/wm/float/float_controller.cc
@@ -17,6 +17,7 @@
 #include "ash/wm/desks/desk.h"
 #include "ash/wm/desks/desks_util.h"
 #include "ash/wm/float/scoped_window_tucker.h"
+#include "ash/wm/float/tablet_mode_tuck_education.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_window_state.h"
@@ -150,6 +151,11 @@
 
     if (desk->is_active())
       float_start_time_ = base::TimeTicks::Now();
+
+    if (Shell::Get()->tablet_mode_controller()->InTabletMode()) {
+      tuck_education_ =
+          std::make_unique<TabletModeTuckEducation>(floated_window);
+    }
   }
 
   FloatedWindowInfo(const FloatedWindowInfo&) = delete;
@@ -260,6 +266,9 @@
   // a normal window state. Null when `floated_window_` is currently not tucked.
   std::unique_ptr<ScopedWindowTucker> scoped_window_tucker_;
 
+  // An object responsible for managing the tuck education nudge and animations.
+  std::unique_ptr<TabletModeTuckEducation> tuck_education_;
+
   // Used to get the tucked window bounds (as opposed to normal floated). False
   // during `scoped_window_tucker_` construction.
   bool is_tucked_for_tablet_ = false;
@@ -632,6 +641,10 @@
   target_desk->NotifyContentChanged();
 }
 
+void FloatController::ClearWorkspaceEventHandler(aura::Window* root) {
+  workspace_event_handlers_.erase(root);
+}
+
 void FloatController::OnTabletModeStarted() {
   DCHECK(!floated_window_info_map_.empty());
   // If a window can still remain floated, update its bounds, otherwise unfloat
@@ -681,6 +694,15 @@
   if (auto* activated_desk_floated_window =
           FindFloatedWindowOfDesk(activated)) {
     ShowFloatedWindow(activated_desk_floated_window);
+
+    // Activate the floated window if it is the top window. This is normally
+    // done in `Desk::Activate`, but floated windows are technically not owned
+    // by the desk, and the window is still hidden at that point so it isn't in
+    // the MRU list.
+    if (auto* top_window = window_util::GetTopWindow();
+        top_window == activated_desk_floated_window) {
+      wm::ActivateWindow(top_window);
+    }
   }
 }
 
@@ -724,14 +746,6 @@
       ->SetLayoutManager(std::make_unique<FloatLayoutManager>());
 }
 
-void FloatController::OnRootWindowWillShutdown(aura::Window* root_window) {
-  workspace_event_handlers_.erase(root_window);
-}
-
-void FloatController::OnShellDestroying() {
-  workspace_event_handlers_.clear();
-}
-
 void FloatController::ToggleFloat(aura::Window* window) {
   WindowState* window_state = WindowState::Get(window);
   const WMEvent toggle_event(window_state->IsFloated() ? WM_EVENT_RESTORE
@@ -745,8 +759,9 @@
 
   FloatImpl(window);
 
-  if (!chromeos::IsSnappedWindowStateType(old_state_type))
+  if (!chromeos::IsSnappedWindowStateType(old_state_type)) {
     return;
+  }
 
   // Update magnetism so that the float window is roughly in the same location
   // as it was when it was snapped.
diff --git a/ash/wm/float/float_controller.h b/ash/wm/float/float_controller.h
index 21b7bbc4..4ebcb1e 100644
--- a/ash/wm/float/float_controller.h
+++ b/ash/wm/float/float_controller.h
@@ -114,6 +114,8 @@
                                    Desk* target_desk,
                                    aura::Window* target_root);
 
+  void ClearWorkspaceEventHandler(aura::Window* root);
+
   // TabletModeObserver:
   void OnTabletModeStarted() override;
   void OnTabletModeEnding() override;
@@ -129,8 +131,6 @@
 
   // ShellObserver:
   void OnRootWindowAdded(aura::Window* root_window) override;
-  void OnRootWindowWillShutdown(aura::Window* root_window) override;
-  void OnShellDestroying() override;
 
   // chromeos::FloatControllerBase:
   void ToggleFloat(aura::Window* window) override;
diff --git a/ash/wm/float/float_controller_unittest.cc b/ash/wm/float/float_controller_unittest.cc
index 88b97ae4..d10df26b 100644
--- a/ash/wm/float/float_controller_unittest.cc
+++ b/ash/wm/float/float_controller_unittest.cc
@@ -59,6 +59,7 @@
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/test/test_widget_observer.h"
 #include "ui/views/test/views_test_utils.h"
+#include "ui/views/widget/any_widget_observer.h"
 #include "ui/wm/core/window_util.h"
 
 namespace ash {
@@ -730,6 +731,33 @@
   EXPECT_TRUE(desk_1->is_active());
 }
 
+// Tests that if a float window was activated before changing desks, it will be
+// activated when returning to that desk.
+TEST_F(WindowFloatTest, FloatWindowActivatesWhenChangingDesks) {
+  auto* desks_controller = DesksController::Get();
+
+  // Create a floated window on desk 1. We expect this window to be active later
+  // when we return to desk 1.
+  std::unique_ptr<aura::Window> floated_window1 = CreateFloatedWindow();
+  ASSERT_TRUE(WindowState::Get(floated_window1.get())->IsActive());
+
+  // Create a new desk with a floated window and a normal window. The normal
+  // window should be activated.
+  NewDesk();
+  ActivateDesk(desks_controller->desks()[1].get());
+  std::unique_ptr<aura::Window> floated_window2 = CreateFloatedWindow();
+  std::unique_ptr<aura::Window> normal_window = CreateAppWindow();
+  ASSERT_TRUE(WindowState::Get(normal_window.get())->IsActive());
+
+  // Switch to desk 1, the first floated window should be active.
+  ActivateDesk(desks_controller->desks()[0].get());
+  EXPECT_TRUE(WindowState::Get(floated_window1.get())->IsActive());
+
+  // Switch to desk 2, the normal window should be active.
+  ActivateDesk(desks_controller->desks()[1].get());
+  EXPECT_TRUE(WindowState::Get(normal_window.get())->IsActive());
+}
+
 // Test when we combine desks, floated window is updated on overview.
 TEST_F(WindowFloatTest, FloatWindowUpdatedOnOverview) {
   auto* desks_controller = DesksController::Get();
@@ -1787,6 +1815,31 @@
   EXPECT_EQ(0, user_action_tester_.GetActionCount(kTuckUserAction));
 }
 
+// Tests that the tuck education nudge appears when the window is first floated.
+TEST_F(TabletWindowFloatTest, BasicTuckNudge) {
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+
+  std::unique_ptr<aura::Window> window = CreateAppWindow();
+
+  // Add observer to check that the tuck education nudge was created.
+  views::NamedWidgetShownWaiter widget_waiter(
+      views::test::AnyWidgetTestPasskey{}, "TuckEducationNudgeWidget");
+
+  // Float window using accelerator.
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  ASSERT_TRUE(WindowState::Get(window.get())->IsFloated());
+
+  // If waiter never sees the tuck education nudge, it will hang forever, and
+  // the test will fail.
+  widget_waiter.WaitIfNeededAndGet();
+
+  // Nudge should dismiss properly after animations end.
+  EXPECT_TRUE(window->children().empty());
+
+  // TODO(hewer): Add a callback to check that the nudge has properly dismissed
+  // after the bounce animations and timer have ended.
+}
+
 using TabletWindowFloatSplitviewTest = TabletWindowFloatTest;
 
 // Tests the expected behaviour when a window is floated when there are snapped
diff --git a/ash/wm/float/tablet_mode_tuck_education.cc b/ash/wm/float/tablet_mode_tuck_education.cc
new file mode 100644
index 0000000..180774a
--- /dev/null
+++ b/ash/wm/float/tablet_mode_tuck_education.cc
@@ -0,0 +1,179 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/wm/float/tablet_mode_tuck_education.h"
+
+#include "ash/shell.h"
+#include "ash/strings/grit/ash_strings.h"
+#include "ash/style/rounded_label.h"
+#include "base/functional/bind.h"
+#include "base/time/time.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/color/color_id.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animator.h"
+#include "ui/compositor/property_change_reason.h"
+#include "ui/display/display.h"
+#include "ui/gfx/animation/tween.h"
+#include "ui/gfx/geometry/transform_util.h"
+#include "ui/views/animation/animation_builder.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+
+namespace {
+
+// The vertical distance from the top of `window_` to the nudge.
+constexpr int kNudgeYOffset = 38;
+// The time it takes for the nudge to fade in or out.
+constexpr base::TimeDelta kNudgeFadeDuration = base::Milliseconds(100);
+// The timer after the second bounce finishes until the nudge starts to fade
+// out.
+constexpr base::TimeDelta kNudgeFadeOutDelay = base::Milliseconds(150);
+
+// The maximum distance the window translates by during the bounce.
+constexpr float kBounceDistance = 50.0f;
+// The time after the first bounce ends and the second bounce begins.
+constexpr base::TimeDelta kSecondBounceDelay = base::Seconds(1);
+// The time for the window to move from its starting position to its furthest
+// position.
+constexpr base::TimeDelta kBounceStartDuration = base::Milliseconds(400);
+// The time for the window to move from its furthest position to back to its
+// original position.
+constexpr base::TimeDelta kBounceEndDuration = base::Milliseconds(700);
+
+// RoundedLabel construction values.
+constexpr int kLabelPadding = 8;
+constexpr int kLabelHeight = 28;
+constexpr float kRoundedDivisor = 2.f;
+
+std::unique_ptr<views::Widget> CreateWidget(aura::Window* window) {
+  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
+  params.name = "TuckEducationNudgeWidget";
+  params.accept_events = false;
+  params.parent = window;
+  params.child = true;
+
+  auto widget = std::make_unique<views::Widget>(std::move(params));
+
+  auto nudge_label = std::make_unique<RoundedLabel>(
+      kLabelPadding, kLabelPadding, kLabelHeight / kRoundedDivisor,
+      kLabelHeight,
+      l10n_util::GetStringUTF16(IDS_ASH_TUCK_EDUCATIONAL_NUDGE_LABEL));
+
+  // TODO(hewer): Update label color to `ui::kColorSysSurface3` to match other
+  // nudges.
+  widget->SetContentsView(std::move(nudge_label));
+
+  return widget;
+}
+
+}  // namespace
+
+TabletModeTuckEducation::TabletModeTuckEducation(aura::Window* floated_window) {
+  // Observe for end of floating crossfade animation to begin education.
+  window_ = floated_window;
+  window_observation_.Observe(window_);
+}
+
+TabletModeTuckEducation::~TabletModeTuckEducation() = default;
+
+void TabletModeTuckEducation::OnWindowTransformed(
+    aura::Window* window,
+    ui::PropertyChangeReason reason) {
+  // Floating a window causes a crossfade animation that can interfere with
+  // other animations or actions performed on the window at the same time. We
+  // observe for the crossfade to finish before performing the bounce.
+  bool animating = window->layer()->GetAnimator()->IsAnimatingProperty(
+      ui::LayerAnimationElement::TRANSFORM);
+  if (!nudge_widget_ && !animating &&
+      reason == ui::PropertyChangeReason::FROM_ANIMATION) {
+    ActivateTuckEducation();
+  }
+}
+
+void TabletModeTuckEducation::ActivateTuckEducation() {
+  // No need to observe for the transform animation (crossfade) to finish as
+  // soon as it has happened once.
+  window_observation_.Reset();
+
+  // TODO(b/275255478): Add checks so the nudge only shows 3 times max with at
+  // least 24h between.
+
+  nudge_widget_ = CreateWidget(window_);
+
+  nudge_widget_->Show();
+  auto* nudge_layer = nudge_widget_->GetLayer();
+  nudge_layer->SetOpacity(0.0f);
+
+  gfx::Size nudge_pref_size =
+      nudge_widget_->GetContentsView()->GetPreferredSize();
+  gfx::Rect window_bounds = window_->GetBoundsInScreen();
+  gfx::Rect new_bounds((window_bounds.width() - nudge_pref_size.width()) / 2,
+                       kNudgeYOffset, nudge_pref_size.width(),
+                       nudge_pref_size.height());
+  nudge_widget_->SetBounds(new_bounds);
+
+  const display::Display display =
+      display::Screen::GetScreen()->GetDisplayNearestWindow(window_);
+
+  bool bounce_right =
+      window_bounds.CenterPoint().x() > display.bounds().CenterPoint().x();
+
+  // Move towards edge of screen.
+  const gfx::Transform side_transform = gfx::Transform::MakeTranslation(
+      bounce_right ? kBounceDistance : -kBounceDistance, 0);
+
+  // Move back to starting position.
+  const gfx::Transform reset_transform = gfx::Transform();
+
+  views::AnimationBuilder()
+      .OnAborted(base::BindOnce(&TabletModeTuckEducation::DismissNudge,
+                                weak_factory_.GetWeakPtr()))
+      .OnEnded(base::BindOnce(&TabletModeTuckEducation::DismissNudge,
+                              weak_factory_.GetWeakPtr()))
+      .SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION)
+      // Fade nudge in.
+      .Once()
+      .SetDuration(kNudgeFadeDuration)
+      .SetOpacity(nudge_widget_->GetLayer(), 1.0f, gfx::Tween::LINEAR)
+      // First bounce.
+      .Then()
+      .SetDuration(kBounceStartDuration)
+      .SetTransform(window_, side_transform, gfx::Tween::ACCEL_20_DECEL_100)
+      .Then()
+      .SetDuration(kBounceEndDuration)
+      .SetTransform(window_, reset_transform, gfx::Tween::ACCEL_20_DECEL_100)
+      // Delay before second bounce.
+      .Then()
+      .SetDuration(kSecondBounceDelay)
+      // Second bounce.
+      .Then()
+      .SetDuration(kBounceStartDuration)
+      .SetTransform(window_, side_transform, gfx::Tween::ACCEL_20_DECEL_100)
+      .Then()
+      .SetDuration(kBounceEndDuration)
+      .SetTransform(window_, reset_transform, gfx::Tween::ACCEL_20_DECEL_100)
+      // Delay before fading out.
+      .Then()
+      .SetDuration(kNudgeFadeOutDelay)
+      // Fade nudge out.
+      .Then()
+      .SetDuration(kNudgeFadeDuration)
+      .SetOpacity(nudge_widget_->GetLayer(), 0.0f, gfx::Tween::LINEAR);
+}
+
+void TabletModeTuckEducation::DismissNudge() {
+  window_ = nullptr;
+
+  if (nudge_widget_ && !nudge_widget_->IsClosed()) {
+    nudge_widget_->GetLayer()->GetAnimator()->AbortAllAnimations();
+    nudge_widget_->CloseNow();
+  }
+
+  // TODO(b/275420014): Destroy `this` once animations finish as no more actions
+  // need to be performed.
+}
+
+}  // namespace ash
diff --git a/ash/wm/float/tablet_mode_tuck_education.h b/ash/wm/float/tablet_mode_tuck_education.h
new file mode 100644
index 0000000..55135b3
--- /dev/null
+++ b/ash/wm/float/tablet_mode_tuck_education.h
@@ -0,0 +1,55 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WM_FLOAT_TABLET_MODE_TUCK_EDUCATION_H_
+#define ASH_WM_FLOAT_TABLET_MODE_TUCK_EDUCATION_H_
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
+#include "ui/views/widget/unique_widget_ptr.h"
+
+namespace ash {
+
+// This class is responsible for educating users about the tuck gesture when
+// a window is floated in tablet mode. It shows a nudge with text indicating the
+// gesture to tuck, and bounces the floated window twice.
+class TabletModeTuckEducation : public aura::WindowObserver {
+ public:
+  explicit TabletModeTuckEducation(aura::Window* floated_window);
+  TabletModeTuckEducation(const TabletModeTuckEducation&) = delete;
+  TabletModeTuckEducation& operator=(const TabletModeTuckEducation&) = delete;
+  ~TabletModeTuckEducation() override;
+
+  // aura::WindowObserver:
+  void OnWindowTransformed(aura::Window* window,
+                           ui::PropertyChangeReason reason) override;
+
+ private:
+  // Activates the tuck education nudge and bounce animations for
+  // `floated_window`.
+  void ActivateTuckEducation();
+
+  // Dismisses the nudge if it is still active, and cleans up all related
+  // pointers.
+  void DismissNudge();
+
+  // The widget that contains the `RoundedLabel`.
+  views::UniqueWidgetPtr nudge_widget_;
+
+  // The floated window that `nudge_widget_` is a child of. Guaranteed to be
+  // alive for the lifetime of `this` since the owner of `this` observes
+  // `OnWindowDestroying()`.
+  aura::Window* window_ = nullptr;
+
+  base::ScopedObservation<aura::Window, aura::WindowObserver>
+      window_observation_{this};
+
+  // Chrome's compiler toolchain enforces that any `WeakPtrFactory`
+  // fields are declared last, to avoid destruction ordering issues.
+  base::WeakPtrFactory<TabletModeTuckEducation> weak_factory_{this};
+};
+
+}  // namespace ash
+
+#endif  // ASH_WM_FLOAT_TABLET_MODE_TUCK_EDUCATION_H_
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 0ada7dd..8d16af2 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2077,8 +2077,8 @@
       "mac/scoped_mach_port.h",
       "mac/scoped_mach_vm.cc",
       "mac/scoped_mach_vm.h",
+      "mac/scoped_nsautorelease_pool.cc",
       "mac/scoped_nsautorelease_pool.h",
-      "mac/scoped_nsautorelease_pool.mm",
       "mac/scoped_nsobject.h",
       "mac/scoped_objc_class_swizzler.h",
       "mac/scoped_objc_class_swizzler.mm",
diff --git a/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java b/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java
index 419b463a..4e525cfd 100644
--- a/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java
+++ b/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java
@@ -6,8 +6,6 @@
 
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-import android.os.Process;
-
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.build.BuildConfig;
@@ -37,11 +35,7 @@
         private final AtomicInteger mCount = new AtomicInteger(1);
         @Override
         public Thread newThread(Runnable r) {
-            Thread t = new Thread(() -> {
-                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-                r.run();
-            }, "CrAsyncTask #" + mCount.getAndIncrement());
-            return t;
+            return new Thread(r, "CrAsyncTask #" + mCount.getAndIncrement());
         }
     };
 
diff --git a/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherTestBase.java b/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherTestBase.java
index 99ab5b6..336aa0f 100644
--- a/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherTestBase.java
+++ b/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherTestBase.java
@@ -376,6 +376,50 @@
         Assert.fail("Expected AssertionError");
     }
 
+    protected void doTestExpectIntRecords_success(@TestScenario int scenario) {
+        // Arrange
+        maybeLoadNativeFirst(scenario);
+        mWatcher = HistogramWatcher.newBuilder()
+                           .expectIntRecords(EXACT_LINEAR_HISTOGRAM_1, 5, 7, 6, 5)
+                           .build();
+
+        // Act
+        RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 6, 10);
+        RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 5, 10);
+        RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 7, 10);
+        RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 5, 10);
+        maybeLoadNativeAfterRecord(scenario);
+
+        // Assert
+        mWatcher.assertExpected();
+    }
+
+    protected void doTestExpectIntRecords_failure(@TestScenario int scenario) {
+        // Arrange
+        maybeLoadNativeFirst(scenario);
+        mWatcher = HistogramWatcher.newBuilder()
+                           .expectIntRecords(EXACT_LINEAR_HISTOGRAM_1, 5, 7, 6, 5)
+                           .build();
+
+        // Act
+        RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 6, 10);
+        RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 5, 10);
+        RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 7, 10);
+        // Miss recording EXACT_LINEAR_HISTOGRAM_1 with value 5.
+        maybeLoadNativeAfterRecord(scenario);
+
+        // Assert
+        try {
+            mWatcher.assertExpected();
+        } catch (AssertionError e) {
+            assertContains(EXACT_LINEAR_HISTOGRAM_1, e.getMessage());
+            assertContains("4 record(s) expected: [5 (2 times), 6, 7]", e.getMessage());
+            assertContains("3 record(s) seen: [5, 6, 7]", e.getMessage());
+            return;
+        }
+        Assert.fail("Expected AssertionError");
+    }
+
     protected void doTestIgnoreOtherHistograms_success(@TestScenario int scenario) {
         // Arrange
         maybeLoadNativeFirst(scenario);
diff --git a/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherWithNativeTest.java b/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherWithNativeTest.java
index 6b321fb..6849e84 100644
--- a/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherWithNativeTest.java
+++ b/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherWithNativeTest.java
@@ -114,6 +114,18 @@
 
     @Test
     @MediumTest
+    public void testExpectIntRecords_success() {
+        doTestExpectIntRecords_success(TestScenario.WITH_NATIVE);
+    }
+
+    @Test
+    @MediumTest
+    public void testExpectIntRecords_failure() {
+        doTestExpectIntRecords_failure(TestScenario.WITH_NATIVE);
+    }
+
+    @Test
+    @MediumTest
     public void testMissingFirstRecord_failure() {
         doTestMissingFirstRecord_failure(TestScenario.WITH_NATIVE);
     }
diff --git a/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherWithoutNativeTest.java b/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherWithoutNativeTest.java
index 08fa06a0..7fdb927c 100644
--- a/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherWithoutNativeTest.java
+++ b/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherWithoutNativeTest.java
@@ -112,6 +112,18 @@
 
     @Test
     @MediumTest
+    public void testExpectIntRecords_success() {
+        doTestExpectIntRecords_success(TestScenario.WITHOUT_NATIVE);
+    }
+
+    @Test
+    @MediumTest
+    public void testExpectIntRecords_failure() {
+        doTestExpectIntRecords_failure(TestScenario.WITHOUT_NATIVE);
+    }
+
+    @Test
+    @MediumTest
     public void testIgnoreOtherHistograms_success() {
         doTestIgnoreOtherHistograms_success(TestScenario.WITHOUT_NATIVE);
     }
diff --git a/base/check.cc b/base/check.cc
index c9f41c5..5bdb0d7 100644
--- a/base/check.cc
+++ b/base/check.cc
@@ -16,114 +16,104 @@
 #include "base/debug/crash_logging.h"
 #endif  // !BUILDFLAG(IS_NACL)
 
+#include <atomic>
+
 namespace logging {
 
 namespace {
 
-void DumpWithoutCrashing(LogMessage* log_message,
-                         const base::Location& location) {
-  // Copy the LogMessage message to stack memory to make sure it can be
-  // recovered in crash dumps. This is easier to recover in minidumps than crash
-  // keys during local debugging.
-  DEBUG_ALIAS_FOR_CSTR(log_message_str, log_message->BuildCrashString().c_str(),
-                       1024);
+// TODO(crbug.com/851128): Once landed this needs to be under
+// BUILDFLAG(DCHECK_IS_CONFIGURABLE) and NotReachedLogMessage cleaned up and
+// instead just be a LogMessage using FATAL.
+void DumpOnceWithoutCrashing(LogMessage* log_message) {
+  // Best-effort gate to prevent multiple DCHECKs from being dumped. This will
+  // race if multiple threads DCHECK at the same time, but we'll eventually stop
+  // reporting and at most report once per thread.
+  static std::atomic<bool> has_dumped = false;
+  if (!has_dumped.load(std::memory_order_relaxed)) {
+    // Copy the LogMessage message to stack memory to make sure it can be
+    // recovered in crash dumps.
+    // TODO(pbos): Do we need this for NACL builds or is the crash key set in
+    // the caller sufficient?
+    DEBUG_ALIAS_FOR_CSTR(log_message_str,
+                         log_message->BuildCrashString().c_str(), 1024);
 
-  // Report from the same location at most once every 30 days (unless the
-  // process has died). This attempts to prevent us from flooding ourselves with
-  // repeat reports for the same bug.
-  base::debug::DumpWithoutCrashing(location, base::Days(30));
+    // Note that dumping may fail if the crash handler hasn't been set yet. In
+    // that case we want to try again on the next failing DCHECK.
+    if (base::debug::DumpWithoutCrashingUnthrottled()) {
+      has_dumped.store(true, std::memory_order_relaxed);
+    }
+  }
 }
 
-void NotReachedDumpWithoutCrashing(LogMessage* log_message,
-                                   const base::Location& location) {
+void NotReachedDumpOnceWithoutCrashing(LogMessage* log_message) {
 #if !BUILDFLAG(IS_NACL)
   SCOPED_CRASH_KEY_STRING1024("Logging", "NOTREACHED_MESSAGE",
                               log_message->BuildCrashString());
 #endif  // !BUILDFLAG(IS_NACL)
-  DumpWithoutCrashing(log_message, location);
-}
-
-void DCheckDumpWithoutCrashing(LogMessage* log_message,
-                               const base::Location& location) {
-#if !BUILDFLAG(IS_NACL)
-  SCOPED_CRASH_KEY_STRING1024("Logging", "DCHECK_MESSAGE",
-                              log_message->BuildCrashString());
-#endif  // !BUILDFLAG(IS_NACL)
-  DumpWithoutCrashing(log_message, location);
+  DumpOnceWithoutCrashing(log_message);
 }
 
 class NotReachedLogMessage : public LogMessage {
  public:
-  NotReachedLogMessage(const base::Location& location, LogSeverity severity)
-      : LogMessage(location.file_name(), location.line_number(), severity),
-        location_(location) {}
+  using LogMessage::LogMessage;
   ~NotReachedLogMessage() override {
     if (severity() != logging::LOGGING_FATAL) {
-      NotReachedDumpWithoutCrashing(this, location_);
+      NotReachedDumpOnceWithoutCrashing(this);
     }
   }
-
- private:
-  const base::Location location_;
 };
 
+#if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
+
+void DCheckDumpOnceWithoutCrashing(LogMessage* log_message) {
+#if !BUILDFLAG(IS_NACL)
+  SCOPED_CRASH_KEY_STRING1024("Logging", "DCHECK_MESSAGE",
+                              log_message->BuildCrashString());
+#endif  // !BUILDFLAG(IS_NACL)
+  DumpOnceWithoutCrashing(log_message);
+}
+
 class DCheckLogMessage : public LogMessage {
  public:
   using LogMessage::LogMessage;
-  DCheckLogMessage(const base::Location& location, LogSeverity severity)
-      : LogMessage(location.file_name(), location.line_number(), severity),
-        location_(location) {}
   ~DCheckLogMessage() override {
     if (severity() != logging::LOGGING_FATAL) {
-      DCheckDumpWithoutCrashing(this, location_);
+      DCheckDumpOnceWithoutCrashing(this);
     }
   }
-
- private:
-  const base::Location location_;
 };
 
 #if BUILDFLAG(IS_WIN)
 class DCheckWin32ErrorLogMessage : public Win32ErrorLogMessage {
  public:
-  DCheckWin32ErrorLogMessage(const base::Location& location,
-                             LogSeverity severity,
-                             SystemErrorCode err)
-      : Win32ErrorLogMessage(location.file_name(),
-                             location.line_number(),
-                             severity,
-                             err),
-        location_(location) {}
+  using Win32ErrorLogMessage::Win32ErrorLogMessage;
   ~DCheckWin32ErrorLogMessage() override {
     if (severity() != logging::LOGGING_FATAL) {
-      DCheckDumpWithoutCrashing(this, location_);
+      DCheckDumpOnceWithoutCrashing(this);
     }
   }
-
- private:
-  const base::Location location_;
 };
 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
 class DCheckErrnoLogMessage : public ErrnoLogMessage {
  public:
-  DCheckErrnoLogMessage(const base::Location& location,
-                        LogSeverity severity,
-                        SystemErrorCode err)
-      : ErrnoLogMessage(location.file_name(),
-                        location.line_number(),
-                        severity,
-                        err),
-        location_(location) {}
+  using ErrnoLogMessage::ErrnoLogMessage;
   ~DCheckErrnoLogMessage() override {
     if (severity() != logging::LOGGING_FATAL) {
-      DCheckDumpWithoutCrashing(this, location_);
+      DCheckDumpOnceWithoutCrashing(this);
     }
   }
-
- private:
-  const base::Location location_;
 };
 #endif  // BUILDFLAG(IS_WIN)
+#else
+static_assert(logging::LOGGING_DCHECK == logging::LOGGING_FATAL);
+using DCheckLogMessage = LogMessage;
+#if BUILDFLAG(IS_WIN)
+using DCheckWin32ErrorLogMessage = Win32ErrorLogMessage;
+#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
+using DCheckErrnoLogMessage = ErrnoLogMessage;
+#endif  // BUILDFLAG(IS_WIN)
+#endif  // BUILDFLAG(DCHECK_IS_CONFIGURABLE)
 
 }  // namespace
 
@@ -135,9 +125,10 @@
   return CheckError(log_message);
 }
 
-CheckError CheckError::DCheck(const char* condition,
-                              const base::Location& location) {
-  auto* const log_message = new DCheckLogMessage(location, LOGGING_DCHECK);
+CheckError CheckError::DCheck(const char* file,
+                              int line,
+                              const char* condition) {
+  auto* const log_message = new DCheckLogMessage(file, line, LOGGING_DCHECK);
   log_message->stream() << "Check failed: " << condition << ". ";
   return CheckError(log_message);
 }
@@ -161,15 +152,16 @@
   return PCheck(file, line, "");
 }
 
-CheckError CheckError::DPCheck(const char* condition,
-                               const base::Location& location) {
+CheckError CheckError::DPCheck(const char* file,
+                               int line,
+                               const char* condition) {
   SystemErrorCode err_code = logging::GetLastSystemErrorCode();
 #if BUILDFLAG(IS_WIN)
   auto* const log_message =
-      new DCheckWin32ErrorLogMessage(location, LOGGING_DCHECK, err_code);
+      new DCheckWin32ErrorLogMessage(file, line, LOGGING_DCHECK, err_code);
 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
   auto* const log_message =
-      new DCheckErrnoLogMessage(location, LOGGING_DCHECK, err_code);
+      new DCheckErrnoLogMessage(file, line, LOGGING_DCHECK, err_code);
 #endif
   log_message->stream() << "Check failed: " << condition << ". ";
   return CheckError(log_message);
@@ -205,10 +197,10 @@
   }
 }
 
-NotReachedError NotReachedError::NotReached(const base::Location& location) {
+NotReachedError NotReachedError::NotReached(const char* file, int line) {
   // Outside DCHECK builds NOTREACHED() should not be FATAL. For now.
   const LogSeverity severity = DCHECK_IS_ON() ? LOGGING_DCHECK : LOGGING_ERROR;
-  auto* const log_message = new NotReachedLogMessage(location, severity);
+  auto* const log_message = new NotReachedLogMessage(file, line, severity);
 
   // TODO(pbos): Consider a better message for NotReached(), this is here to
   // match existing behavior + test expectations.
@@ -219,7 +211,7 @@
 void NotReachedError::TriggerNotReached() {
   // This triggers a NOTREACHED() error as the returned NotReachedError goes out
   // of scope.
-  NotReached();
+  NotReached("", -1);
 }
 
 NotReachedError::~NotReachedError() = default;
@@ -237,9 +229,8 @@
 NotReachedNoreturnError::~NotReachedNoreturnError() {
   delete log_message_;
 
-  // Make sure we die if we haven't.
-  // TODO(crbug.com/1409729): Replace this with NOTREACHED_NORETURN() once
-  // LOG(FATAL) is [[noreturn]].
+  // Make sure we die if we haven't. LOG(FATAL) is not yet [[noreturn]] as of
+  // writing this.
   base::ImmediateCrash();
 }
 
diff --git a/base/check.h b/base/check.h
index e8083320..71a27cb 100644
--- a/base/check.h
+++ b/base/check.h
@@ -12,7 +12,6 @@
 #include "base/dcheck_is_on.h"
 #include "base/debug/debugging_buildflags.h"
 #include "base/immediate_crash.h"
-#include "base/location.h"
 
 // This header defines the CHECK, DCHECK, and DPCHECK macros.
 //
@@ -68,16 +67,12 @@
 
   static CheckError Check(const char* file, int line, const char* condition);
 
-  static CheckError DCheck(
-      const char* condition,
-      const base::Location& location = base::Location::Current());
+  static CheckError DCheck(const char* file, int line, const char* condition);
 
   static CheckError PCheck(const char* file, int line, const char* condition);
   static CheckError PCheck(const char* file, int line);
 
-  static CheckError DPCheck(
-      const char* condition,
-      const base::Location& location = base::Location::Current());
+  static CheckError DPCheck(const char* file, int line, const char* condition);
 
   static CheckError NotImplemented(const char* file,
                                    int line,
@@ -104,8 +99,7 @@
 
 class BASE_EXPORT NotReachedError : public CheckError {
  public:
-  static NotReachedError NotReached(
-      const base::Location& location = base::Location::Current());
+  static NotReachedError NotReached(const char* file, int line);
 
   // Used to trigger a NOTREACHED() without providing file or line while also
   // discarding log-stream arguments. See base/notreached.h.
@@ -188,10 +182,14 @@
 
 #if DCHECK_IS_ON()
 
-#define DCHECK(condition) \
-  CHECK_FUNCTION_IMPL(::logging::CheckError::DCheck(#condition), condition)
-#define DPCHECK(condition) \
-  CHECK_FUNCTION_IMPL(::logging::CheckError::DPCheck(#condition), condition)
+#define DCHECK(condition)                                            \
+  CHECK_FUNCTION_IMPL(                                               \
+      ::logging::CheckError::DCheck(__FILE__, __LINE__, #condition), \
+      condition)
+#define DPCHECK(condition)                                            \
+  CHECK_FUNCTION_IMPL(                                                \
+      ::logging::CheckError::DPCheck(__FILE__, __LINE__, #condition), \
+      condition)
 
 #else
 
diff --git a/base/mac/scoped_nsautorelease_pool.cc b/base/mac/scoped_nsautorelease_pool.cc
new file mode 100644
index 0000000..b9b28b79
--- /dev/null
+++ b/base/mac/scoped_nsautorelease_pool.cc
@@ -0,0 +1,34 @@
+// Copyright 2010 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/mac/scoped_nsautorelease_pool.h"
+
+// Note that this uses the direct runtime interface to the autorelease pool.
+// https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support
+// This is so this can work when compiled for ARC.
+
+extern "C" {
+void* objc_autoreleasePoolPush(void);
+void objc_autoreleasePoolPop(void* pool);
+}
+
+namespace base::mac {
+
+ScopedNSAutoreleasePool::ScopedNSAutoreleasePool()
+    : autorelease_pool_(objc_autoreleasePoolPush()) {}
+
+ScopedNSAutoreleasePool::~ScopedNSAutoreleasePool() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  objc_autoreleasePoolPop(autorelease_pool_);
+}
+
+// Cycle the internal pool, allowing everything there to get cleaned up and
+// start anew.
+void ScopedNSAutoreleasePool::Recycle() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  objc_autoreleasePoolPop(autorelease_pool_);
+  autorelease_pool_ = objc_autoreleasePoolPush();
+}
+
+}  // namespace base::mac
diff --git a/base/mac/scoped_nsautorelease_pool.h b/base/mac/scoped_nsautorelease_pool.h
index 1e9608be..1a824cc 100644
--- a/base/mac/scoped_nsautorelease_pool.h
+++ b/base/mac/scoped_nsautorelease_pool.h
@@ -6,21 +6,23 @@
 #define BASE_MAC_SCOPED_NSAUTORELEASE_POOL_H_
 
 #include "base/base_export.h"
-
-#if defined(__OBJC__)
-@class NSAutoreleasePool;
-#else  // __OBJC__
-class NSAutoreleasePool;
-#endif  // __OBJC__
+#include "base/threading/thread_checker.h"
 
 namespace base::mac {
 
-// ScopedNSAutoreleasePool allocates an NSAutoreleasePool when instantiated and
-// sends it a -drain message when destroyed.  This allows an autorelease pool to
-// be maintained in ordinary C++ code without bringing in any direct Objective-C
-// dependency.
+// ScopedNSAutoreleasePool creates an autorelease pool when instantiated and
+// pops it when destroyed.  This allows an autorelease pool to be maintained in
+// ordinary C++ code without bringing in any direct Objective-C dependency.
 //
-// Use only in C++ code; use @autoreleasepool in Obj-C(++) code.
+// Before using, please be aware that the semantics of autorelease pools do not
+// match the semantics of a C++ class. In particular, recycling or destructing a
+// pool lower on the stack destroys all pools higher on the stack, which does
+// not mesh well with the existence of C++ objects for each pool.
+//
+// TODO(https://crbug.com/1424190): Enforce stack-only use via the
+// STACK_ALLOCATED annotation.
+//
+// Use this class only in C++ code; use @autoreleasepool in Obj-C(++) code.
 
 class BASE_EXPORT ScopedNSAutoreleasePool {
  public:
@@ -28,16 +30,21 @@
 
   ScopedNSAutoreleasePool(const ScopedNSAutoreleasePool&) = delete;
   ScopedNSAutoreleasePool& operator=(const ScopedNSAutoreleasePool&) = delete;
+  ScopedNSAutoreleasePool(ScopedNSAutoreleasePool&&) = delete;
+  ScopedNSAutoreleasePool& operator=(ScopedNSAutoreleasePool&&) = delete;
 
   ~ScopedNSAutoreleasePool();
 
-  // Clear out the pool in case its position on the stack causes it to be
-  // alive for long periods of time (such as the entire length of the app).
-  // Only use then when you're certain the items currently in the pool are
-  // no longer needed.
+  // Clear out the pool in case its position on the stack causes it to be alive
+  // for long periods of time (such as the entire length of the app). Only use
+  // then when you're certain the items currently in the pool are no longer
+  // needed.
   void Recycle();
+
  private:
-  NSAutoreleasePool* autorelease_pool_;
+  void* autorelease_pool_ GUARDED_BY_CONTEXT(thread_checker_);
+
+  THREAD_CHECKER(thread_checker_);
 };
 
 }  // namespace base::mac
diff --git a/base/mac/scoped_nsautorelease_pool.mm b/base/mac/scoped_nsautorelease_pool.mm
deleted file mode 100644
index e7b8465..0000000
--- a/base/mac/scoped_nsautorelease_pool.mm
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2010 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/mac/scoped_nsautorelease_pool.h"
-
-#import <Foundation/Foundation.h>
-
-#include "base/check.h"
-
-namespace base::mac {
-
-ScopedNSAutoreleasePool::ScopedNSAutoreleasePool()
-    : autorelease_pool_([[NSAutoreleasePool alloc] init]) {
-  DCHECK(autorelease_pool_);
-}
-
-ScopedNSAutoreleasePool::~ScopedNSAutoreleasePool() {
-  [autorelease_pool_ drain];
-}
-
-// Cycle the internal pool, allowing everything there to get cleaned up and
-// start anew.
-void ScopedNSAutoreleasePool::Recycle() {
-  [autorelease_pool_ drain];
-  autorelease_pool_ = [[NSAutoreleasePool alloc] init];
-  DCHECK(autorelease_pool_);
-}
-
-}  // namespace base::mac
diff --git a/base/message_loop/message_pump_glib.cc b/base/message_loop/message_pump_glib.cc
index 29c83ea..ca2dd6b 100644
--- a/base/message_loop/message_pump_glib.cc
+++ b/base/message_loop/message_pump_glib.cc
@@ -191,7 +191,7 @@
 
   // Create our wakeup pipe, which is used to flag when work was scheduled.
   int fds[2];
-  [[maybe_unused]] int ret = pipe(fds);
+  [[maybe_unused]] int ret = pipe2(fds, O_CLOEXEC);
   DCHECK_EQ(ret, 0);
 
   wakeup_pipe_read_ = fds[0];
diff --git a/base/notreached.h b/base/notreached.h
index 96d4f9b..b5b634a 100644
--- a/base/notreached.h
+++ b/base/notreached.h
@@ -24,8 +24,9 @@
 // which is [[noreturn]] and always FATAL. Once that's done, rename
 // NOTREACHED_NORETURN() back to NOTREACHED() and remove the non-FATAL version.
 #if CHECK_WILL_STREAM() || BUILDFLAG(ENABLE_LOG_ERROR_NOT_REACHED)
-#define NOTREACHED() \
-  CHECK_FUNCTION_IMPL(::logging::NotReachedError::NotReached(), false)
+#define NOTREACHED()   \
+  CHECK_FUNCTION_IMPL( \
+      ::logging::NotReachedError::NotReached(__FILE__, __LINE__), false)
 #else
 #define NOTREACHED()                                       \
   (true) ? ::logging::NotReachedError::TriggerNotReached() \
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
index f0c34da..b667ffa9 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
@@ -24,6 +24,7 @@
 
 import androidx.core.content.ContextCompat;
 import androidx.test.InstrumentationRegistry;
+import androidx.test.internal.runner.ClassPathScanner;
 import androidx.test.internal.runner.RunnerArgs;
 import androidx.test.internal.runner.TestExecutor;
 import androidx.test.internal.runner.TestRequestBuilder;
@@ -344,14 +345,7 @@
         DexFileTestRequestBuilder(Instrumentation instr, Bundle bundle, List<DexFile> dexFiles) {
             super(instr, bundle);
             mDexFiles = dexFiles;
-            try {
-                Field excludedPackagesField =
-                        TestRequestBuilder.class.getDeclaredField("DEFAULT_EXCLUDED_PACKAGES");
-                excludedPackagesField.setAccessible(true);
-                mExcludedPrefixes.addAll(Arrays.asList((String[]) excludedPackagesField.get(null)));
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
+            mExcludedPrefixes.addAll(ClassPathScanner.getDefaultExcludedPackages());
         }
 
         @Override
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/HistogramWatcher.java b/base/test/android/javatests/src/org/chromium/base/test/util/HistogramWatcher.java
index 578ad2b..5783a0bb 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/HistogramWatcher.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/HistogramWatcher.java
@@ -129,6 +129,17 @@
         }
 
         /**
+         * Add expectations that {@code histogram} will be recorded with each of the int {@code
+         * values} provided.
+         */
+        public Builder expectIntRecords(String histogram, int... values) {
+            for (int value : values) {
+                expectIntRecord(histogram, value);
+            }
+            return this;
+        }
+
+        /**
          * Add an expectation that {@code histogram} will be recorded a number of {@code times} with
          * an int {@code value}.
          */
diff --git a/base/threading/platform_thread_fuchsia.cc b/base/threading/platform_thread_fuchsia.cc
index 1d8c04d..fd3ab6dd 100644
--- a/base/threading/platform_thread_fuchsia.cc
+++ b/base/threading/platform_thread_fuchsia.cc
@@ -51,6 +51,10 @@
       fidl::SyncClient<fuchsia_media::ProfileProvider>>
       profile_provider(ConnectProfileProvider());
 
+  if (!profile_provider->is_valid()) {
+    return;
+  }
+
   zx::thread dup_thread;
   zx_status_t status =
       zx::thread::self()->duplicate(ZX_RIGHT_SAME_RIGHTS, &dup_thread);
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h
index 29eb73c4..3c8faea 100644
--- a/base/trace_event/builtin_categories.h
+++ b/base/trace_event/builtin_categories.h
@@ -354,6 +354,7 @@
   X("renderer,webkit")                                                        \
   X("renderer_host,navigation")                                               \
   X("renderer_host," TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"))        \
+  X("scheduler,devtools.timeline,loading")                                    \
   X("shutdown,viz")                                                           \
   X("startup,benchmark,rail")                                                 \
   X("startup,rail")                                                           \
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index 4311c56..c828109 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -188,7 +188,7 @@
 
  private:
   std::vector<protozero::ContiguousMemoryRange> ranges_;
-  perfetto::protos::pbzero::DebugAnnotation* annotation_proto_;
+  raw_ptr<perfetto::protos::pbzero::DebugAnnotation> annotation_proto_;
 };
 
 void AddConvertableToTraceFormat(
diff --git a/base/values.cc b/base/values.cc
index 909d93a9..cd41f9c 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -1281,64 +1281,6 @@
   return const_cast<Value*>(std::as_const(*this).FindListPath(path));
 }
 
-Value* Value::SetPath(StringPiece path, Value&& value) {
-  return GetDict().SetByDottedPath(path, std::move(value));
-}
-
-Value* Value::SetStringPath(StringPiece path, StringPiece value) {
-  return GetDict().SetByDottedPath(path, value);
-}
-
-Value* Value::SetStringPath(StringPiece path, std::string&& value) {
-  return GetDict().SetByDottedPath(path, std::move(value));
-}
-
-Value* Value::SetStringPath(StringPiece path, const char* value) {
-  return GetDict().SetByDottedPath(path, value);
-}
-
-Value* Value::SetStringPath(StringPiece path, StringPiece16 value) {
-  return GetDict().SetByDottedPath(path, value);
-}
-
-Value* Value::SetPath(std::initializer_list<StringPiece> path, Value&& value) {
-  DCHECK_GE(path.size(), 2u) << "Use SetKey() for a path of length 1.";
-  return SetPath(make_span(path.begin(), path.size()), std::move(value));
-}
-
-Value* Value::SetPath(span<const StringPiece> path, Value&& value) {
-  DCHECK(path.begin() != path.end());  // Can't be empty path.
-
-  // Walk/construct intermediate dictionaries. The last element requires
-  // special handling so skip it in this loop.
-  Value* cur = this;
-  auto cur_path = path.begin();
-  for (; (cur_path + 1) < path.end(); ++cur_path) {
-    if (!cur->is_dict()) {
-      return nullptr;
-    }
-
-    // Use lower_bound to avoid doing the search twice for missing keys.
-    const StringPiece path_component = *cur_path;
-    auto found = cur->GetDict().storage_.lower_bound(path_component);
-    if (found == cur->GetDict().storage_.end() ||
-        found->first != path_component) {
-      // No key found, insert one.
-      auto inserted = cur->GetDict().storage_.try_emplace(
-          found, path_component, std::make_unique<Value>(Type::DICT));
-      cur = inserted->second.get();
-    } else {
-      cur = found->second.get();
-    }
-  }
-
-  // "cur" will now contain the last dictionary to insert or replace into.
-  if (!cur->is_dict()) {
-    return nullptr;
-  }
-  return cur->SetKey(*cur_path, std::move(value));
-}
-
 Value::dict_iterator_proxy Value::DictItems() {
   return dict_iterator_proxy(&GetDict().storage_);
 }
diff --git a/base/values.h b/base/values.h
index 0ff64447..059bd42 100644
--- a/base/values.h
+++ b/base/values.h
@@ -855,37 +855,6 @@
   Value* FindListPath(StringPiece path);
   const Value* FindListPath(StringPiece path) const;
 
-  // Sets the given path, expanding and creating dictionary keys as necessary.
-  //
-  // If the current value is not a dictionary, the function returns nullptr. If
-  // path components do not exist, they will be created. If any but the last
-  // components matches a value that is not a dictionary, the function will fail
-  // (it will not overwrite the value) and return nullptr. The last path
-  // component will be unconditionally overwritten if it exists, and created if
-  // it doesn't.
-  //
-  // Note: If there is only one component in the path, use `SetKey()` instead.
-  // Note: Using `Set<Type>Path()` might be more convenient and efficient.
-  //
-  // DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
-  Value* SetPath(StringPiece path, Value&& value);
-
-  // These setters are more convenient and efficient than the corresponding
-  // SetPath(...) call.
-  //
-  // DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
-  Value* SetStringPath(StringPiece path, StringPiece value);
-  // DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
-  Value* SetStringPath(StringPiece path, const char* value);
-  // DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
-  Value* SetStringPath(StringPiece path, std::string&& value);
-  // DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
-  Value* SetStringPath(StringPiece path, StringPiece16 value);
-
-  // DEPRECATED: Use `Value::Dict::SetByDottedPath()`.
-  Value* SetPath(std::initializer_list<StringPiece> path, Value&& value);
-  Value* SetPath(span<const StringPiece> path, Value&& value);
-
   using dict_iterator_proxy = detail::dict_iterator_proxy;
   using const_dict_iterator_proxy = detail::const_dict_iterator_proxy;
 
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index f2ae442d..6ea7229 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -1126,7 +1126,7 @@
   EXPECT_EQ(123, found->GetInt());
 }
 
-TEST(ValuesTest, SetPath) {
+TEST(ValuesTest, SetByDottedPath) {
   Value::Dict root;
 
   Value* inserted = root.SetByDottedPath("one.two", Value(123));
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py
index 35dca28..d179b91 100755
--- a/build/android/gyp/proguard.py
+++ b/build/android/gyp/proguard.py
@@ -608,15 +608,8 @@
   dynamic_config_data = _CreateDynamicConfig(options)
 
   logging.debug('Looking for embedded configs')
-  libraries = []
-  for p in options.classpath:
-    # TODO(bjoyce): Remove filter once old android support libraries are gone.
-    # Fix for having Library class extend program class dependency problem.
-    if 'com_android_support' in p or 'android_support_test' in p:
-      continue
-    # If a jar is part of input no need to include it as library jar.
-    if p not in libraries and p not in options.input_paths:
-      libraries.append(p)
+  # If a jar is part of input no need to include it as library jar.
+  libraries = [p for p in options.classpath if p not in options.input_paths]
 
   embedded_configs = {}
   for jar_path in options.input_paths + libraries:
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 45e3a1c..283e026 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-12.20230328.1.1
+12.20230329.0.1
diff --git a/build/fuchsia/test/flash_device_unittests.py b/build/fuchsia/test/flash_device_unittests.py
index d09a95db..3499b7b 100755
--- a/build/fuchsia/test/flash_device_unittests.py
+++ b/build/fuchsia/test/flash_device_unittests.py
@@ -16,6 +16,7 @@
 _TEST_VERSION = 'test.version'
 
 
+@unittest.skipIf(os.name == 'nt', 'Fuchsia tests not supported on Windows')
 # pylint: disable=too-many-public-methods,protected-access
 class FlashDeviceTest(unittest.TestCase):
     """Unittests for flash_device.py."""
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni
index 58ebf32..d872285 100644
--- a/buildtools/deps_revisions.gni
+++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@
 declare_args() {
   # Used to cause full rebuilds on libc++ rolls. This should be kept in sync
   # with the libcxx_revision vars in //DEPS.
-  libcxx_revision = "26ace673c4b9c7a352fa9db182256bb341b6c44f"
+  libcxx_revision = "e0dca93272081cf3b2d04fcf83f5b5804c3730de"
 }
diff --git a/cc/slim/layer_tree_impl.cc b/cc/slim/layer_tree_impl.cc
index 1ca2a620..b880314 100644
--- a/cc/slim/layer_tree_impl.cc
+++ b/cc/slim/layer_tree_impl.cc
@@ -433,11 +433,13 @@
        /*opacity=*/1.0f);
   render_pass->filters = root_->GetFilters();
 
-  if (background_color_.fA &&
-      !frame_data.occlusion_in_target.Contains(device_viewport_rect_)) {
+  bool background_opaque = background_color_.isOpaque();
+  bool viewport_fully_occluded =
+      frame_data.occlusion_in_target.Contains(device_viewport_rect_);
+  render_pass->has_transparent_background =
+      !background_opaque && !viewport_fully_occluded;
+  if (background_color_.fA && !viewport_fully_occluded) {
     // Quads does not cover entire viewport. Fill in the gutters.
-    bool background_opaque = background_color_.isOpaque();
-    render_pass->has_transparent_background = !background_opaque;
     Region unoccluded_region(device_viewport_rect_);
     for (size_t i = 0; i < frame_data.occlusion_in_target.GetRegionComplexity();
          ++i) {
diff --git a/cc/slim/simple_scheduler.h b/cc/slim/simple_scheduler.h
index dfc47b70..212c4914 100644
--- a/cc/slim/simple_scheduler.h
+++ b/cc/slim/simple_scheduler.h
@@ -6,6 +6,7 @@
 #define CC_SLIM_SIMPLE_SCHEDULER_H_
 
 #include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
 #include "cc/slim/scheduler.h"
 
 namespace cc::slim {
@@ -22,7 +23,7 @@
       const viz::BeginFrameArgs& begin_frame_args) override;
 
  private:
-  SchedulerClient* client_ = nullptr;
+  raw_ptr<SchedulerClient> client_ = nullptr;
 };
 
 }  // namespace cc::slim
diff --git a/cc/slim/slim_layer_tree_compositor_frame_unittest.cc b/cc/slim/slim_layer_tree_compositor_frame_unittest.cc
index 8ce6c0362..1fa45768 100644
--- a/cc/slim/slim_layer_tree_compositor_frame_unittest.cc
+++ b/cc/slim/slim_layer_tree_compositor_frame_unittest.cc
@@ -1616,6 +1616,20 @@
   }
 }
 
+TEST_F(SlimLayerTreeCompositorFrameTest, OccludedNonOpaqueBackgroundColor) {
+  // Check that even if background color is not opaque, the frame should still
+  // be opaque if the viewport is entirely occluded by opaque layers.
+  auto root_layer = CreateSolidColorLayer(viewport_.size(), SkColors::kGray);
+  layer_tree_->set_background_color(SkColors::kTransparent);
+  layer_tree_->SetRoot(root_layer);
+  viz::CompositorFrame frame = ProduceFrame();
+  ASSERT_EQ(frame.render_pass_list.size(), 1u);
+  auto& pass = frame.render_pass_list.back();
+  ASSERT_THAT(pass->quad_list,
+              ElementsAre(viz::IsSolidColorQuad(SkColors::kGray)));
+  EXPECT_FALSE(pass->has_transparent_background);
+}
+
 TEST_F(SlimLayerTreeCompositorFrameTest, Guttering) {
   auto root_layer = CreateSolidColorLayer(gfx::Size(50, 50), SkColors::kRed);
   root_layer->SetPosition(gfx::PointF(25.0f, 25.0f));
diff --git a/chrome/VERSION b/chrome/VERSION
index 5979ad2..bda3b92 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=114
 MINOR=0
-BUILD=5682
+BUILD=5683
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 93b94db..75993c7 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -903,7 +903,6 @@
   "java/src/org/chromium/chrome/browser/payments/AddressEditor.java",
   "java/src/org/chromium/chrome/browser/payments/AutofillAddress.java",
   "java/src/org/chromium/chrome/browser/payments/AutofillContact.java",
-  "java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java",
   "java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestFactory.java",
   "java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java",
   "java/src/org/chromium/chrome/browser/payments/ChromePaymentResponseHelper.java",
@@ -1143,6 +1142,7 @@
   "java/src/org/chromium/chrome/browser/ui/MediaCaptureOverlayController.java",
   "java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java",
   "java/src/org/chromium/chrome/browser/ui/ViewDrawBlocker.java",
+  "java/src/org/chromium/chrome/browser/ui/fold_transitions/FoldTransitionController.java",
   "java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java",
   "java/src/org/chromium/chrome/browser/undo_tab_close_snackbar/UndoBarController.java",
   "java/src/org/chromium/chrome/browser/upgrade/PackageReplacedBroadcastReceiver.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index 37bc1b73..f41d5388 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -293,6 +293,7 @@
   "junit/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediatorUnitTest.java",
   "junit/src/org/chromium/chrome/browser/ui/AppLaunchDrawBlockerUnitTest.java",
   "junit/src/org/chromium/chrome/browser/ui/IncognitoRestoreAppLaunchDrawBlockerUnitTest.java",
+  "junit/src/org/chromium/chrome/browser/ui/fold_transitions/FoldTransitionControllerUnitTest.java",
   "junit/src/org/chromium/chrome/browser/usage_stats/EventTrackerTest.java",
   "junit/src/org/chromium/chrome/browser/usage_stats/PageViewObserverTest.java",
   "junit/src/org/chromium/chrome/browser/webapps/MockWebappDataStorageClockRule.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 0e6c726..d27b0b0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -605,9 +605,9 @@
 
                     boolean gridTabSwitcherEnabled = TabUiFeatureUtilities.isGridTabSwitcherEnabled(
                             ChromeTabbedActivity.this);
-                    boolean overviewVisible =
-                            mLayoutManager.isLayoutVisible(LayoutType.TAB_SWITCHER)
-                            || mLayoutManager.isLayoutVisible(LayoutType.START_SURFACE);
+                    boolean overviewVisible = isLayoutManagerCreated()
+                            && (mLayoutManager.isLayoutVisible(LayoutType.TAB_SWITCHER)
+                                    || mLayoutManager.isLayoutVisible(LayoutType.START_SURFACE));
                     boolean hasNextTab = !(getTabModelSelector().getTotalTabCount() == 0
                             || (!getTabModelSelector().isIncognitoSelected()
                                     && getTabModelSelector().getModel(false).getCount() == 0));
@@ -980,6 +980,9 @@
             PostTask.postTask(TaskTraits.UI_DEFAULT,
                     mCallbackController.makeCancelable(
                             this::maybeCreateIncognitoTabSnapshotController));
+            if (BackPressManager.isEnabled()) {
+                PostTask.postTask(TaskTraits.UI_DEFAULT, this::initializeBackPressHandlers);
+            }
             PostTask.postTask(TaskTraits.UI_DEFAULT,
                     mCallbackController.makeCancelable(
                             this::onAccessibilityTabSwitcherModeChanged));
@@ -1008,7 +1011,6 @@
 
             ChromeAccessibilityUtil.get().addObserver(mLayoutManager);
             if (isTablet()) ChromeAccessibilityUtil.get().addObserver(mCompositorViewHolder);
-            if (BackPressManager.isEnabled()) initializeBackPressHandlers();
 
             mInactivityTracker.setLastVisibleTimeMsAndRecord(System.currentTimeMillis());
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index b43431f..11fa3e6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -403,6 +403,7 @@
     private StylusWritingCoordinator mStylusWritingCoordinator;
     private boolean mBlockingDrawForAppRestart;
     private Runnable mShowContentRunnable;
+    private boolean mIsRecreatingForTabletModeChange;
 
     protected ChromeActivity() {
         mIntentHandler = new IntentHandler(this, createIntentHandlerDelegate());
@@ -978,6 +979,8 @@
         if (mDeferredStartupQueued || shouldPostDeferredStartupForReparentedTab()) {
             postDeferredStartupIfNeeded();
         }
+
+        mRootUiCoordinator.restoreUiState(getSavedInstanceState());
     }
 
     /**
@@ -1490,6 +1493,7 @@
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
+        mRootUiCoordinator.onSaveInstanceState(outState, mIsRecreatingForTabletModeChange);
     }
 
     /**
@@ -2803,6 +2807,7 @@
             mTabReparentingControllerSupplier.get().prepareTabsForReparenting();
             mIsTabReparentingPrepared = true;
             if (!isFinishing()) {
+                mIsRecreatingForTabletModeChange = true;
                 recreate();
                 mHandler.removeCallbacks(mShowContentRunnable);
                 return true;
@@ -2837,6 +2842,11 @@
         return mBackPressManager;
     }
 
+    @VisibleForTesting
+    public boolean recreatingForTabletModeChangeForTesting() {
+        return mIsRecreatingForTabletModeChange;
+    }
+
     /** Returns whether the print action was successfully started. */
     private boolean doPrintShare(Activity activity, Supplier<Tab> currentTabSupplier) {
         PrintingController printingController = PrintingControllerImpl.getInstance();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
index 3a22616..1c0da83 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
@@ -1254,6 +1254,11 @@
     }
 
     @Override
+    public boolean isLayoutStartingToShow(int layoutType) {
+        return isLayoutVisible(layoutType) && getActiveLayout().isStartingToShow();
+    }
+
+    @Override
     public void addObserver(LayoutStateObserver listener) {
         mLayoutObservers.addObserver(listener);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS
index 2ae5248..08e0826 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS
@@ -1,4 +1,5 @@
 eirage@chromium.org
+kgrosu@google.com
 mvanouwerkerk@chromium.org
 peconn@chromium.org
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java
deleted file mode 100644
index 4462b247..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright 2016 The Chromium Authors
-// 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.payments;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.JsonWriter;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
-import androidx.appcompat.content.res.AppCompatResources;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.autofill.PersonalDataManager;
-import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
-import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
-import org.chromium.chrome.browser.autofill.PersonalDataManager.NormalizedAddressRequestDelegate;
-import org.chromium.components.autofill.EditableOption;
-import org.chromium.components.payments.ErrorStrings;
-import org.chromium.components.payments.PayerData;
-import org.chromium.components.payments.PaymentApp.InstrumentDetailsCallback;
-import org.chromium.content_public.browser.WebContents;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * The locally stored credit card payment instrument.
- */
-// TODO(crbug.com/1209835): Move this class into autofill now that it no longer interacts with
-// Payments code.
-public class AutofillPaymentInstrument
-        extends EditableOption implements NormalizedAddressRequestDelegate {
-    // Bit field values are identical to CreditCardCompletionStatus fields in
-    // autofill_card_validation.h. Please modify autofill_card_validation.h after changing these.
-    @IntDef({CompletionStatus.COMPLETE, CompletionStatus.CREDIT_CARD_EXPIRED,
-            CompletionStatus.CREDIT_CARD_NO_CARDHOLDER, CompletionStatus.CREDIT_CARD_NO_NUMBER,
-            CompletionStatus.CREDIT_CARD_NO_BILLING_ADDRESS,
-            CompletionStatus.CREDIT_CARD_TYPE_MISMATCH})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface CompletionStatus {
-        int COMPLETE = 0;
-        int CREDIT_CARD_EXPIRED = 1 << 0;
-        int CREDIT_CARD_NO_CARDHOLDER = 1 << 1;
-        int CREDIT_CARD_NO_NUMBER = 1 << 2;
-        int CREDIT_CARD_NO_BILLING_ADDRESS = 1 << 3;
-        int CREDIT_CARD_TYPE_MISMATCH = 1 << 4;
-    }
-
-    private final WebContents mWebContents;
-    private CreditCard mCard;
-    private String mSecurityCode;
-    @Nullable
-    private AutofillProfile mBillingAddress;
-    @Nullable
-    private String mMethodName;
-    @Nullable
-    private InstrumentDetailsCallback mCallback;
-    private boolean mIsWaitingForBillingNormalization;
-    private boolean mHasValidNumberAndName;
-
-    /**
-     * Builds a payment instrument for the given credit card.
-     *
-     * @param webContents                    The web contents where PaymentRequest was invoked.
-     * @param card                           The autofill card that can be used for payment.
-     * @param billingAddress                 The billing address for the card.
-     * @param methodName                     The payment method name, e.g., "basic-card", "visa",
-     *                                       amex", or null.
-     */
-    public AutofillPaymentInstrument(WebContents webContents, CreditCard card,
-            @Nullable AutofillProfile billingAddress, @Nullable String methodName) {
-        super(card.getGUID(), card.getNetworkAndLastFourDigits(), card.getName(), null);
-        mWebContents = webContents;
-        mCard = card;
-        mBillingAddress = billingAddress;
-        mIsEditable = true;
-        mMethodName = methodName;
-
-        Context context = ContextUtils.getApplicationContext();
-        if (context == null) return;
-
-        if (card.getIssuerIconDrawableId() != 0) {
-            updateDrawableIcon(
-                    AppCompatResources.getDrawable(context, card.getIssuerIconDrawableId()));
-        }
-
-        checkAndUpdateCardCompleteness(context);
-    }
-
-    @Override
-    public void onAddressNormalized(AutofillProfile profile) {
-        if (!mIsWaitingForBillingNormalization) return;
-        mIsWaitingForBillingNormalization = false;
-
-        // If the normalization finished first, use the normalized address.
-        if (profile != null) mBillingAddress = profile;
-
-        sendInstrumentDetails();
-    }
-
-    @Override
-    public void onCouldNotNormalize(AutofillProfile profile) {
-        onAddressNormalized(null);
-    }
-
-    /**
-     * Stringify the card details and send the resulting string and the method name to the
-     * registered callback.
-     */
-    private void sendInstrumentDetails() {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter json = new JsonWriter(stringWriter);
-        try {
-            json.beginObject();
-
-            json.name("cardholderName").value(mCard.getName());
-            json.name("cardNumber").value(mCard.getNumber());
-            json.name("expiryMonth").value(mCard.getMonth());
-            json.name("expiryYear").value(mCard.getYear());
-            json.name("cardSecurityCode").value(mSecurityCode);
-
-            json.name("billingAddress").beginObject();
-
-            json.name("country").value(ensureNotNull(mBillingAddress.getCountryCode()));
-            json.name("region").value(ensureNotNull(mBillingAddress.getRegion()));
-            json.name("city").value(ensureNotNull(mBillingAddress.getLocality()));
-            json.name("dependentLocality")
-                    .value(ensureNotNull(mBillingAddress.getDependentLocality()));
-
-            json.name("addressLine").beginArray();
-            String multipleLines = ensureNotNull(mBillingAddress.getStreetAddress());
-            if (!TextUtils.isEmpty(multipleLines)) {
-                String[] lines = multipleLines.split("\n");
-                for (int i = 0; i < lines.length; i++) {
-                    json.value(lines[i]);
-                }
-            }
-            json.endArray();
-
-            json.name("postalCode").value(ensureNotNull(mBillingAddress.getPostalCode()));
-            json.name("sortingCode").value(ensureNotNull(mBillingAddress.getSortingCode()));
-            json.name("languageCode").value(ensureNotNull(mBillingAddress.getLanguageCode()));
-            json.name("organization").value(ensureNotNull(mBillingAddress.getCompanyName()));
-            json.name("recipient").value(ensureNotNull(mBillingAddress.getFullName()));
-            json.name("phone").value(ensureNotNull(mBillingAddress.getPhoneNumber()));
-
-            json.endObject();
-
-            json.endObject();
-        } catch (IOException e) {
-            onFullCardError();
-            return;
-        } finally {
-            mSecurityCode = "";
-        }
-
-        mCallback.onInstrumentDetailsReady(mMethodName, stringWriter.toString(), new PayerData());
-        mCallback = null;
-    }
-
-    private static String ensureNotNull(@Nullable String value) {
-        return value == null ? "" : value;
-    }
-
-    private void onFullCardError() {
-        // There's no need to disambiguate between user cancelling the CVC unmask and other types of
-        // failures, because a failure to unmask an Autofill card will show the Payment Request UI
-        // again and prompt the user to attempt to complete a transaction using a different card.
-        mCallback.onInstrumentDetailsError(ErrorStrings.USER_CANCELLED);
-        mCallback = null;
-    }
-
-    /**
-     * @return Whether the card is complete and ready to be sent to the merchant as-is. If true,
-     * this card has a valid card number, a non-empty name on card, and a complete billing address.
-     */
-    @Override
-    public boolean isComplete() {
-        return mIsComplete;
-    }
-
-    /**
-     * Updates the instrument and marks it "complete." Called after the user has edited this
-     * instrument.
-     *
-     * @param card           The new credit card to use. The GUID should not change.
-     * @param methodName     The payment method name to use for this instrument, e.g., "visa",
-     *                       "basic-card".
-     * @param billingAddress The billing address for the card. The GUID should match the billing
-     *                       address ID of the new card to use.
-     */
-    public void completeInstrument(
-            CreditCard card, String methodName, AutofillProfile billingAddress) {
-        assert card != null;
-        assert methodName != null;
-        assert billingAddress != null;
-        assert card.getBillingAddressId() != null;
-        assert card.getBillingAddressId().equals(billingAddress.getGUID());
-        assert card.getIssuerIconDrawableId() != 0;
-        assert AutofillAddress.checkAddressCompletionStatus(
-                billingAddress, AutofillAddress.CompletenessCheckType.IGNORE_PHONE)
-                == AutofillAddress.CompletionStatus.COMPLETE;
-
-        mCard = card;
-        mMethodName = methodName;
-        mBillingAddress = billingAddress;
-
-        Context context = ContextUtils.getApplicationContext();
-        if (context == null) return;
-
-        updateIdentifierLabelsAndIcon(card.getGUID(), card.getNetworkAndLastFourDigits(),
-                card.getName(), null,
-                AppCompatResources.getDrawable(context, card.getIssuerIconDrawableId()));
-        checkAndUpdateCardCompleteness(context);
-        assert mIsComplete;
-        assert mHasValidNumberAndName;
-    }
-
-    /**
-     * Checks whether card is complete, i.e., can be sent to the merchant as-is without editing
-     * first. And updates edit message, edit title and complete status.
-     *
-     * For both local and server cards, verifies that the billing address is present. For local
-     * cards also verifies that the card number is valid and the name on card is not empty.
-     *
-     * Does not check that the billing address has all of the required fields. This is done
-     * elsewhere to filter out such billing addresses entirely.
-     *
-     * Does not check the expiration date for mIsComplete. If the card is expired, the user has the
-     * opportunity update the expiration date when providing their CVC in the card unmask dialog.
-     *
-     * Does not check that the card type is accepted by the merchant. This is done elsewhere to
-     * filter out such cards from view entirely.
-     *
-     * Completeness weights for all fields are identiacal to their equivalent in
-     * GetCompletenessScore from autofill_card_validation.cc, Please modify the weights in both
-     * files if needed.
-     */
-    private void checkAndUpdateCardCompleteness(Context context) {
-        int editMessageResId = 0; // Zero is the invalid resource Id.
-        int editTitleResId = R.string.payments_edit_card;
-        int invalidFieldsCount = 0;
-        mCompletenessScore = 0;
-        int missingFields = getMissingFields();
-
-        // Even though expiration date does not affect mIsComplete, cards with valid expiration date
-        // still score higher than expired cards. This is used to list expired cards after
-        // non-expired cards after sorting instruments.
-        if ((missingFields & CompletionStatus.CREDIT_CARD_EXPIRED) == 0) mCompletenessScore += 6;
-
-        if ((missingFields & CompletionStatus.CREDIT_CARD_NO_BILLING_ADDRESS) == 0) {
-            // Add 10 for complete address.
-            mCompletenessScore += 10;
-        } else {
-            editMessageResId = R.string.payments_billing_address_required;
-            editTitleResId = R.string.payments_add_billing_address;
-            invalidFieldsCount++;
-        }
-
-        mHasValidNumberAndName = true;
-        if ((missingFields & CompletionStatus.CREDIT_CARD_NO_CARDHOLDER) == 0) {
-            // Add 8 for complete card holder's name.
-            mCompletenessScore += 8;
-        } else {
-            mHasValidNumberAndName = false;
-            editMessageResId = R.string.payments_name_on_card_required;
-            editTitleResId = R.string.payments_add_name_on_card;
-            invalidFieldsCount++;
-        }
-        if ((missingFields & CompletionStatus.CREDIT_CARD_NO_NUMBER) == 0) {
-            // Add 13 for valid card number.
-            mCompletenessScore += 13;
-        } else {
-            mHasValidNumberAndName = false;
-            editMessageResId = R.string.payments_card_number_invalid_validation_message;
-            editTitleResId = R.string.payments_add_valid_card_number;
-            invalidFieldsCount++;
-        }
-
-        if (invalidFieldsCount > 1) {
-            editMessageResId = R.string.payments_more_information_required;
-            editTitleResId = R.string.payments_add_more_information;
-        }
-
-        mEditMessage = editMessageResId == 0 ? null : context.getString(editMessageResId);
-        mEditTitle = context.getString(editTitleResId);
-        mIsComplete = mEditMessage == null;
-    }
-
-    /** @return The credit card represented by this payment instrument. */
-    public CreditCard getCard() {
-        return mCard;
-    }
-
-    /** @return The billing address associated with this payment instrument. */
-    @Nullable
-    public AutofillProfile getBillingProfile() {
-        return mBillingAddress;
-    }
-
-    @Override
-    public String getPreviewString(String labelSeparator, int maxLength) {
-        StringBuilder previewString = new StringBuilder(getLabel());
-        if (maxLength < 0) return previewString.toString();
-
-        int networkNameEndIndex = previewString.indexOf(" ");
-        if (networkNameEndIndex > 0) {
-            // Only display card network name.
-            previewString.delete(networkNameEndIndex, previewString.length());
-        }
-        if (previewString.length() < maxLength) return previewString.toString();
-        return previewString.substring(0, maxLength / 2);
-    }
-
-    /** @return a bit vector of the card's missing fields. */
-    public int getMissingFields() {
-        int missingFields = CompletionStatus.COMPLETE;
-        if (mBillingAddress == null) {
-            missingFields |= CompletionStatus.CREDIT_CARD_NO_BILLING_ADDRESS;
-        }
-        if (!mCard.hasValidCreditCardExpirationDate()) {
-            missingFields |= CompletionStatus.CREDIT_CARD_EXPIRED;
-        }
-
-        if (mCard.getIsLocal()) {
-            if (TextUtils.isEmpty(mCard.getName())) {
-                missingFields |= CompletionStatus.CREDIT_CARD_NO_CARDHOLDER;
-            }
-
-            if (PersonalDataManager.getInstance().getBasicCardIssuerNetwork(
-                        mCard.getNumber().toString(), true)
-                    == null) {
-                missingFields |= CompletionStatus.CREDIT_CARD_NO_NUMBER;
-            }
-        }
-
-        return missingFields;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
index fc2d8e4..e474e79 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
@@ -354,13 +354,6 @@
         mPaymentUiService.enableAndUpdatePaymentRequestUIWithPaymentInfo();
     }
 
-    // Implements BrowserPaymentRequest:
-    @Override
-    public void onInstrumentDetailsLoading() {
-        assert mPaymentUiService.getSelectedPaymentApp() == null;
-        mPaymentUiService.showProcessingMessage();
-    }
-
     // Implements PaymentUiService.Delegate:
     @Override
     public boolean invokePaymentApp(EditableOption selectedShippingAddress,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
index ba79181..f3fd326 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
@@ -1010,15 +1010,6 @@
     }
 
     /**
-     * Shows the processing message. Precondition: isPaymentRequestUiAlive() needs to be true for
-     * the method to take effect.
-     */
-    public void showProcessingMessage() {
-        if (mPaymentRequestUI == null) return;
-        mPaymentRequestUI.showProcessingMessage();
-    }
-
-    /**
      *  Shows the processing message after payment details have been loaded in the case the
      *  app selector UI has been skipped. Precondition: isPaymentRequestUiAlive() needs to be
      *  true for the method to take effect.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index a023668..f15b4d37 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -1281,6 +1281,16 @@
     }
 
     /**
+     * Returns the UrlBar text excluding the autocomplete text.
+     */
+    public String getUrlBarTextWithoutAutocomplete() {
+        assert mLocationBar
+                instanceof LocationBarCoordinator
+            : "LocationBar should be an instance of LocationBarCoordinator.";
+        return ((LocationBarCoordinator) mLocationBar).getUrlBarTextWithoutAutocomplete();
+    }
+
+    /**
      * Enable the bottom controls.
      */
     public void enableBottomControls() {
@@ -1786,10 +1796,23 @@
      * @param reason The given reason.
      */
     public void setUrlBarFocus(boolean focused, @OmniboxFocusReason int reason) {
+        setUrlBarFocusAndText(focused, reason, null);
+    }
+
+    /**
+     * Same as {@code #setUrlBarFocus(boolean, @OmniboxFocusReason int)}, with the additional option
+     * to set URL bar text.
+     *
+     * @param focused Whether URL bar should be focused.
+     * @param reason The given reason.
+     * @param text The URL bar text. {@code null} if no text is to be set.
+     */
+    public void setUrlBarFocusAndText(
+            boolean focused, @OmniboxFocusReason int reason, String text) {
         if (!mInitializedWithNative) return;
         if (mLocationBar.getOmniboxStub() == null) return;
         boolean wasFocused = mLocationBar.getOmniboxStub().isUrlBarFocused();
-        mLocationBar.getOmniboxStub().setUrlBarFocus(focused, null, reason);
+        mLocationBar.getOmniboxStub().setUrlBarFocus(focused, text, reason);
         if (wasFocused && focused) {
             mLocationBar.selectAll();
         }
@@ -1808,8 +1831,8 @@
     }
 
     /**
-     * See {@link #setUrlBarFocus}, but if native is not loaded it will queue the request instead
-     * of dropping it.
+     * See {@link #setUrlBarFocus}, but if native is not loaded it will queue the request instead of
+     * dropping it.
      */
     public void setUrlBarFocusOnceNativeInitialized(
             boolean focused, @OmniboxFocusReason int reason) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
index 0f6dc7e..41f7013 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -10,6 +10,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.Handler;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
@@ -133,6 +134,7 @@
 import org.chromium.chrome.browser.ui.appmenu.AppMenuCoordinatorFactory;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuDelegate;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuObserver;
+import org.chromium.chrome.browser.ui.fold_transitions.FoldTransitionController;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.ui.system.StatusBarColorController;
 import org.chromium.chrome.browser.ui.system.StatusBarColorController.StatusBarColorProvider;
@@ -1565,6 +1567,30 @@
         return mIncognitoReauthControllerOneshotSupplier;
     }
 
+    /**
+     * Saves relevant information that will be used to restore the UI state after the activity is
+     * recreated. This is expected to be invoked in {@code Activity#onSaveInstanceState(Bundle)}.
+     *
+     * @param outState The {@link Bundle} that is used to save state information.
+     * @param isRecreatingForTabletModeChange Whether the activity is recreated due to a fold
+     *         configuration change. {@code true} if the fold configuration changed, {@code false}
+     *         otherwise.
+     */
+    public void onSaveInstanceState(Bundle outState, boolean isRecreatingForTabletModeChange) {
+        FoldTransitionController.saveUiState(outState, getToolbarManager(), mActivityTabProvider,
+                isRecreatingForTabletModeChange);
+    }
+
+    /**
+     * Restores the relevant UI state when the activity is recreated on a device fold transition.
+     *
+     * @param savedInstanceState The {@link Bundle} that is used to restore the UI state.
+     */
+    public void restoreUiState(Bundle savedInstanceState) {
+        FoldTransitionController.restoreUiState(
+                savedInstanceState, getToolbarManager(), mLayoutManager, new Handler());
+    }
+
     // Testing methods
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/fold_transitions/FoldTransitionController.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/fold_transitions/FoldTransitionController.java
new file mode 100644
index 0000000..b3160ac
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/fold_transitions/FoldTransitionController.java
@@ -0,0 +1,133 @@
+// Copyright 2023 The Chromium Authors
+// 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.ui.fold_transitions;
+
+import android.os.Bundle;
+import android.os.Handler;
+
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.layouts.LayoutStateProvider;
+import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver;
+import org.chromium.chrome.browser.layouts.LayoutType;
+import org.chromium.chrome.browser.omnibox.OmniboxFocusReason;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.toolbar.ToolbarManager;
+import org.chromium.components.embedder_support.util.UrlUtilities;
+
+/**
+ * A utility class to handle saving and restoring the UI state across fold transitions.
+ */
+public class FoldTransitionController {
+    @VisibleForTesting
+    public static final String DID_CHANGE_TABLET_MODE = "did_change_tablet_mode";
+    static final String URL_BAR_FOCUS_STATE = "url_bar_focus_state";
+    static final String URL_BAR_EDIT_TEXT = "url_bar_edit_text";
+
+    /**
+     * Saves the relevant UI when the activity is recreated on a device fold transition. Expected to
+     * be invoked during {@code Activity#onSaveInstanceState()}.
+     *
+     * @param savedInstanceState The {@link Bundle} where the UI state will be saved.
+     * @param toolbarManager The {@link ToolbarManager} for the current activity.
+     * @param activityTabProvider The activity tab {@link Supplier} for the current activity.
+     * @param didChangeTabletMode Whether the activity is recreated due to a fold configuration
+     *         change. {@code true} if the fold configuration changed, {@code false} otherwise.
+     */
+    public static void saveUiState(Bundle savedInstanceState, ToolbarManager toolbarManager,
+            Supplier<Tab> activityTabProvider, boolean didChangeTabletMode) {
+        savedInstanceState.putBoolean(
+                FoldTransitionController.DID_CHANGE_TABLET_MODE, didChangeTabletMode);
+        saveOmniboxState(savedInstanceState, toolbarManager, activityTabProvider);
+    }
+
+    /**
+     * Restores the relevant UI state when the activity is recreated on a device fold transition.
+     *
+     * @param savedInstanceState The {@link Bundle} that is used to restore the UI state.
+     * @param toolbarManager The {@link ToolbarManager} for the current activity.
+     * @param layoutManager The {@link LayoutStateProvider} for the current activity.
+     * @param layoutStateHandler The {@link Handler} to post UI state restoration.
+     */
+    public static void restoreUiState(Bundle savedInstanceState, ToolbarManager toolbarManager,
+            LayoutStateProvider layoutManager, Handler layoutStateHandler) {
+        restoreOmniboxState(savedInstanceState, toolbarManager, layoutManager, layoutStateHandler);
+    }
+
+    private static void saveOmniboxState(Bundle savedInstanceState, ToolbarManager toolbarManager,
+            Supplier<Tab> activityTabProvider) {
+        if (savedInstanceState == null || toolbarManager == null) {
+            return;
+        }
+        if (activityTabProvider == null || activityTabProvider.get() == null
+                || UrlUtilities.isNTPUrl(activityTabProvider.get().getUrl())) {
+            // TODO (crbug.com/1425248): Support NTP fakebox focus state retention.
+            return;
+        }
+        if (toolbarManager.isUrlBarFocused()) {
+            savedInstanceState.putBoolean(FoldTransitionController.URL_BAR_FOCUS_STATE, true);
+            savedInstanceState.putString(FoldTransitionController.URL_BAR_EDIT_TEXT,
+                    toolbarManager.getUrlBarTextWithoutAutocomplete());
+        }
+    }
+
+    private static void restoreOmniboxState(Bundle savedInstanceState,
+            ToolbarManager toolbarManager, LayoutStateProvider layoutManager,
+            Handler layoutStateHandler) {
+        if (savedInstanceState == null || toolbarManager == null || layoutManager == null) {
+            return;
+        }
+        // Restore the omnibox state only on a device fold transition.
+        if (!savedInstanceState.getBoolean(DID_CHANGE_TABLET_MODE, false)) {
+            return;
+        }
+
+        if (savedInstanceState.getBoolean(URL_BAR_FOCUS_STATE, false)) {
+            String urlBarText = savedInstanceState.getString(URL_BAR_EDIT_TEXT, "");
+
+            /* TODO (crbug/1395495): Call {@code ToolbarManager#setUrlBarFocusAndText(boolean,
+             * @OmniboxFocusReason int, String)} directly if the invocation of {@code
+             * StaticLayout#requestFocus(Tab)} in {@code StaticLayout#doneShowing()} is removed. We
+             * set focus currently after the {@link StaticLayout} is done showing to persist the
+             * last focus on the omnibox. If the layout is visible and done showing, it is safe to
+             * call {@code ToolbarManager#setUrlBarFocusAndText(boolean, @OmniboxFocusReason int,
+             * String)} directly to persist the omnibox focus. */
+            if (layoutManager.isLayoutVisible(LayoutType.BROWSING)
+                    && !layoutManager.isLayoutStartingToShow(LayoutType.BROWSING)) {
+                setUrlBarFocusAndText(toolbarManager, urlBarText);
+            } else {
+                layoutManager.addObserver(createLayoutStateObserver(
+                        urlBarText, toolbarManager, layoutManager, layoutStateHandler));
+            }
+        }
+    }
+
+    @VisibleForTesting
+    static LayoutStateObserver createLayoutStateObserver(String urlBarText,
+            ToolbarManager toolbarManager, LayoutStateProvider layoutManager,
+            Handler layoutStateHandler) {
+        return new LayoutStateObserver() {
+            @Override
+            public void onFinishedShowing(int layoutType) {
+                assert layoutManager.isLayoutVisible(LayoutType.BROWSING)
+                    : "LayoutType is "
+                        + layoutManager.getActiveLayoutType()
+                        + ", expected BROWSING type on activity start.";
+                LayoutStateObserver.super.onFinishedShowing(layoutType);
+                layoutStateHandler.post(() -> {
+                    setUrlBarFocusAndText(toolbarManager, urlBarText);
+                    layoutManager.removeObserver(this);
+                    layoutStateHandler.removeCallbacksAndMessages(null);
+                });
+            }
+        };
+    }
+
+    private static void setUrlBarFocusAndText(ToolbarManager toolbarManager, String urlBarText) {
+        toolbarManager.setUrlBarFocusAndText(
+                true, OmniboxFocusReason.FOLD_TRANSITION_RESTORATION, urlBarText);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/fold_transitions/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/ui/fold_transitions/OWNERS
new file mode 100644
index 0000000..cecb7e8c
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/fold_transitions/OWNERS
@@ -0,0 +1,2 @@
+aishwaryarj@google.com
+skavuluru@google.com
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/tab_activity_glue/TabletPhoneLayoutChangeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/tab_activity_glue/TabletPhoneLayoutChangeTest.java
index 2a36272..9bc76fa 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/tab_activity_glue/TabletPhoneLayoutChangeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/tab_activity_glue/TabletPhoneLayoutChangeTest.java
@@ -7,6 +7,7 @@
 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
 
 import android.content.res.Configuration;
+import android.os.Bundle;
 
 import androidx.test.filters.MediumTest;
 
@@ -18,10 +19,12 @@
 
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DoNotBatch;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.lifecycle.RecreateObserver;
+import org.chromium.chrome.browser.ui.fold_transitions.FoldTransitionController;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -34,6 +37,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@DoNotBatch(reason = "This class tests activity restart behavior and thus cannot be batched.")
 public class TabletPhoneLayoutChangeTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@@ -61,6 +65,15 @@
             Assert.assertTrue(
                     "Activity should be ready for tablet mode change.", cta.didChangeTabletMode());
             cta.getDisplayAndroidObserverForTesting().onCurrentModeChanged(null);
+            Assert.assertTrue("ChromeActivity#mIsRecreatingForTabletModeChange should be true.",
+                    cta.recreatingForTabletModeChangeForTesting());
+
+            // Simulate invocation of #onSaveInstanceState to verify that the saved instance state
+            // contains DID_CHANGE_TABLET_MODE.
+            Bundle outState = new Bundle();
+            cta.onSaveInstanceState(outState);
+            Assert.assertTrue("DID_CHANGE_TABLET_MODE in the saved instance state should be true.",
+                    outState.getBoolean(FoldTransitionController.DID_CHANGE_TABLET_MODE));
         });
 
         helper.waitForFirst("Activity should be restart");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityAppMenuTest.java
index 6d434ba..007f3d88 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityAppMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityAppMenuTest.java
@@ -31,6 +31,8 @@
 import org.junit.rules.RuleChain;
 import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.IntentUtils;
 import org.chromium.base.library_loader.LibraryLoader;
@@ -41,6 +43,7 @@
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.app.metrics.LaunchCauseMetrics;
 import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
@@ -51,6 +54,8 @@
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
+import org.chromium.chrome.browser.translate.TranslateBridge;
+import org.chromium.chrome.browser.translate.TranslateBridgeJni;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuCoordinator;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuItemProperties;
@@ -74,6 +79,11 @@
     private static final String TEST_PAGE = "/chrome/test/data/android/google.html";
     private static final String TEST_MENU_TITLE = "testMenuTitle";
 
+    @Rule
+    public JniMocker jniMocker = new JniMocker();
+    @Mock
+    private TranslateBridge.Natives mTranslateBridgeJniMock;
+
     public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
 
     private final TestRule mModuleOverridesRule =
@@ -96,6 +106,13 @@
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        // Mock translate bridge so "Translate..." menu item doesn't unexpectedly show up.
+        jniMocker.mock(org.chromium.chrome.browser.translate.TranslateBridgeJni.TEST_HOOKS,
+                mTranslateBridgeJniMock);
+        jniMocker.mock(TranslateBridgeJni.TEST_HOOKS, mTranslateBridgeJniMock);
+
         TestThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(true));
         mTestPage = mCustomTabActivityTestRule.getTestServer().getURL(TEST_PAGE);
         LibraryLoader.getInstance().ensureInitialized();
@@ -148,7 +165,7 @@
         final int expectedMenuSize = numMenuEntries + NUM_CHROME_MENU_ITEMS_WITH_DIVIDER;
 
         Assert.assertNotNull("App menu is not initialized: ", menuItemsModelList);
-        assertEquals(expectedMenuSize, menuItemsModelList.size());
+        CustomTabsTestUtils.assertMenuSize(menuItemsModelList, expectedMenuSize);
         Assert.assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
                 mCustomTabActivityTestRule.getAppMenuCoordinator(), R.id.forward_menu_id));
         Assert.assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
@@ -192,7 +209,7 @@
         final int expectedMenuSize = numMenuEntries + NUM_CHROME_MENU_ITEMS;
 
         Assert.assertNotNull("App menu is not initialized: ", menuItemsModelList);
-        assertEquals(expectedMenuSize, menuItemsModelList.size());
+        CustomTabsTestUtils.assertMenuSize(menuItemsModelList, expectedMenuSize);
 
         // Assert the divider line is not displayed.
         int dividerLine = AppMenuTestSupport.findIndexOfMenuItemById(
@@ -235,7 +252,7 @@
         final int expectedMenuSize = 2;
 
         Assert.assertNotNull("App menu is not initialized: ", menuItemsModelList);
-        assertEquals(expectedMenuSize, menuItemsModelList.size());
+        CustomTabsTestUtils.assertMenuSize(menuItemsModelList, expectedMenuSize);
         Assert.assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
                 mCustomTabActivityTestRule.getAppMenuCoordinator(), R.id.find_in_page_id));
         Assert.assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
@@ -260,7 +277,7 @@
         final int expectedMenuSize = 3;
 
         Assert.assertNotNull("App menu is not initialized: ", menuItemsModelList);
-        assertEquals(expectedMenuSize, menuItemsModelList.size());
+        CustomTabsTestUtils.assertMenuSize(menuItemsModelList, expectedMenuSize);
         Assert.assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
                 mCustomTabActivityTestRule.getAppMenuCoordinator(), R.id.find_in_page_id));
         Assert.assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
@@ -299,7 +316,7 @@
         final int expectedMenuSize = 3;
 
         Assert.assertNotNull("App menu is not initialized: ", menuItemsModelList);
-        assertEquals(expectedMenuSize, menuItemsModelList.size());
+        CustomTabsTestUtils.assertMenuSize(menuItemsModelList, expectedMenuSize);
         // Checks the first row (icons).
         Assert.assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
                 mCustomTabActivityTestRule.getAppMenuCoordinator(), R.id.forward_menu_id));
@@ -359,7 +376,7 @@
                 mCustomTabActivityTestRule.getAppMenuCoordinator());
         final int expectedMenuSize = MAX_MENU_CUSTOM_ITEMS + NUM_CHROME_MENU_ITEMS_WITH_DIVIDER;
         Assert.assertNotNull("App menu is not initialized: ", menuItemsModelList);
-        assertEquals(expectedMenuSize, menuItemsModelList.size());
+        CustomTabsTestUtils.assertMenuSize(menuItemsModelList, expectedMenuSize);
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java
index fed9658..1dc0f45 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java
@@ -47,6 +47,8 @@
 import org.junit.Test;
 import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.CallbackController;
@@ -56,6 +58,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
+import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.customtabs.CustomTabsIntentTestUtils.OnFinishedForTest;
@@ -70,6 +73,8 @@
 import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.translate.TranslateBridge;
+import org.chromium.chrome.browser.translate.TranslateBridgeJni;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuItemProperties;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuTestSupport;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -108,8 +113,20 @@
     @Rule
     public EmbeddedTestServerRule mEmbeddedTestServerRule = new EmbeddedTestServerRule();
 
+    @Rule
+    public JniMocker jniMocker = new JniMocker();
+    @Mock
+    private TranslateBridge.Natives mTranslateBridgeJniMock;
+
     @Before
     public void setUp() throws TimeoutException {
+        MockitoAnnotations.initMocks(this);
+
+        // Mock translate bridge so "Translate..." menu item doesn't unexpectedly show up.
+        jniMocker.mock(org.chromium.chrome.browser.translate.TranslateBridgeJni.TEST_HOOKS,
+                mTranslateBridgeJniMock);
+        jniMocker.mock(TranslateBridgeJni.TEST_HOOKS, mTranslateBridgeJniMock);
+
         FirstRunStatus.setFirstRunFlowComplete(true);
         mTestPage = mEmbeddedTestServerRule.getServer().getURL(TEST_PAGE);
         // Ensuring native is initialized before we access the CCT_INCOGNITO feature flag.
@@ -374,7 +391,7 @@
         ModelList menuItemsModelList = AppMenuTestSupport.getMenuModelList(
                 mCustomTabActivityTestRule.getAppMenuCoordinator());
         // Check the menu items have only 3 items visible including the top icon row menu.
-        assertEquals(3, menuItemsModelList.size());
+        CustomTabsTestUtils.assertMenuSize(menuItemsModelList, 3);
         assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
                 mCustomTabActivityTestRule.getAppMenuCoordinator(), R.id.icon_row_menu_id));
         assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
@@ -401,7 +418,7 @@
         ModelList menuItemsModelList = AppMenuTestSupport.getMenuModelList(
                 mCustomTabActivityTestRule.getAppMenuCoordinator());
         // Check the menu items have only 2 items visible "not" including the top icon row menu.
-        assertEquals(2, menuItemsModelList.size());
+        CustomTabsTestUtils.assertMenuSize(menuItemsModelList, 2);
         assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
                 mCustomTabActivityTestRule.getAppMenuCoordinator(), R.id.reader_mode_prefs_id));
         assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
index 74be39c..1184dca1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.customtabs;
 
+import static org.junit.Assert.assertEquals;
+
 import static org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule.LONG_TIMEOUT_MS;
 
 import android.content.ComponentName;
@@ -29,8 +31,10 @@
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ui.appmenu.AppMenuItemProperties;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
+import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
 
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
@@ -145,6 +149,27 @@
         ChromeTabUtils.waitForTabPageLoaded(connection.getSpeculationParamsForTesting().tab, url);
     }
 
+    /**
+     * Asserts that the number of items in {@code list} matches the {@code expectedSize}.
+     * @param list The list of items in the menu.
+     * @param expectedSize The number of expected menu items.
+     */
+    public static void assertMenuSize(ModelList list, int expectedSize) {
+        assertEquals("Populated menu items were:" + getMenuTitles(list), expectedSize, list.size());
+    }
+
+    /**
+     * @param list The list of items in the menu.
+     * @return A string containing the titles of all items in the {@code list}.
+     */
+    public static String getMenuTitles(ModelList list) {
+        StringBuilder items = new StringBuilder();
+        for (int i = 0; i < list.size(); i++) {
+            items.append("\n").append(list.get(i).model.get(AppMenuItemProperties.TITLE));
+        }
+        return items.toString();
+    }
+
     @NativeMethods
     interface Natives {
         boolean hasVariationId(int id);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenterTest.java
index 795e9e4d..548b5be 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenterTest.java
@@ -186,6 +186,7 @@
     @SmallTest
     @Feature({"ModalDialog"})
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
+    @DisabledTest(message = "https://crbug.com/1420186")
     public void testSuspend_ToggleOverview() throws Exception {
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> mActivity.getActivityTab().addObserver(mTestObserver));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java
index b718ddda..6297618 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java
@@ -16,7 +16,6 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -29,8 +28,8 @@
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.UiThreadTest;
-import org.chromium.base.test.metrics.HistogramTestRule;
 import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.util.HistogramWatcher;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorSupplier;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
@@ -74,9 +73,6 @@
     @Rule
     public ChromeBrowserTestRule mTestRule = new ChromeBrowserTestRule();
 
-    @Rule
-    public HistogramTestRule mHistogramTestRule = new HistogramTestRule();
-
     @Mock
     private PaymentManifestWebDataService mPaymentManifestWebDataService;
     @Mock
@@ -171,44 +167,28 @@
         Mockito.verify(delegate).onDoneCreatingPaymentApps(/*factory=*/null);
     }
 
-    /* Verify no metrics were recorded for the number of supported payment methods. */
-    private void verifyNoSupportedPaymentMethodCountMetric() {
-        verifySupportedPaymentMethodCountMetric(/*histograms=*/0, /*methods=*/-1);
-    }
-
-    /* Verify the supported payment method count. */
-    private void verifySupportedPaymentMethodCountMetric(int histograms, int methods) {
-        Assert.assertEquals(
-                String.format("Expected number of histogram recordings: %d.", histograms),
-                /*expected=*/histograms,
-                mHistogramTestRule.getHistogramTotalCount(
-                        "PaymentRequest.NumberOfSupportedMethods.AndroidApp"));
-
-        if (histograms > 0) {
-            Assert.assertEquals(String.format("Expected number of payment methods: %d.", methods),
-                    /*expected=*/histograms,
-                    mHistogramTestRule.getHistogramValueCount(
-                            "PaymentRequest.NumberOfSupportedMethods.AndroidApp",
-                            /*sample=*/methods));
-        }
-    }
-
     @SmallTest
     @Test
     @UiThreadTest
     public void testNoValidPaymentMethodNames() {
+        var histograms =
+                HistogramWatcher.newBuilder()
+                        .expectNoRecords("PaymentRequest.NumberOfSupportedMethods.AndroidApp")
+                        .build();
         verifyNoAppsFound(findApps(new String[] {"unknown-payment-method-name",
                                            "http://not.secure.payment.method.name.com", "https://"},
                 mPaymentManifestDownloader, mPaymentManifestParser, mPackageManagerDelegate));
-
-        // No apps:
-        verifyNoSupportedPaymentMethodCountMetric();
+        histograms.assertExpected("No apps, so 0 records are expected");
     }
 
     @SmallTest
     @Test
     @UiThreadTest
     public void testQueryWithoutApps() {
+        var histograms =
+                HistogramWatcher.newBuilder()
+                        .expectNoRecords("PaymentRequest.NumberOfSupportedMethods.AndroidApp")
+                        .build();
         Mockito.when(mPackageManagerDelegate.getActivitiesThatCanRespondToIntentWithMetaData(
                              ArgumentMatchers.argThat(sPayIntentArgumentMatcher)))
                 .thenReturn(new ArrayList<ResolveInfo>());
@@ -219,15 +199,16 @@
         Mockito.verify(mPackageManagerDelegate, Mockito.never())
                 .getStringArrayResourceForApplication(
                         ArgumentMatchers.any(ApplicationInfo.class), ArgumentMatchers.anyInt());
-
-        // No apps:
-        verifyNoSupportedPaymentMethodCountMetric();
+        histograms.assertExpected("No apps, so 0 records are expected");
     }
 
     @SmallTest
     @Test
     @UiThreadTest
     public void testQueryWithoutMetaData() {
+        var histograms = HistogramWatcher.newSingleRecordWatcher(
+                "PaymentRequest.NumberOfSupportedMethods.AndroidApp", /*value=*/0);
+
         List<ResolveInfo> activities = new ArrayList<>();
         ResolveInfo alicePay = new ResolveInfo();
         alicePay.activityInfo = new ActivityInfo();
@@ -248,14 +229,17 @@
                 .getStringArrayResourceForApplication(
                         ArgumentMatchers.any(ApplicationInfo.class), ArgumentMatchers.anyInt());
 
-        // The installed app declared support for no payment methods:
-        verifySupportedPaymentMethodCountMetric(/*histograms=*/1, /*methods=*/0);
+        histograms.assertExpected(
+                "The installed app should have declared support for 0 payment methods");
     }
 
     @SmallTest
     @Test
     @UiThreadTest
     public void testQueryWithoutLabel() {
+        var histograms = HistogramWatcher.newSingleRecordWatcher(
+                "PaymentRequest.NumberOfSupportedMethods.AndroidApp", /*value=*/1);
+
         List<ResolveInfo> activities = new ArrayList<>();
         ResolveInfo alicePay = new ResolveInfo();
         alicePay.activityInfo = new ActivityInfo();
@@ -279,14 +263,16 @@
                 .getStringArrayResourceForApplication(
                         ArgumentMatchers.any(ApplicationInfo.class), ArgumentMatchers.anyInt());
 
-        // The installed app supports only "basic-card" method:
-        verifySupportedPaymentMethodCountMetric(/*histograms=*/1, /*methods=*/1);
+        histograms.assertExpected("The installed app should support only \"basic-card\" method");
     }
 
     @SmallTest
     @Test
     @UiThreadTest
     public void testQueryUnsupportedPaymentMethod() {
+        var histograms = HistogramWatcher.newSingleRecordWatcher(
+                "PaymentRequest.NumberOfSupportedMethods.AndroidApp", /*value=*/1);
+
         PackageManagerDelegate packageManagerDelegate = installPaymentApps(
                 new String[] {"com.alicepay.app"}, new String[] {"unsupported-payment-method"});
 
@@ -297,8 +283,8 @@
                 .getStringArrayResourceForApplication(
                         ArgumentMatchers.any(ApplicationInfo.class), ArgumentMatchers.anyInt());
 
-        // The installed app supports only "unsupported-payment-method" method:
-        verifySupportedPaymentMethodCountMetric(/*histograms=*/1, /*methods=*/1);
+        histograms.assertExpected(
+                "The installed app should support only \"unsupported-payment-method\" method");
     }
 
     private PackageManagerDelegate installPaymentApps(String[] packageNames, String[] methodNames) {
@@ -329,6 +315,8 @@
     @Test
     @UiThreadTest
     public void testQueryDifferentPaymentMethod() {
+        var histograms = HistogramWatcher.newSingleRecordWatcher(
+                "PaymentRequest.NumberOfSupportedMethods.AndroidApp", /*value=*/1);
         PackageManagerDelegate packageManagerDelegate =
                 installPaymentApps(new String[] {"com.alicepay.app"}, new String[] {"basic-card"});
 
@@ -339,14 +327,15 @@
                 .getStringArrayResourceForApplication(
                         ArgumentMatchers.any(ApplicationInfo.class), ArgumentMatchers.anyInt());
 
-        // The installed app supports only "basic-card" method:
-        verifySupportedPaymentMethodCountMetric(/*histograms=*/1, /*methods=*/1);
+        histograms.assertExpected("The installed app should support only \"basic-card\" method");
     }
 
     @SmallTest
     @Test
     @UiThreadTest
     public void testQueryNoPaymentMethod() {
+        var histograms = HistogramWatcher.newSingleRecordWatcher(
+                "PaymentRequest.NumberOfSupportedMethods.AndroidApp", /*value=*/1);
         PackageManagerDelegate packageManagerDelegate =
                 installPaymentApps(new String[] {"com.alicepay.app"}, new String[] {"basic-card"});
 
@@ -357,14 +346,18 @@
                 .getStringArrayResourceForApplication(
                         ArgumentMatchers.any(ApplicationInfo.class), ArgumentMatchers.anyInt());
 
-        // The installed app supports only "basic-card" method:
-        verifySupportedPaymentMethodCountMetric(/*histograms=*/1, /*methods=*/1);
+        histograms.assertExpected("The installed app should support only \"basic-card\" method");
     }
 
     @SmallTest
     @Test
     @UiThreadTest
     public void testHistogramForMutlipleApps() {
+        var histograms =
+                HistogramWatcher.newBuilder()
+                        .expectIntRecordTimes("PaymentRequest.NumberOfSupportedMethods.AndroidApp",
+                                /*value=*/1, /*times=*/2)
+                        .build();
         PackageManagerDelegate packageManagerDelegate =
                 installPaymentApps(new String[] {"com.alicepay.app", "com.bobpay.app"},
                         new String[] {"https://alicepay.test", "https://bobpay.test"});
@@ -373,14 +366,16 @@
         findApps(new String[] {"https://charliepay.test"}, mPaymentManifestDownloader,
                 mPaymentManifestParser, packageManagerDelegate);
 
-        // Two apps are installed, with one method each.
-        verifySupportedPaymentMethodCountMetric(/*histograms=*/2, /*methods=*/1);
+        histograms.assertExpected(
+                "Two apps are installed with one method each, expected two records with value 1.");
     }
 
     @SmallTest
     @Test
     @UiThreadTest
     public void testHistogramForMutlipleMethods() {
+        var histograms = HistogramWatcher.newSingleRecordWatcher(
+                "PaymentRequest.NumberOfSupportedMethods.AndroidApp", /*value=*/2);
         List<ResolveInfo> activities = new ArrayList<>();
         ResolveInfo bobPay = new ResolveInfo();
         bobPay.activityInfo = new ActivityInfo();
@@ -410,8 +405,8 @@
         findApps(new String[] {"https://charliepay.test"}, mPaymentManifestDownloader,
                 mPaymentManifestParser, mPackageManagerDelegate);
 
-        // One app is installed. It has two payment methods.
-        verifySupportedPaymentMethodCountMetric(/*histograms=*/1, /*methods=*/2);
+        histograms.assertExpected(
+                "One app is installed with two payment methods, expected one record with value 2.");
     }
 
     @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
index 73414d4..5b957b2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
@@ -703,6 +703,7 @@
 
     @Test
     @SmallTest
+    @DisableIf.Device(type = {UiDisableIf.TABLET}) // The active color is only apply to the phone.
     @EnableFeatures({ChromeFeatureList.OMNIBOX_MODERNIZE_VISUAL_UPDATE})
     @CommandLineFlags.
     Add({"enable-features=" + ChromeFeatureList.OMNIBOX_MODERNIZE_VISUAL_UPDATE + "<Study",
@@ -727,6 +728,7 @@
 
     @Test
     @SmallTest
+    @DisableIf.Device(type = {UiDisableIf.TABLET}) // The active color is only apply to the phone.
     @EnableFeatures({ChromeFeatureList.OMNIBOX_MODERNIZE_VISUAL_UPDATE})
     @CommandLineFlags.
     Add({"enable-features=" + ChromeFeatureList.OMNIBOX_MODERNIZE_VISUAL_UPDATE + "<Study",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappLaunchCauseMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappLaunchCauseMetricsTest.java
index bc52649..68568c4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappLaunchCauseMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappLaunchCauseMetricsTest.java
@@ -9,9 +9,7 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -25,14 +23,13 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.UiThreadTest;
-import org.chromium.base.test.metrics.HistogramTestRule;
 import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.util.HistogramWatcher;
 import org.chromium.chrome.browser.app.metrics.LaunchCauseMetrics;
 import org.chromium.chrome.browser.app.metrics.LaunchCauseMetrics.LaunchCause;
 import org.chromium.chrome.browser.browserservices.intents.WebappInfo;
 import org.chromium.components.webapps.ShortcutSource;
 import org.chromium.components.webapps.WebApkDistributor;
-import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
@@ -48,14 +45,6 @@
 
     @Rule
     public MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
-    @Rule
-    public HistogramTestRule mHistogramTestRule = new HistogramTestRule();
-
-    @BeforeClass
-    public static void setUpClass() {
-        // Needs to load before HistogramTestRule is applied.
-        NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
-    }
 
     @Before
     public void setUp() {
@@ -72,17 +61,12 @@
         });
     }
 
-    private int histogramCountForValue(int value) {
-        return mHistogramTestRule.getHistogramValueCount(
-                LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM, value);
-    }
-
     @Test
     @SmallTest
     @UiThreadTest
     public void testHomescreenLaunch() throws Throwable {
-        int otherCount = histogramCountForValue(LaunchCause.WEBAPK_OTHER_DISTRIBUTOR);
-        int chromeCount = histogramCountForValue(LaunchCause.WEBAPK_CHROME_DISTRIBUTOR);
+        var histogram = HistogramWatcher.newSingleRecordWatcher(
+                LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM, LaunchCause.WEBAPK_CHROME_DISTRIBUTOR);
         Mockito.when(mWebappInfo.isLaunchedFromHomescreen()).thenReturn(true);
         Mockito.when(mWebappInfo.isForWebApk()).thenReturn(true);
         Mockito.when(mWebappInfo.distributor()).thenReturn(WebApkDistributor.BROWSER);
@@ -91,34 +75,33 @@
 
         metrics.onReceivedIntent();
         metrics.recordLaunchCause();
-        ++chromeCount;
-        Assert.assertEquals(
-                chromeCount, histogramCountForValue(LaunchCause.WEBAPK_CHROME_DISTRIBUTOR));
+        histogram.assertExpected();
 
         LaunchCauseMetrics.resetForTests();
 
+        histogram = HistogramWatcher.newSingleRecordWatcher(
+                LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM, LaunchCause.WEBAPK_OTHER_DISTRIBUTOR);
         Mockito.when(mWebappInfo.distributor()).thenReturn(WebApkDistributor.OTHER);
         metrics.onReceivedIntent();
         metrics.recordLaunchCause();
-        ++otherCount;
-        Assert.assertEquals(
-                chromeCount, histogramCountForValue(LaunchCause.WEBAPK_OTHER_DISTRIBUTOR));
+        histogram.assertExpected();
 
         LaunchCauseMetrics.resetForTests();
 
+        histogram = HistogramWatcher.newSingleRecordWatcher(
+                LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM, LaunchCause.WEBAPK_CHROME_DISTRIBUTOR);
         Mockito.when(mWebappInfo.isForWebApk()).thenReturn(false);
         metrics.onReceivedIntent();
         metrics.recordLaunchCause();
-        ++chromeCount;
-        Assert.assertEquals(
-                chromeCount, histogramCountForValue(LaunchCause.WEBAPK_CHROME_DISTRIBUTOR));
+        histogram.assertExpected();
     }
 
     @Test
     @SmallTest
     @UiThreadTest
     public void testViewIntentLaunch() throws Throwable {
-        int count = histogramCountForValue(LaunchCause.EXTERNAL_VIEW_INTENT);
+        var histogram = HistogramWatcher.newSingleRecordWatcher(
+                LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM, LaunchCause.EXTERNAL_VIEW_INTENT);
         Mockito.when(mWebappInfo.isLaunchedFromHomescreen()).thenReturn(false);
         Mockito.when(mWebappInfo.source()).thenReturn(ShortcutSource.EXTERNAL_INTENT);
 
@@ -126,21 +109,20 @@
 
         metrics.onReceivedIntent();
         metrics.recordLaunchCause();
-        ++count;
-        Assert.assertEquals(count, histogramCountForValue(LaunchCause.EXTERNAL_VIEW_INTENT));
+        histogram.assertExpected();
     }
 
     @Test
     @SmallTest
     @UiThreadTest
     public void testNullWebAppInfo() throws Throwable {
-        int count = histogramCountForValue(LaunchCause.OTHER);
+        var histogram = HistogramWatcher.newSingleRecordWatcher(
+                LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM, LaunchCause.OTHER);
 
         WebappLaunchCauseMetrics metrics = new WebappLaunchCauseMetrics(mActivity, null);
 
         metrics.onReceivedIntent();
         metrics.recordLaunchCause();
-        ++count;
-        Assert.assertEquals(count, histogramCountForValue(LaunchCause.OTHER));
+        histogram.assertExpected();
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ui/fold_transitions/FoldTransitionControllerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ui/fold_transitions/FoldTransitionControllerUnitTest.java
new file mode 100644
index 0000000..269c29d
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ui/fold_transitions/FoldTransitionControllerUnitTest.java
@@ -0,0 +1,160 @@
+// Copyright 2023 The Chromium Authors
+// 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.ui.fold_transitions;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.os.Bundle;
+import android.os.Handler;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.layouts.LayoutStateProvider;
+import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver;
+import org.chromium.chrome.browser.layouts.LayoutType;
+import org.chromium.chrome.browser.omnibox.OmniboxFocusReason;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.toolbar.ToolbarManager;
+import org.chromium.url.JUnitTestGURLs;
+
+/** Unit tests for {@link FoldTransitionController}. */
+@RunWith(BaseRobolectricTestRunner.class)
+public class FoldTransitionControllerUnitTest {
+    @Mock
+    private ActivityTabProvider mActivityTabProvider;
+    @Mock
+    private Tab mActivityTab;
+    @Mock
+    private ToolbarManager mToolbarManager;
+    @Mock
+    private LayoutStateProvider mLayoutManager;
+    @Mock
+    private Handler mHandler;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        doReturn(mActivityTab).when(mActivityTabProvider).get();
+        doReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.HTTP_URL)).when(mActivityTab).getUrl();
+        doNothing().when(mToolbarManager).setUrlBarFocusAndText(anyBoolean(), anyInt(), any());
+        doNothing().when(mLayoutManager).addObserver(any());
+        doReturn(true).when(mLayoutManager).isLayoutStartingToShow(LayoutType.BROWSING);
+    }
+
+    @Test
+    public void testSaveUiState_urlBarFocused() {
+        String text = "hello";
+        doReturn(true).when(mToolbarManager).isUrlBarFocused();
+        doReturn(text).when(mToolbarManager).getUrlBarTextWithoutAutocomplete();
+        Bundle savedInstanceState = new Bundle();
+        FoldTransitionController.saveUiState(savedInstanceState, mToolbarManager,
+                mActivityTabProvider, /* didChangeTabletMode= */ true);
+
+        Assert.assertTrue("Saved instance state should contain URL_BAR_FOCUS_STATE.",
+                savedInstanceState.containsKey(FoldTransitionController.URL_BAR_FOCUS_STATE));
+        Assert.assertTrue("URL_BAR_FOCUS_STATE in the saved instance state should be true.",
+                savedInstanceState.getBoolean(FoldTransitionController.URL_BAR_FOCUS_STATE));
+        Assert.assertTrue("Saved instance state should contain URL_BAR_EDIT_TEXT.",
+                savedInstanceState.containsKey(FoldTransitionController.URL_BAR_EDIT_TEXT));
+        Assert.assertEquals("URL_BAR_EDIT_TEXT in the saved instance state should match.", text,
+                savedInstanceState.getString(FoldTransitionController.URL_BAR_EDIT_TEXT));
+    }
+
+    @Test
+    public void testSaveUiState_urlBarNotFocused() {
+        doReturn(false).when(mToolbarManager).isUrlBarFocused();
+        Bundle savedInstanceState = new Bundle();
+        FoldTransitionController.saveUiState(savedInstanceState, mToolbarManager,
+                mActivityTabProvider, /* didChangeTabletMode= */ true);
+
+        Assert.assertFalse("Saved instance state should not contain URL_BAR_FOCUS_STATE.",
+                savedInstanceState.containsKey(FoldTransitionController.URL_BAR_FOCUS_STATE));
+        Assert.assertFalse("Saved instance state should not contain URL_BAR_EDIT_TEXT.",
+                savedInstanceState.containsKey(FoldTransitionController.URL_BAR_EDIT_TEXT));
+    }
+
+    @Test
+    public void testRestoreUiState_urlBarFocused_layoutPendingShow() {
+        String text = "hello";
+        FoldTransitionController.restoreUiState(
+                createSavedInstanceState(
+                        /* didChangeTabletMode= */ true, /* urlBarFocused= */ true, text),
+                mToolbarManager, mLayoutManager, mHandler);
+        ArgumentCaptor<LayoutStateObserver> layoutStateObserverCaptor =
+                ArgumentCaptor.forClass(LayoutStateObserver.class);
+        verify(mLayoutManager).addObserver(layoutStateObserverCaptor.capture());
+
+        // Simulate invocation of Layout#doneShowing after invocation of #restoreUiState.
+        doReturn(true).when(mLayoutManager).isLayoutVisible(LayoutType.BROWSING);
+        layoutStateObserverCaptor.getValue().onFinishedShowing(LayoutType.BROWSING);
+        ArgumentCaptor<Runnable> postRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+        verify(mHandler).post(postRunnableCaptor.capture());
+        postRunnableCaptor.getValue().run();
+        verify(mToolbarManager)
+                .setUrlBarFocusAndText(true, OmniboxFocusReason.FOLD_TRANSITION_RESTORATION, text);
+    }
+
+    @Test
+    public void testRestoreUiState_urlBarFocused_layoutDoneShowing() {
+        String text = "hello";
+        // Assume that Layout#doneShowing is invoked before invocation of #restoreUiState.
+        doReturn(true).when(mLayoutManager).isLayoutVisible(LayoutType.BROWSING);
+        doReturn(false).when(mLayoutManager).isLayoutStartingToShow(LayoutType.BROWSING);
+        FoldTransitionController.restoreUiState(
+                createSavedInstanceState(
+                        /* didChangeTabletMode= */ true, /* urlBarFocused= */ true, text),
+                mToolbarManager, mLayoutManager, mHandler);
+        verify(mToolbarManager)
+                .setUrlBarFocusAndText(true, OmniboxFocusReason.FOLD_TRANSITION_RESTORATION, text);
+    }
+
+    @Test
+    public void testRestoreUiState_urlBarNotFocused() {
+        FoldTransitionController.restoreUiState(
+                createSavedInstanceState(
+                        /* didChangeTabletMode= */ true, /* urlBarFocused= */ false, null),
+                mToolbarManager, mLayoutManager, mHandler);
+        verify(mLayoutManager, never()).addObserver(any());
+        verify(mToolbarManager, never()).setUrlBarFocusAndText(anyBoolean(), anyInt(), any());
+    }
+
+    @Test
+    public void testRestoreUiState_didNotChangeTabletMode() {
+        String text = "hello";
+        FoldTransitionController.restoreUiState(
+                createSavedInstanceState(
+                        /* didChangeTabletMode= */ false, /* urlBarFocused= */ true, text),
+                mToolbarManager, mLayoutManager, mHandler);
+        verify(mLayoutManager, never()).addObserver(any());
+        verify(mToolbarManager, never()).setUrlBarFocusAndText(anyBoolean(), anyInt(), any());
+    }
+
+    private Bundle createSavedInstanceState(
+            boolean didChangeTabletMode, boolean urlBarFocused, String urlBarText) {
+        Bundle savedInstanceState = new Bundle();
+        savedInstanceState.putBoolean(
+                FoldTransitionController.DID_CHANGE_TABLET_MODE, didChangeTabletMode);
+        savedInstanceState.putBoolean(FoldTransitionController.URL_BAR_FOCUS_STATE, urlBarFocused);
+        if (urlBarText != null) {
+            savedInstanceState.putString(FoldTransitionController.URL_BAR_EDIT_TEXT, urlBarText);
+        }
+        return savedInstanceState;
+    }
+}
diff --git a/chrome/app/bookmarks_strings.grdp b/chrome/app/bookmarks_strings.grdp
index 8bf7ea18..274b641 100644
--- a/chrome/app/bookmarks_strings.grdp
+++ b/chrome/app/bookmarks_strings.grdp
@@ -418,6 +418,9 @@
   <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_INCOGNITO_WITH_COUNT" desc="Menu description for opening all urls in a bookmark folder in an Incognito window, which includes a count of urls">
     Open all (<ph name="URL_COUNT">$1<ex>5</ex></ph>) in Incognito window
   </message>
+  <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_TAB_GROUP_WITH_COUNT" desc="Menu description for opening all urls in a bookmark folder in a new tab group, which includes a count of urls">
+    Open all (<ph name="URL_COUNT">$1<ex>5</ex></ph>) in new tab group
+  </message>
   <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB" desc="Menu description for opening a bookmark in a new tab">
     Open in new tab
   </message>
@@ -427,6 +430,9 @@
   <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_INCOGNITO" desc="Menu description for opening a bookmark in Incognito window">
     Open in Incognito window
   </message>
+  <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB_GROUP" desc="Menu description for opening a bookmark in a new tab group">
+    Open in new tab group
+  </message>
   <message name="IDS_BOOKMARK_MANAGER_MENU_RENAME" desc="Title of the bookmark list dropdown menu item that renames folders.">
     Rename
   </message>
diff --git a/chrome/app/bookmarks_strings_grdp/IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_TAB_GROUP_WITH_COUNT.png.sha1 b/chrome/app/bookmarks_strings_grdp/IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_TAB_GROUP_WITH_COUNT.png.sha1
new file mode 100644
index 0000000..4b569fc
--- /dev/null
+++ b/chrome/app/bookmarks_strings_grdp/IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_TAB_GROUP_WITH_COUNT.png.sha1
@@ -0,0 +1 @@
+59cf788db6b00e6b20b05fa8f8829a48d2cf83e5
\ No newline at end of file
diff --git a/chrome/app/bookmarks_strings_grdp/IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB_GROUP.png.sha1 b/chrome/app/bookmarks_strings_grdp/IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB_GROUP.png.sha1
new file mode 100644
index 0000000..2e38056d
--- /dev/null
+++ b/chrome/app/bookmarks_strings_grdp/IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB_GROUP.png.sha1
@@ -0,0 +1 @@
+336db4605fe100d44849174efdf7af250ec25ba6
\ No newline at end of file
diff --git a/chrome/app/media_router_strings.grdp b/chrome/app/media_router_strings.grdp
index a7951a5..56462d5 100644
--- a/chrome/app/media_router_strings.grdp
+++ b/chrome/app/media_router_strings.grdp
@@ -81,8 +81,8 @@
   <message name="IDS_MEDIA_ROUTER_ISSUE_FAILED_TO_CAST" desc="Title of an issue shown when cast intialization failed with no clear reason">
       Failed to cast. Please try again.
   </message>
-  <message name="IDS_MEDIA_ROUTER_ISSUE_CANNOT_TERMINATE" desc="Title of an issue shown when a Cast session cannot be stopped from Chrome side, and needs to be stopped from the Cast device where the Cast session is running.">
-      Cast isn't responding. Stop from <ph name="DEVICE_NAME">$1</ph>.
+  <message name="IDS_MEDIA_ROUTER_ISSUE_CANNOT_TERMINATE" desc="Title of an issue shown when a Cast session cannot be stopped from Chrome side, and needs to be stopped using the remote control for the Cast device where the Cast session is running.">
+      Use remote to stop casting.
   </message>
 
 
diff --git a/chrome/app/media_router_strings_grdp/IDS_MEDIA_ROUTER_ISSUE_CANNOT_TERMINATE.png.sha1 b/chrome/app/media_router_strings_grdp/IDS_MEDIA_ROUTER_ISSUE_CANNOT_TERMINATE.png.sha1
index ea46f6db..caa71096 100644
--- a/chrome/app/media_router_strings_grdp/IDS_MEDIA_ROUTER_ISSUE_CANNOT_TERMINATE.png.sha1
+++ b/chrome/app/media_router_strings_grdp/IDS_MEDIA_ROUTER_ISSUE_CANNOT_TERMINATE.png.sha1
@@ -1 +1 @@
-d27b03a2b03746236eb8af8604d7d9002150a8b2
\ No newline at end of file
+a104a9f9170e06b3c359eb1b874c90f82318a1e1
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index cb366a9b..f3364b6 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -262,6 +262,23 @@
     Keep updates
   </message>
 
+ <!-- ChromeOS End Of Life Incentive -->
+  <message name="IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_TITLE" desc="The title of the end of life incentive which informs the user of an offer with a dollar amount they can get save when upgrading to a new Chromebook.">
+    Save &#36;50 or more on a new Chromebook, when you upgrade today
+  </message>
+  <message name="IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_TITLE" desc="The title of the end of life incentive which informs the user that they should upgrade their device to continue getting software updates.">
+    Upgrade to a new Chromebook for the latest security and software
+  </message>
+  <message name="IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_MESSAGE" desc="The message of the end of life incentive which informs the user that their device will no longer get updates, and to upgrade the device for the latest features, using an offer.">
+    Your Chromebook is no longer receiving security and software updates. Upgrade your device for the latest security and new features. Offer terms apply.
+  </message>
+  <message name="IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_MESSAGE" desc="The message of the end of life incentive which informs the user that their device will no longer get updates, and they should get a new Chromebook.">
+    Your Chromebook is no longer receiving security and software updates. Get a new Chromebook for the best experience.
+  </message>
+  <message name="IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_BUTTON" desc="The button label for the end of life incentive offer which will take the user to a URL to shop for a new device.">
+    Shop Now
+  </message>
+
   <!-- People (OS settings) -->
   <message name="IDS_OS_SETTINGS_PROFILE_NAME" desc="Label with device account first name, showing which user is currently signed in.">
     Currently signed in as <ph name="NAME">$1<ex>John</ex></ph>
@@ -880,8 +897,11 @@
   <message name="IDS_SETTINGS_GOOGLE_DRIVE_DISCONNECT" translateable="false" desc="Action to disconnect from Google Drive in Settings: Files: Google Drive.">
     Disconnect
   </message>
+  <message name="IDS_SETTINGS_GOOGLE_DRIVE_CONNECT" translateable="false" desc="Action to connect Google Drive in Settings: Files: Google Drive.">
+    Connect
+  </message>
   <message name="IDS_SETTINGS_GOOGLE_DRIVE_SIGNED_IN_AS" translateable="false" desc="Label indicating account signed in with Google Drive in Settings: Files: Google Drive.">
-    Signed in as
+    Signed in as: <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="DRIVE_ACCOUNT_EMAIL">$1<ex>john@google.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph>
   </message>
   <message name="IDS_SETTINGS_GOOGLE_DRIVE_OFFLINE_TITLE" translateable="false" desc="Title for the everything offline feature in Settings: Files: Google Drive.">
     Keep your files available when you're offline
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_MESSAGE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_MESSAGE.png.sha1
new file mode 100644
index 0000000..39d24899
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_MESSAGE.png.sha1
@@ -0,0 +1 @@
+7e7f43bb4b8733411d5dc281153e878d7606cc98
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_TITLE.png.sha1
new file mode 100644
index 0000000..39d24899
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_TITLE.png.sha1
@@ -0,0 +1 @@
+7e7f43bb4b8733411d5dc281153e878d7606cc98
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_BUTTON.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_BUTTON.png.sha1
new file mode 100644
index 0000000..ce3e5faa
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_BUTTON.png.sha1
@@ -0,0 +1 @@
+9693712ac4d495b56c4877b137f2ca07c4b7aa8f
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_MESSAGE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_MESSAGE.png.sha1
new file mode 100644
index 0000000..ce3e5faa
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_MESSAGE.png.sha1
@@ -0,0 +1 @@
+9693712ac4d495b56c4877b137f2ca07c4b7aa8f
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_TITLE.png.sha1
new file mode 100644
index 0000000..ce3e5faa
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_TITLE.png.sha1
@@ -0,0 +1 @@
+9693712ac4d495b56c4877b137f2ca07c4b7aa8f
\ No newline at end of file
diff --git a/chrome/app/password_manager_ui_strings.grdp b/chrome/app/password_manager_ui_strings.grdp
index d868f3e..2cc5359f 100644
--- a/chrome/app/password_manager_ui_strings.grdp
+++ b/chrome/app/password_manager_ui_strings.grdp
@@ -409,4 +409,10 @@
   <message name="IDS_PASSWORD_MANAGER_UI_DELETE_DIALOG_FROM_DEVICE_CHECKBOX_LABEL" desc="The label for the checkbox that represents whether the user wishes to remove a password from the device.">
     From this device
   </message>
+  <message name="IDS_PASSWORD_MANAGER_UI_APPS_LABEL" desc="Label shown if credential is saved only for apps.">
+    Apps
+  </message>
+  <message name="IDS_PASSWORD_MANAGER_UI_SITES_AND_APPS_LABEL" desc="Label shown if credential is saved for sites and apps.">
+    Sites and apps
+  </message>
 </grit-part>
diff --git a/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_APPS_LABEL.png.sha1 b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_APPS_LABEL.png.sha1
new file mode 100644
index 0000000..39a8b1a
--- /dev/null
+++ b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_APPS_LABEL.png.sha1
@@ -0,0 +1 @@
+3045ccd66a172bde7aba8c47c276401a7bba984c
\ No newline at end of file
diff --git a/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_SITES_AND_APPS_LABEL.png.sha1 b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_SITES_AND_APPS_LABEL.png.sha1
new file mode 100644
index 0000000..e801a66
--- /dev/null
+++ b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_SITES_AND_APPS_LABEL.png.sha1
@@ -0,0 +1 @@
+17233e6c77303fffc7a801beba9f9c1a0a33bc0b
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index af20f72..95578f1 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4332,6 +4332,8 @@
       "webauthn/local_credential_management.h",
       "webauthn/observable_authenticator_list.cc",
       "webauthn/observable_authenticator_list.h",
+      "webauthn/passkey_model_factory.cc",
+      "webauthn/passkey_model_factory.h",
       "webauthn/webauthn_switches.cc",
       "webauthn/webauthn_switches.h",
     ]
@@ -4425,6 +4427,7 @@
       "//components/user_notes/interfaces",
       "//components/user_notes/storage",
       "//components/web_modal",
+      "//components/webauthn/core/browser",
       "//courgette:courgette_lib",
       "//services/device/public/cpp/hid",
       "//third_party/sqlite",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index eae1562..1ff639c1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -4425,12 +4425,6 @@
     {"isolation-by-default", flag_descriptions::kIsolationByDefaultName,
      flag_descriptions::kIsolationByDefaultDescription, kOsAll,
      SINGLE_VALUE_TYPE(switches::kIsolationByDefault)},
-#if !BUILDFLAG(IS_ANDROID)
-    {"enable-webview-tag-site-isolation",
-     flag_descriptions::kWebViewTagSiteIsolationName,
-     flag_descriptions::kWebViewTagSiteIsolationDescription, kOsDesktop,
-     FEATURE_VALUE_TYPE(features::kSiteIsolationForGuests)},
-#endif
     {"allow-insecure-localhost", flag_descriptions::kAllowInsecureLocalhostName,
      flag_descriptions::kAllowInsecureLocalhostDescription, kOsAll,
      SINGLE_VALUE_TYPE(switches::kAllowInsecureLocalhost)},
@@ -5886,6 +5880,12 @@
          optimization_guide::features::
              kPageContentAnnotationsPersistSalientImageMetadata)},
 
+    {"page-content-annotations-remote-page-metadata",
+     flag_descriptions::kPageContentAnnotationsRemotePageMetadataName,
+     flag_descriptions::kPageContentAnnotationsRemotePageMetadataDescription,
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(optimization_guide::features::kRemotePageMetadata)},
+
     {"page-entities-page-content-annotations",
      flag_descriptions::kPageEntitiesPageContentAnnotationsName,
      flag_descriptions::kPageEntitiesPageContentAnnotationsDescription,
diff --git a/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.h b/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.h
index 78458e1..547a093c 100644
--- a/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.h
+++ b/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
 #include "content/public/browser/document_service.h"
@@ -93,7 +94,7 @@
   bool stop_transcriptions_ = false;
 
   // The user preferences containing the target and source language codes.
-  PrefService* prefs_;
+  raw_ptr<PrefService> prefs_;
 
   base::WeakPtrFactory<LiveCaptionSpeechRecognitionHost> weak_factory_{this};
 };
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java
index f684adf5..4045632 100644
--- a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java
+++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java
@@ -22,6 +22,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.text.TextUtils;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Pair;
 import android.view.Display;
@@ -30,6 +31,7 @@
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.WindowInsets;
+import android.view.WindowMetrics;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.AutoCompleteTextView;
@@ -591,7 +593,8 @@
     }
 
     private void initializeBreakpointSlider() {
-        int maxBreakpointDp = getMaximumPossibleSizeDp();
+        int maxBreakpointDp =
+                (int) (getMaximumPossibleSizePx() / getResources().getDisplayMetrics().density);
         mPcctBreakpointSlider = findViewById(R.id.pcct_breakpoint_slider);
         mPcctBreakpointLabel = findViewById(R.id.pcct_breakpoint_slider_label);
         mPcctBreakpointSlider.setMax(maxBreakpointDp);
@@ -929,7 +932,7 @@
         actionIntent.putExtra(Intent.EXTRA_EMAIL, "example@example.com");
         actionIntent.putExtra(Intent.EXTRA_SUBJECT, "example");
         PendingIntent pi =
-                PendingIntent.getActivity(this, 0, actionIntent, PendingIntent.FLAG_MUTABLE);
+                PendingIntent.getActivity(this, 0, actionIntent, PendingIntent.FLAG_IMMUTABLE);
         Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.baseline_send_white);
         builder.setActionButton(icon, "send email", pi, true);
     }
@@ -972,25 +975,29 @@
     }
 
     private @Px int getMaximumPossibleSizePx() {
-        @Px
-        int res = 0;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
-            Insets navbarInsets =
-                    getWindowManager().getCurrentWindowMetrics().getWindowInsets().getInsets(
-                            WindowInsets.Type.navigationBars() | WindowInsets.Type.displayCutout());
+            WindowMetrics windowMetrics = getWindowManager().getCurrentWindowMetrics();
+            Insets navbarInsets = windowMetrics.getWindowInsets().getInsets(
+                    WindowInsets.Type.navigationBars() | WindowInsets.Type.displayCutout());
             int navbarWidth = navbarInsets.left + navbarInsets.right;
             Rect windowBounds = getWindowManager().getCurrentWindowMetrics().getBounds();
-            res = windowBounds.width() - navbarWidth;
+            int width = windowBounds.width() - navbarWidth;
+            int height = windowMetrics.getBounds().height();
+            return Math.max(width, height);
         } else {
             Display display = getWindowManager().getDefaultDisplay();
             Point size = new Point();
             display.getSize(size);
-            res = size.x;
-        }
-        return res;
-    }
+            int width = size.x;
 
-    private int getMaximumPossibleSizeDp() {
-        return (int) (getMaximumPossibleSizePx() / getResources().getDisplayMetrics().density);
+            DisplayMetrics displayMetrics = new DisplayMetrics();
+            if (isInMultiWindowMode()) {
+                display.getMetrics(displayMetrics);
+            } else {
+                display.getRealMetrics(displayMetrics);
+            }
+            int height = displayMetrics.heightPixels;
+            return Math.max(width, height);
+        }
     }
 }
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device_unittest.cc b/chrome/browser/android/vr/arcore_device/arcore_device_unittest.cc
index 44c39cce..66e8eb0 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device_unittest.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_device_unittest.cc
@@ -126,6 +126,14 @@
         .Run(nullptr, gpu::kNullSurfaceHandle, nullptr,
              display::Display::Rotation::ROTATE_0, {1024, 512});
   }
+
+  void RequestVrSession(int render_process_id,
+                        int render_frame_id,
+                        SurfaceReadyCallback ready_callback,
+                        SurfaceTouchCallback touch_callback,
+                        SurfaceDestroyedCallback destroyed_callback) override {
+    NOTREACHED();
+  }
   void EndSession() override {}
 
   bool EnsureARCoreLoaded() override { return true; }
diff --git a/chrome/browser/apps/app_discovery_service/recommended_arc_app_fetcher.cc b/chrome/browser/apps/app_discovery_service/recommended_arc_app_fetcher.cc
index 194b82fa..ecb74aa 100644
--- a/chrome/browser/apps/app_discovery_service/recommended_arc_app_fetcher.cc
+++ b/chrome/browser/apps/app_discovery_service/recommended_arc_app_fetcher.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
 #include "chrome/browser/apps/app_discovery_service/play_extras.h"
 #include "chrome/browser/ash/login/screens/recommend_apps/recommend_apps_fetcher.h"
 
@@ -45,31 +46,33 @@
 
   std::vector<Result> results;
   for (auto& big_app : apps) {
-    if (big_app.is_dict()) {
-      const base::Value* app = big_app.FindDictKey("androidApp");
+    const base::Value::Dict* big_app_dict = big_app.GetIfDict();
+    if (big_app_dict) {
+      const base::Value::Dict* app = big_app_dict->FindDict("androidApp");
       if (!app) {
         continue;
       }
-      const std::string* package_name = app->FindStringKey("packageName");
-      const std::string* title = app->FindStringKey("title");
+      const std::string* package_name = app->FindString("packageName");
+      const std::string* title = app->FindString("title");
       if (!package_name || !title)
         continue;
-      const std::string* icon_url = app->FindStringPath("icon.imageUri");
-      const std::string* category = app->FindStringKey("category");
+      const std::string* icon_url =
+          app->FindStringByDottedPath("icon.imageUri");
+      const std::string* category = app->FindString("category");
       const std::string* app_description =
-          app->FindStringPath("appDescription.shortDescription");
+          app->FindStringByDottedPath("appDescription.shortDescription");
       const std::string* content_rating =
-          app->FindStringPath("contentRating.name");
+          app->FindStringByDottedPath("contentRating.name");
       const std::string* content_rating_url =
-          app->FindStringPath("contentRating.image.imageUri");
-      const std::string* in_app_purchases =
-          app->FindStringPath("inAppPurchaseInformation.disclaimerText");
+          app->FindStringByDottedPath("contentRating.image.imageUri");
+      const std::string* in_app_purchases = app->FindStringByDottedPath(
+          "inAppPurchaseInformation.disclaimerText");
       const std::string* previously_installed =
-          app->FindStringPath("fastAppReinstall.explanationText");
+          app->FindStringByDottedPath("fastAppReinstall.explanationText");
       const std::string* contain_ads =
-          app->FindStringPath("adsInformation.disclaimerText");
-      const base::Value* optimized_for_chrome =
-          big_app.FindDictKey("merchCurated");
+          app->FindStringByDottedPath("adsInformation.disclaimerText");
+      const base::Value::Dict* optimized_for_chrome =
+          big_app_dict->FindDict("merchCurated");
 
       auto extras = std::make_unique<PlayExtras>(
           *package_name, icon_url ? GURL(*icon_url) : GURL(),
diff --git a/chrome/browser/apps/app_preload_service/app_preload_service.cc b/chrome/browser/apps/app_preload_service/app_preload_service.cc
index 1d9094e..db4b54ea 100644
--- a/chrome/browser/apps/app_preload_service/app_preload_service.cc
+++ b/chrome/browser/apps/app_preload_service/app_preload_service.cc
@@ -52,6 +52,10 @@
 static constexpr char kFirstLoginFlowHistogramFailureName[] =
     "AppPreloadService.FirstLoginFlowTime.Failure";
 
+bool AreTestAppsEnabled() {
+  return base::FeatureList::IsEnabled(apps::kAppPreloadServiceEnableTestApps);
+}
+
 }  // namespace
 
 namespace apps {
@@ -65,6 +69,10 @@
              "AppPreloadServiceForceRun",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kAppPreloadServiceEnableTestApps,
+             "AppPreloadServiceEnableTestApps",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 AppPreloadService::AppPreloadService(Profile* profile)
     : profile_(profile),
       server_connector_(std::make_unique<AppPreloadServerConnector>()),
@@ -189,8 +197,11 @@
     return false;
   }
 
-  // We currently only install apps which were requested by the device OEM.
-  if (!app.IsOemApp()) {
+  // We currently only install apps which were requested by the device OEM. If
+  // the testing feature is enabled, also install test apps.
+  bool install_reason_allowed =
+      app.IsOemApp() || (app.IsTestApp() && AreTestAppsEnabled());
+  if (!install_reason_allowed) {
     return false;
   }
 
diff --git a/chrome/browser/apps/app_preload_service/app_preload_service.h b/chrome/browser/apps/app_preload_service/app_preload_service.h
index 0b33f2a..8d672663 100644
--- a/chrome/browser/apps/app_preload_service/app_preload_service.h
+++ b/chrome/browser/apps/app_preload_service/app_preload_service.h
@@ -38,6 +38,10 @@
 // the Profile would not normally be eligible.
 BASE_DECLARE_FEATURE(kAppPreloadServiceForceRun);
 
+// Debugging/testing feature to install test apps returned by the server, which
+// are normally silently ignored.
+BASE_DECLARE_FEATURE(kAppPreloadServiceEnableTestApps);
+
 class AppPreloadService : public KeyedService {
  public:
   explicit AppPreloadService(Profile* profile);
diff --git a/chrome/browser/apps/app_preload_service/app_preload_service_browsertest.cc b/chrome/browser/apps/app_preload_service/app_preload_service_browsertest.cc
index b95c607..669c462 100644
--- a/chrome/browser/apps/app_preload_service/app_preload_service_browsertest.cc
+++ b/chrome/browser/apps/app_preload_service/app_preload_service_browsertest.cc
@@ -196,6 +196,28 @@
   ASSERT_FALSE(found);
 }
 
+IN_PROC_BROWSER_TEST_F(AppPreloadServiceBrowserTest, IgnoreTestAppInstall) {
+  proto::AppPreloadListResponse response;
+  auto* app = response.add_apps_to_install();
+  app->set_name("Peanut Types");
+  app->set_package_id("web:https://peanuttypes.com/app");
+  app->set_install_reason(proto::AppPreloadListResponse::INSTALL_REASON_TEST);
+
+  app->mutable_web_extras()->set_manifest_url(
+      https_server()->GetURL(kDefaultManifestUrl).spec());
+  app->mutable_web_extras()->set_original_manifest_url(
+      "https://peanuttypes.com/app");
+
+  SetAppProvisioningResponse(response);
+  // No call to SetManifestResponse, so if installation was attempted, it would
+  // fail.
+
+  base::test::TestFuture<bool> result;
+  auto* service = AppPreloadService::Get(profile());
+  service->StartFirstLoginFlowForTesting(result.GetCallback());
+  ASSERT_TRUE(result.Get());
+}
+
 // Verifies that user-installed apps are not skipped, and are marked as OEM
 // installed.
 IN_PROC_BROWSER_TEST_F(AppPreloadServiceBrowserTest, InstallOverUserApp) {
@@ -380,4 +402,45 @@
   histograms.ExpectTotalCount(kFirstLoginFlowHistogramFailureName, 1);
 }
 
+class AppPreloadServiceWithTestAppsBrowserTest
+    : public AppPreloadServiceBrowserTest {
+ private:
+  base::test::ScopedFeatureList feature_list_{kAppPreloadServiceEnableTestApps};
+};
+
+// When kAppPreloadServiceEnableTestApps is enabled, apps with the "test"
+// install reason should be installed.
+IN_PROC_BROWSER_TEST_F(AppPreloadServiceWithTestAppsBrowserTest,
+                       InstallTestApp) {
+  proto::AppPreloadListResponse response;
+  auto* app = response.add_apps_to_install();
+  app->set_name("Peanut Types");
+  app->set_package_id("web:https://peanuttypes.com/app");
+  app->set_install_reason(proto::AppPreloadListResponse::INSTALL_REASON_TEST);
+
+  app->mutable_web_extras()->set_manifest_url(
+      https_server()->GetURL(kDefaultManifestUrl).spec());
+  app->mutable_web_extras()->set_original_manifest_url(
+      "https://peanuttypes.com/app");
+
+  const std::string kManifest = AddIconToManifest(R"({
+    "name": "Peanut Types",
+    "start_url": "/app",
+    "icons": $1
+  })");
+
+  SetAppProvisioningResponse(response);
+  SetManifestResponse(kDefaultManifestUrl, kManifest);
+
+  base::test::TestFuture<bool> result;
+  auto* service = AppPreloadService::Get(profile());
+  service->StartFirstLoginFlowForTesting(result.GetCallback());
+  ASSERT_TRUE(result.Get());
+
+  auto app_id = web_app::GenerateAppId(absl::nullopt,
+                                       GURL("https://peanuttypes.com/app"));
+  bool found = app_registry_cache().ForOneApp(app_id, [](const AppUpdate&) {});
+  ASSERT_TRUE(found);
+}
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_preload_service/preload_app_definition.cc b/chrome/browser/apps/app_preload_service/preload_app_definition.cc
index f8de346..da9d47e 100644
--- a/chrome/browser/apps/app_preload_service/preload_app_definition.cc
+++ b/chrome/browser/apps/app_preload_service/preload_app_definition.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/apps/app_preload_service/preload_app_definition.h"
 
 #include "base/strings/string_util.h"
+#include "chrome/browser/apps/app_preload_service/proto/app_preload.pb.h"
 #include "chrome/browser/apps/app_service/package_id.h"
 #include "url/gurl.h"
 
@@ -37,6 +38,11 @@
          proto::AppPreloadListResponse::INSTALL_REASON_OEM;
 }
 
+bool PreloadAppDefinition::IsTestApp() const {
+  return app_proto_.install_reason() ==
+         proto::AppPreloadListResponse::INSTALL_REASON_TEST;
+}
+
 GURL PreloadAppDefinition::GetWebAppManifestUrl() const {
   DCHECK_EQ(GetPlatform(), AppType::kWeb);
 
diff --git a/chrome/browser/apps/app_preload_service/preload_app_definition.h b/chrome/browser/apps/app_preload_service/preload_app_definition.h
index 6dbdc97..b25f322 100644
--- a/chrome/browser/apps/app_preload_service/preload_app_definition.h
+++ b/chrome/browser/apps/app_preload_service/preload_app_definition.h
@@ -28,6 +28,7 @@
   std::string GetName() const;
   AppType GetPlatform() const;
   bool IsOemApp() const;
+  bool IsTestApp() const;
 
   // Returns the Web App manifest URL for the app, which hosts the manifest of
   // the app in a JSON format. The URL could point to a local file, or a web
diff --git a/chrome/browser/apps/app_preload_service/preload_app_definition_unittest.cc b/chrome/browser/apps/app_preload_service/preload_app_definition_unittest.cc
index 1670810..3da47ef2 100644
--- a/chrome/browser/apps/app_preload_service/preload_app_definition_unittest.cc
+++ b/chrome/browser/apps/app_preload_service/preload_app_definition_unittest.cc
@@ -94,6 +94,22 @@
   ASSERT_FALSE(app_def.IsOemApp());
 }
 
+TEST_F(PreloadAppDefinitionTest, IsTestApp) {
+  proto::AppPreloadListResponse_App app;
+  app.set_install_reason(proto::AppPreloadListResponse::INSTALL_REASON_TEST);
+
+  PreloadAppDefinition app_def(app);
+  ASSERT_TRUE(app_def.IsTestApp());
+}
+
+TEST_F(PreloadAppDefinitionTest, IsNotTestApp) {
+  proto::AppPreloadListResponse_App app;
+  app.set_install_reason(proto::AppPreloadListResponse::INSTALL_REASON_OEM);
+
+  PreloadAppDefinition app_def(app);
+  ASSERT_FALSE(app_def.IsTestApp());
+}
+
 TEST_F(PreloadAppDefinitionTest, GetWebAppManifestUrlWebsite) {
   proto::AppPreloadListResponse_App app = CreateTestWebApp();
   app.mutable_web_extras()->set_manifest_url(
diff --git a/chrome/browser/apps/app_preload_service/proto/app_preload.proto b/chrome/browser/apps/app_preload_service/proto/app_preload.proto
index fd1dbc3..4967ef5 100644
--- a/chrome/browser/apps/app_preload_service/proto/app_preload.proto
+++ b/chrome/browser/apps/app_preload_service/proto/app_preload.proto
@@ -37,6 +37,11 @@
 
     // An app installed for an OEM.
     INSTALL_REASON_OEM = 2;
+
+    // An app which is being returned by the server for testing purposes.
+    // This generally will be ignored by the client unless it is configured
+    // in some sort of test mode.
+    INSTALL_REASON_TEST = 3;
   }
 
   message Icon {
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
index 3e8db2b5..59f4faea 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
@@ -503,7 +503,7 @@
 
 void LoadIconFromExtension(IconType icon_type,
                            int size_hint_in_dip,
-                           content::BrowserContext* context,
+                           Profile* profile,
                            const std::string& extension_id,
                            IconEffects icon_effects,
                            LoadIconCallback callback) {
@@ -512,60 +512,58 @@
   constexpr bool is_placeholder_icon = false;
   scoped_refptr<AppIconLoader> icon_loader =
       base::MakeRefCounted<AppIconLoader>(
-          icon_type, size_hint_in_dip, is_placeholder_icon, icon_effects,
-          IDR_APP_DEFAULT_ICON, std::move(callback));
+          profile, icon_type, size_hint_in_dip, is_placeholder_icon,
+          icon_effects, IDR_APP_DEFAULT_ICON, std::move(callback));
   icon_loader->LoadExtensionIcon(
-      extensions::ExtensionRegistry::Get(context)->GetInstalledExtension(
-          extension_id),
-      context);
+      extensions::ExtensionRegistry::Get(profile)->GetInstalledExtension(
+          extension_id));
 }
 
-void LoadIconFromWebApp(content::BrowserContext* context,
+void LoadIconFromWebApp(Profile* profile,
                         IconType icon_type,
                         int size_hint_in_dip,
                         const std::string& web_app_id,
                         IconEffects icon_effects,
                         LoadIconCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(context);
+  CHECK(profile);
   web_app::WebAppProvider* web_app_provider =
-      web_app::WebAppProvider::GetForLocalAppsUnchecked(
-          Profile::FromBrowserContext(context));
+      web_app::WebAppProvider::GetForLocalAppsUnchecked(profile);
 
-  DCHECK(web_app_provider);
+  CHECK(web_app_provider);
   constexpr bool is_placeholder_icon = false;
   scoped_refptr<AppIconLoader> icon_loader =
       base::MakeRefCounted<AppIconLoader>(
-          icon_type, size_hint_in_dip, is_placeholder_icon, icon_effects,
-          IDR_APP_DEFAULT_ICON, std::move(callback));
+          profile, icon_type, size_hint_in_dip, is_placeholder_icon,
+          icon_effects, IDR_APP_DEFAULT_ICON, std::move(callback));
   icon_loader->LoadWebAppIcon(
       web_app_id,
       web_app_provider->registrar_unsafe().GetAppStartUrl(web_app_id),
-      web_app_provider->icon_manager(), Profile::FromBrowserContext(context));
+      web_app_provider->icon_manager());
 }
 
 #if BUILDFLAG(IS_CHROMEOS)
-void GetWebAppCompressedIconData(content::BrowserContext* context,
+void GetWebAppCompressedIconData(Profile* profile,
                                  const std::string& web_app_id,
                                  int size_in_dip,
                                  ui::ResourceScaleFactor scale_factor,
                                  LoadIconCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(context);
+  CHECK(profile);
   web_app::WebAppProvider* web_app_provider =
-      web_app::WebAppProvider::GetForLocalAppsUnchecked(
-          Profile::FromBrowserContext(context));
+      web_app::WebAppProvider::GetForLocalAppsUnchecked(profile);
 
   DCHECK(web_app_provider);
   scoped_refptr<AppIconLoader> icon_loader =
       base::MakeRefCounted<AppIconLoader>(
-          IconType::kCompressed, size_in_dip, /*is_placeholder_icon=*/false,
-          IconEffects::kNone, kInvalidIconResource, std::move(callback));
+          profile, IconType::kCompressed, size_in_dip,
+          /*is_placeholder_icon=*/false, IconEffects::kNone,
+          kInvalidIconResource, std::move(callback));
   icon_loader->GetWebAppCompressedIconData(web_app_id, scale_factor,
                                            web_app_provider->icon_manager());
 }
 
-void GetChromeAppCompressedIconData(content::BrowserContext* context,
+void GetChromeAppCompressedIconData(Profile* profile,
                                     const std::string& extension_id,
                                     int size_in_dip,
                                     ui::ResourceScaleFactor scale_factor,
@@ -574,25 +572,26 @@
 
   scoped_refptr<AppIconLoader> icon_loader =
       base::MakeRefCounted<AppIconLoader>(
-          IconType::kCompressed, size_in_dip, /*is_placeholder_icon=*/false,
-          IconEffects::kNone, kInvalidIconResource, std::move(callback));
+          profile, IconType::kCompressed, size_in_dip,
+          /*is_placeholder_icon=*/false, IconEffects::kNone,
+          kInvalidIconResource, std::move(callback));
   icon_loader->GetChromeAppCompressedIconData(
-      extensions::ExtensionRegistry::Get(context)->GetInstalledExtension(
+      extensions::ExtensionRegistry::Get(profile)->GetInstalledExtension(
           extension_id),
-      context, scale_factor);
+      scale_factor);
 }
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-void GetArcAppCompressedIconData(content::BrowserContext* context,
+void GetArcAppCompressedIconData(Profile* profile,
                                  const std::string& app_id,
                                  int size_in_dip,
                                  ui::ResourceScaleFactor scale_factor,
                                  LoadIconCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(context);
+  CHECK(profile);
 
-  ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context);
+  ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile);
   if (!prefs) {
     std::move(callback).Run(std::make_unique<IconValue>());
     return;
@@ -600,25 +599,26 @@
 
   scoped_refptr<AppIconLoader> icon_loader =
       base::MakeRefCounted<AppIconLoader>(
-          IconType::kCompressed, size_in_dip, /*is_placeholder_icon=*/false,
-          IconEffects::kNone, kInvalidIconResource, std::move(callback));
+          profile, IconType::kCompressed, size_in_dip,
+          /*is_placeholder_icon=*/false, IconEffects::kNone,
+          kInvalidIconResource, std::move(callback));
   icon_loader->GetArcAppCompressedIconData(app_id, prefs, scale_factor);
 }
 
-void GetGuestOSAppCompressedIconData(content::BrowserContext* context,
+void GetGuestOSAppCompressedIconData(Profile* profile,
                                      const std::string& app_id,
                                      int size_in_dip,
                                      ui::ResourceScaleFactor scale_factor,
                                      LoadIconCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(context);
+  CHECK(profile);
 
   scoped_refptr<AppIconLoader> icon_loader =
       base::MakeRefCounted<AppIconLoader>(
-          IconType::kCompressed, size_in_dip, /*is_placeholder_icon=*/false,
-          IconEffects::kNone, kInvalidIconResource, std::move(callback));
-  icon_loader->GetGuestOSAppCompressedIconData(
-      Profile::FromBrowserContext(context), app_id, scale_factor);
+          profile, IconType::kCompressed, size_in_dip,
+          /*is_placeholder_icon=*/false, IconEffects::kNone,
+          kInvalidIconResource, std::move(callback));
+  icon_loader->GetGuestOSAppCompressedIconData(app_id, scale_factor);
 }
 
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
@@ -635,8 +635,9 @@
 
   scoped_refptr<AppIconLoader> icon_loader =
       base::MakeRefCounted<AppIconLoader>(
-          icon_type, size_hint_in_dip, is_placeholder_icon, icon_effects,
-          kInvalidIconResource, std::move(fallback), std::move(callback));
+          /*profile=*/nullptr, icon_type, size_hint_in_dip, is_placeholder_icon,
+          icon_effects, kInvalidIconResource, std::move(fallback),
+          std::move(callback));
   icon_loader->LoadCompressedIconFromFile(path);
 }
 
@@ -650,8 +651,8 @@
 
   scoped_refptr<AppIconLoader> icon_loader =
       base::MakeRefCounted<AppIconLoader>(
-          icon_type, size_hint_in_dip, is_placeholder_icon, icon_effects,
-          kInvalidIconResource, std::move(callback));
+          /*profile=*/nullptr, icon_type, size_hint_in_dip, is_placeholder_icon,
+          icon_effects, kInvalidIconResource, std::move(callback));
   icon_loader->LoadIconFromCompressedData(compressed_icon_data);
 }
 
@@ -667,8 +668,8 @@
 
   scoped_refptr<AppIconLoader> icon_loader =
       base::MakeRefCounted<AppIconLoader>(
-          icon_type, size_hint_in_dip, is_placeholder_icon, icon_effects,
-          fallback_icon_resource, std::move(callback));
+          /*profile=*/nullptr, icon_type, size_hint_in_dip, is_placeholder_icon,
+          icon_effects, fallback_icon_resource, std::move(callback));
   icon_loader->LoadIconFromResource(resource_id);
 }
 
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_factory.h b/chrome/browser/apps/app_service/app_icon/app_icon_factory.h
index b60cd88..0b904a5 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_factory.h
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_factory.h
@@ -24,14 +24,11 @@
 #include "ui/base/resource/resource_scale_factor.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-namespace content {
-class BrowserContext;
-}
-
 namespace gfx {
 class ImageSkia;
 }
 
+class Profile;
 class SkBitmap;
 
 namespace apps {
@@ -129,13 +126,13 @@
 // Loads an icon from an extension.
 void LoadIconFromExtension(IconType icon_type,
                            int size_hint_in_dip,
-                           content::BrowserContext* context,
+                           Profile* profile,
                            const std::string& extension_id,
                            IconEffects icon_effects,
                            LoadIconCallback callback);
 
 // Loads an icon from a web app.
-void LoadIconFromWebApp(content::BrowserContext* context,
+void LoadIconFromWebApp(Profile* profile,
                         IconType icon_type,
                         int size_hint_in_dip,
                         const std::string& web_app_id,
@@ -144,7 +141,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS)
 // Requests a compressed icon data for an web app identified by `web_app_id`.
-void GetWebAppCompressedIconData(content::BrowserContext* context,
+void GetWebAppCompressedIconData(Profile* profile,
                                  const std::string& web_app_id,
                                  int size_in_dip,
                                  ui::ResourceScaleFactor scale_factor,
@@ -152,7 +149,7 @@
 
 // Requests a compressed icon data for a chrome app identified by
 // `extension_id`.
-void GetChromeAppCompressedIconData(content::BrowserContext* context,
+void GetChromeAppCompressedIconData(Profile* profile,
                                     const std::string& extension_id,
                                     int size_in_dip,
                                     ui::ResourceScaleFactor scale_factor,
@@ -161,14 +158,14 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 // Requests a compressed icon data for an ARC app identified by `app_id`.
-void GetArcAppCompressedIconData(content::BrowserContext* context,
+void GetArcAppCompressedIconData(Profile* profile,
                                  const std::string& app_id,
                                  int size_in_dip,
                                  ui::ResourceScaleFactor scale_factor,
                                  LoadIconCallback callback);
 
 // Requests a compressed icon data for a Guest OS app identified by `app_id`.
-void GetGuestOSAppCompressedIconData(content::BrowserContext* context,
+void GetGuestOSAppCompressedIconData(Profile* profile,
                                      const std::string& app_id,
                                      int size_in_dip,
                                      ui::ResourceScaleFactor scale_factor,
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc b/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc
index 7c238b26..39db579 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc
@@ -296,13 +296,15 @@
          background_icon_path.empty();
 }
 
-AppIconLoader::AppIconLoader(IconType icon_type,
+AppIconLoader::AppIconLoader(Profile* profile,
+                             IconType icon_type,
                              int size_hint_in_dip,
                              bool is_placeholder_icon,
                              apps::IconEffects icon_effects,
                              int fallback_icon_resource,
                              LoadIconCallback callback)
-    : AppIconLoader(icon_type,
+    : AppIconLoader(profile,
+                    icon_type,
                     size_hint_in_dip,
                     is_placeholder_icon,
                     icon_effects,
@@ -311,6 +313,7 @@
                     std::move(callback)) {}
 
 AppIconLoader::AppIconLoader(
+    Profile* profile,
     IconType icon_type,
     int size_hint_in_dip,
     bool is_placeholder_icon,
@@ -318,7 +321,8 @@
     int fallback_icon_resource,
     base::OnceCallback<void(LoadIconCallback)> fallback,
     LoadIconCallback callback)
-    : icon_type_(icon_type),
+    : profile_(profile),
+      icon_type_(icon_type),
       size_hint_in_dip_(size_hint_in_dip),
       icon_size_in_px_(apps_util::ConvertDipToPx(
           size_hint_in_dip,
@@ -329,7 +333,11 @@
       icon_effects_(icon_effects),
       fallback_icon_resource_(fallback_icon_resource),
       callback_(std::move(callback)),
-      fallback_callback_(std::move(fallback)) {}
+      fallback_callback_(std::move(fallback)) {
+  if (profile) {
+    profile_observation_.Observe(profile);
+  }
+}
 
 AppIconLoader::AppIconLoader(
     int size_hint_in_dip,
@@ -412,12 +420,11 @@
 
 void AppIconLoader::LoadWebAppIcon(const std::string& web_app_id,
                                    const GURL& launch_url,
-                                   web_app::WebAppIconManager& icon_manager,
-                                   Profile* profile) {
+                                   web_app::WebAppIconManager& icon_manager) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  CHECK(profile_);
 
   fallback_favicon_url_ = launch_url;
-  profile_ = profile;
 
   // In all other callpaths MaybeApplyEffectsAndComplete() uses
   // |icon_scale_for_compressed_response_| to apps::EncodeImageToPngBytes(). In
@@ -493,9 +500,9 @@
   NOTREACHED();
 }
 
-void AppIconLoader::LoadExtensionIcon(const extensions::Extension* extension,
-                                      content::BrowserContext* context) {
+void AppIconLoader::LoadExtensionIcon(const extensions::Extension* extension) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  CHECK(profile_);
 
   if (!extension) {
     MaybeLoadFallbackOrCompleteEmpty();
@@ -504,7 +511,6 @@
 
   fallback_favicon_url_ =
       extensions::AppLaunchInfo::GetFullLaunchURL(extension);
-  profile_ = Profile::FromBrowserContext(context);
   switch (icon_type_) {
     case IconType::kCompressed:
       [[fallthrough]];
@@ -514,7 +520,7 @@
       // We always load the uncompressed image to apply the icon effects or
       // resize the icon size, and then re-encode the image if the compressed
       // icon is requested.
-      extensions::ImageLoader::Get(context)->LoadImageAtEveryScaleFactorAsync(
+      extensions::ImageLoader::Get(profile_)->LoadImageAtEveryScaleFactorAsync(
           extension, gfx::Size(size_hint_in_dip_, size_hint_in_dip_),
           ImageToImageSkia(
               base::BindOnce(&AppIconLoader::MaybeApplyEffectsAndComplete,
@@ -708,9 +714,9 @@
 
 void AppIconLoader::GetChromeAppCompressedIconData(
     const extensions::Extension* extension,
-    content::BrowserContext* context,
     ui::ResourceScaleFactor scale_factor) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  CHECK(profile_);
 
   if (!extension || icon_type_ == IconType::kUnknown) {
     MaybeLoadFallbackOrCompleteEmpty();
@@ -718,8 +724,7 @@
   }
 
   icon_scale_ = ui::GetScaleForResourceScaleFactor(scale_factor);
-  profile_ = Profile::FromBrowserContext(context);
-  extensions::ImageLoader::Get(context)->LoadImageAtEveryScaleFactorAsync(
+  extensions::ImageLoader::Get(profile_)->LoadImageAtEveryScaleFactorAsync(
       extension, gfx::Size(size_hint_in_dip_, size_hint_in_dip_),
       ImageToImageSkia(
           base::BindOnce(&AppIconLoader::OnReadChromeAppForCompressedIconData,
@@ -771,13 +776,11 @@
 }
 
 void AppIconLoader::GetGuestOSAppCompressedIconData(
-    Profile* profile,
     const std::string& app_id,
     ui::ResourceScaleFactor scale_factor) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(profile);
+  CHECK(profile_);
 
-  profile_ = profile;
   auto* registry =
       guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile_);
   if (!registry) {
@@ -873,7 +876,11 @@
 
 void AppIconLoader::TranscodeIconFromSvg(base::FilePath svg_path,
                                          base::FilePath png_path) {
-  DCHECK(profile_);
+  if (!profile_) {
+    // Profile has been destroyed.
+    return;
+  }
+
   gfx::Size kPreferredSize = gfx::Size(128, 128);
   if (!svg_icon_transcoder_) {
     svg_icon_transcoder_ = std::make_unique<SvgIconTranscoder>(profile_);
@@ -1117,7 +1124,7 @@
 }
 
 void AppIconLoader::MaybeLoadFallbackOrCompleteEmpty() {
-  if (fallback_favicon_url_.is_valid() &&
+  if (profile_ && fallback_favicon_url_.is_valid() &&
       icon_size_in_px_ == kFaviconFallbackImagePx) {
     GURL favicon_url = fallback_favicon_url_;
     // Reset to avoid infinite loops.
@@ -1174,4 +1181,10 @@
   std::move(callback_).Run(std::make_unique<IconValue>());
 }
 
+void AppIconLoader::OnProfileWillBeDestroyed(Profile* profile) {
+  profile_ = nullptr;
+  profile_observation_.Reset();
+  cancelable_task_tracker_.TryCancelAll();
+}
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_loader.h b/chrome/browser/apps/app_service/app_icon/app_icon_loader.h
index b1b8a2b..23cc4fbb 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_loader.h
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_loader.h
@@ -13,10 +13,12 @@
 #include "base/files/file_path.h"
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "base/task/cancelable_task_tracker.h"
 #include "base/task/sequenced_task_runner.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_icon/app_icon_factory.h"
+#include "chrome/browser/profiles/profile_observer.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "extensions/common/constants.h"
 #include "ui/gfx/image/image_skia.h"
@@ -30,10 +32,6 @@
 class IconDecodeRequest;
 }
 
-namespace content {
-class BrowserContext;
-}
-
 namespace extensions {
 class Extension;
 }
@@ -71,19 +69,22 @@
 // * Allow easy additions to the icon loader if necessary (like new effects or
 // backups).
 // Must be created & run from the UI thread.
-class AppIconLoader : public base::RefCounted<AppIconLoader> {
+class AppIconLoader : public base::RefCounted<AppIconLoader>,
+                      public ProfileObserver {
  public:
   static const int kFaviconFallbackImagePx =
       extension_misc::EXTENSION_ICON_BITTY;
 
-  AppIconLoader(IconType icon_type,
+  AppIconLoader(Profile* profile,
+                IconType icon_type,
                 int size_hint_in_dip,
                 bool is_placeholder_icon,
                 apps::IconEffects icon_effects,
                 int fallback_icon_resource,
                 LoadIconCallback callback);
 
-  AppIconLoader(IconType icon_type,
+  AppIconLoader(Profile* profile,
+                IconType icon_type,
                 int size_hint_in_dip,
                 bool is_placeholder_icon,
                 apps::IconEffects icon_effects,
@@ -106,11 +107,9 @@
 
   void LoadWebAppIcon(const std::string& web_app_id,
                       const GURL& launch_url,
-                      web_app::WebAppIconManager& icon_manager,
-                      Profile* profile);
+                      web_app::WebAppIconManager& icon_manager);
 
-  void LoadExtensionIcon(const extensions::Extension* extension,
-                         content::BrowserContext* context);
+  void LoadExtensionIcon(const extensions::Extension* extension);
 
   // The image file must be compressed using the default encoding.
   void LoadCompressedIconFromFile(const base::FilePath& path);
@@ -143,7 +142,6 @@
   // Requests a compressed icon data with `scale_factor` for a chrome app
   // identified by `extension`.
   void GetChromeAppCompressedIconData(const extensions::Extension* extension,
-                                      content::BrowserContext* context,
                                       ui::ResourceScaleFactor scale_factor);
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
@@ -156,15 +154,14 @@
 
   // Requests a compressed icon data with `scale_factor` for a Guest OS app
   // identified by `app_id`.
-  void GetGuestOSAppCompressedIconData(Profile* profile,
-                                       const std::string& app_id,
+  void GetGuestOSAppCompressedIconData(const std::string& app_id,
                                        ui::ResourceScaleFactor scale_factor);
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
  private:
   friend class base::RefCounted<AppIconLoader>;
 
-  ~AppIconLoader();
+  ~AppIconLoader() override;
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   void OnGetArcAppCompressedIconData(AdaptiveIconPaths app_icon_paths,
@@ -209,6 +206,16 @@
 
   void MaybeLoadFallbackOrCompleteEmpty();
 
+  // ProfileManagerObserver overrides.
+  void OnProfileWillBeDestroyed(Profile* profile) override;
+
+  // If non-null, points to the profile necessary to support the icon loading.
+  // Not used by all codepaths, so this isn't mandatory in the constructor,
+  // and could be reset to null if the profile is torn down whilst async icon
+  // loading is in-flight.
+  raw_ptr<Profile> profile_ = nullptr;
+  base::ScopedObservation<Profile, ProfileObserver> profile_observation_{this};
+
   const IconType icon_type_ = IconType::kUnknown;
 
   const int size_hint_in_dip_ = 0;
@@ -228,7 +235,6 @@
   // first fallback method attempted in MaybeLoadFallbackOrCompleteEmpty().
   // These members are only populated from LoadWebAppIcon or LoadExtensionIcon.
   GURL fallback_favicon_url_;
-  raw_ptr<Profile, DanglingUntriaged> profile_ = nullptr;
 
   // If |fallback_icon_resource_| is not |kInvalidIconResource|, then it is the
   // second fallback method attempted in MaybeLoadFallbackOrCompleteEmpty()
diff --git a/chrome/browser/apps/app_service/app_icon/chrome_apps_icon_unittest.cc b/chrome/browser/apps/app_service/app_icon/chrome_apps_icon_unittest.cc
index 23badbce..8686c57 100644
--- a/chrome/browser/apps/app_service/app_icon/chrome_apps_icon_unittest.cc
+++ b/chrome/browser/apps/app_service/app_icon/chrome_apps_icon_unittest.cc
@@ -53,12 +53,10 @@
     // - 1 dummy extension (which should not be visible in the launcher)
     // - 2 packaged extension apps
     // - 1 hosted extension app
-    base::FilePath source_install_dir =
-        data_dir().AppendASCII("app_list").AppendASCII("Extensions");
-    base::FilePath pref_path =
-        source_install_dir.DirName().Append(chrome::kPreferencesFilename);
     ExtensionServiceInitParams params;
-    InitializeInstalledExtensionService(pref_path, source_install_dir, params);
+    ASSERT_TRUE(params.ConfigureByTestDataDirectory(
+        data_dir().AppendASCII("app_list")));
+    InitializeExtensionService(params);
     service_->Init();
 
     // Let any async services complete their set-up.
diff --git a/chrome/browser/apps/app_service/intent_util.cc b/chrome/browser/apps/app_service/intent_util.cc
index 39662c7d..ad7a781 100644
--- a/chrome/browser/apps/app_service/intent_util.cc
+++ b/chrome/browser/apps/app_service/intent_util.cc
@@ -262,7 +262,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS)
   if (extensions::ActionHandlersInfo::HasActionHandler(
-          extension, extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE)) {
+          extension, extensions::api::app_runtime::ActionType::kNewNote)) {
     filters.push_back(CreateNoteTakingFilter());
   }
 #endif
diff --git a/chrome/browser/apps/app_service/intent_util_unittest.cc b/chrome/browser/apps/app_service/intent_util_unittest.cc
index c205a84..6619cd8 100644
--- a/chrome/browser/apps/app_service/intent_util_unittest.cc
+++ b/chrome/browser/apps/app_service/intent_util_unittest.cc
@@ -285,7 +285,7 @@
 TEST_F(IntentUtilsTest, CreateIntentFiltersForChromeApp_NoteTaking) {
   const std::string note_action_handler =
       extensions::api::app_runtime::ToString(
-          extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE);
+          extensions::api::app_runtime::ActionType::kNewNote);
   // Foo app has a note-taking action handler.
   extensions::ExtensionBuilder foo_app("Foo");
   std::string manifest = base::StringPrintf(R"(
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 3254f8c..fa480b6 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -1539,6 +1539,8 @@
     "login/app_mode/force_install_observer.h",
     "login/app_mode/kiosk_launch_controller.cc",
     "login/app_mode/kiosk_launch_controller.h",
+    "login/app_mode/network_ui_controller.cc",
+    "login/app_mode/network_ui_controller.h",
     "login/auth/chrome_login_performer.cc",
     "login/auth/chrome_login_performer.h",
     "login/auth/chrome_safe_mode_delegate.cc",
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
index a19e72e8..a6d0271 100644
--- a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
@@ -1671,10 +1671,8 @@
   sm_.Replay();
 }
 
-// TODO(https://crbug.com/1064947): Flaky on ASAN. (Note MAYBE_ doesn't work
-// well with parameterized tests).
-#if !defined(ADDRESS_SANITIZER)
-IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ResetTtsSettings) {
+// TODO(https://crbug.com/1064947): Flaky on ASAN and linux-chromeos-dbg.
+IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, DISABLED_ResetTtsSettings) {
   EnableChromeVox();
   sm_.Call([this]() {
     ASSERT_TRUE(ui_test_utils::NavigateToURL(
@@ -1706,7 +1704,6 @@
   sm_.ExpectSpeech("Pitch 50 percent");
   sm_.Replay();
 }
-#endif  // !defined(ADDRESS_SANITIZER)
 
 // Tests the keyboard shortcut to cycle the punctuation echo setting,
 // Search+A then P.
diff --git a/chrome/browser/ash/app_list/app_list_test_util.cc b/chrome/browser/ash/app_list/app_list_test_util.cc
index 389ff0a5..0a6ab30 100644
--- a/chrome/browser/ash/app_list/app_list_test_util.cc
+++ b/chrome/browser/ash/app_list/app_list_test_util.cc
@@ -41,13 +41,11 @@
   // - 1 dummy extension (which should not be visible in the launcher)
   // - 2 packaged extension apps
   // - 1 hosted extension app
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("app_list").AppendASCII("Extensions");
-  base::FilePath pref_path =
-      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
   ExtensionServiceInitParams params;
+  ASSERT_TRUE(
+      params.ConfigureByTestDataDirectory(data_dir().AppendASCII("app_list")));
   params.profile_is_guest = guest_mode;
-  InitializeInstalledExtensionService(pref_path, source_install_dir, params);
+  InitializeExtensionService(params);
   service_->Init();
 
   ConfigureWebAppProvider();
diff --git a/chrome/browser/ash/app_list/launcher_search_iph_browsertest.cc b/chrome/browser/ash/app_list/launcher_search_iph_browsertest.cc
index 7fabcdd..251206c 100644
--- a/chrome/browser/ash/app_list/launcher_search_iph_browsertest.cc
+++ b/chrome/browser/ash/app_list/launcher_search_iph_browsertest.cc
@@ -91,9 +91,9 @@
     MixinBasedInProcessBrowserTest::SetUpOnMainThread();
   }
 
-  void TearDownOnMainThread() override {
-    test_api_impl_.SetAssistantEnabled(false);
-  }
+  void TearDownOnMainThread() override { DisableAssistant(); }
+
+  void DisableAssistant() { test_api_impl_.SetAssistantEnabled(false); }
 
  private:
   ash::TestAssistantService test_service_;
@@ -112,7 +112,7 @@
   }
 
  protected:
-  void OpenAppListWithIph() {
+  void OpenAppList() {
     ASSERT_TRUE(!app_list_client_impl_);
     ASSERT_TRUE(!search_box_view_);
 
@@ -126,6 +126,11 @@
         /*wait_for_opening_animation=*/true);
     search_box_view_ = ash::GetSearchBoxView();
     ASSERT_TRUE(search_box_view_);
+  }
+
+  void OpenAppListWithIph() {
+    OpenAppList();
+
     // There is an async call for checking IPH trigger condition.
     ViewWaiter(search_box_view_, ash::LauncherSearchIphView::ViewId::kSelf)
         .Run();
@@ -160,6 +165,7 @@
 IN_PROC_BROWSER_TEST_F(AppListIphBrowserTestWithDemoMode, LauncherSearchIph) {
   OpenAppListWithIph();
   EXPECT_TRUE(IsLauncherSearchIphViewVisible());
+  EXPECT_TRUE(search_box_view()->assistant_button()->GetBackground());
 
   // Dismiss the app list and show it again. IPH won't be shown this time. Note
   // that this is IPH demo mode behavior.
@@ -171,6 +177,9 @@
       /*wait_for_opening_animation=*/false);
 
   EXPECT_FALSE(IsLauncherSearchIphViewVisible());
+  // Launcher search iph installs a background to assistant button. It should be
+  // removed if the iph gets dismissed.
+  EXPECT_FALSE(search_box_view()->assistant_button()->GetBackground());
 }
 
 IN_PROC_BROWSER_TEST_F(AppListIphBrowserTestWithDemoMode,
@@ -224,3 +233,21 @@
             ash::GetAppListBubbleView()->current_page_for_test());
   EXPECT_FALSE(IsLauncherSearchIphViewVisible());
 }
+
+IN_PROC_BROWSER_TEST_F(AppListIphBrowserTestWithDemoMode,
+                       NoIphWithoutAssistant) {
+  // `AssistantTestApiImpl::SetAssistantEnabled` asserts that the value has
+  // taken effect, i.e. we are sure that Assistant gets disabled after this
+  // call.
+  DisableAssistant();
+
+  OpenAppList();
+
+  // There is an async call for IPH to be shown. This test expects that IPH does
+  // NOT get shown. But run `RunUntilIdle` as this test can get failed if we
+  // starts showing an IPH for this case.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
+  EXPECT_FALSE(search_box_view()->assistant_button()->GetBackground());
+}
diff --git a/chrome/browser/ash/app_list/search/system_info/battery_answer_result.cc b/chrome/browser/ash/app_list/search/system_info/battery_answer_result.cc
index edd2cd26..4aa5efe0 100644
--- a/chrome/browser/ash/app_list/search/system_info/battery_answer_result.cc
+++ b/chrome/browser/ash/app_list/search/system_info/battery_answer_result.cc
@@ -25,7 +25,7 @@
     const std::u16string& title,
     const std::u16string& description,
     SystemInfoCategory system_info_category,
-    AnswerCardInfo answer_card_info)
+    const AnswerCardInfo& answer_card_info)
     : SystemInfoAnswerResult(profile,
                              query,
                              url_path,
diff --git a/chrome/browser/ash/app_list/search/system_info/battery_answer_result.h b/chrome/browser/ash/app_list/search/system_info/battery_answer_result.h
index d28c91249..ba212ac5 100644
--- a/chrome/browser/ash/app_list/search/system_info/battery_answer_result.h
+++ b/chrome/browser/ash/app_list/search/system_info/battery_answer_result.h
@@ -22,7 +22,7 @@
                       const std::u16string& title,
                       const std::u16string& description,
                       SystemInfoCategory system_info_category,
-                      ash::SystemInfoAnswerCardData answer_card_info);
+                      const ash::SystemInfoAnswerCardData& answer_card_info);
 
   ~BatteryAnswerResult() override;
 
diff --git a/chrome/browser/ash/app_list/search/system_info/memory_answer_result.cc b/chrome/browser/ash/app_list/search/system_info/memory_answer_result.cc
new file mode 100644
index 0000000..4f4531f7
--- /dev/null
+++ b/chrome/browser/ash/app_list/search/system_info/memory_answer_result.cc
@@ -0,0 +1,70 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/app_list/search/system_info/memory_answer_result.h"
+
+#include "ash/public/cpp/app_list/app_list_types.h"
+#include "ash/public/cpp/power_utils.h"
+#include "base/functional/callback.h"
+#include "chrome/browser/ash/app_list/search/system_info/cpu_data.h"
+#include "chrome/browser/ash/app_list/search/system_info/system_info_answer_result.h"
+#include "chrome/browser/ash/app_list/search/system_info/system_info_util.h"
+
+namespace app_list {
+namespace {
+
+constexpr int kMemoryRefreshIntervalInSeconds = 10;
+using AnswerCardInfo = ::ash::SystemInfoAnswerCardData;
+
+}  // namespace
+
+MemoryAnswerResult::MemoryAnswerResult(
+    Profile* profile,
+    const std::u16string& query,
+    const std::string& url_path,
+    const gfx::ImageSkia& icon,
+    double relevance_score,
+    const std::u16string& title,
+    const std::u16string& description,
+    SystemInfoCategory system_info_category,
+    const AnswerCardInfo& answer_card_info,
+    SystemInfoCardProvider::UpdateMemoryResultCallback callback,
+    std::unique_ptr<base::RepeatingTimer> timer,
+    SystemInfoCardProvider* provider)
+    : SystemInfoAnswerResult(profile,
+                             query,
+                             url_path,
+                             icon,
+                             relevance_score,
+                             title,
+                             description,
+                             system_info_category,
+                             answer_card_info),
+      callback_(std::move(callback)),
+      timer_(std::move(timer)),
+      provider_(provider) {
+  provider_->AddMemoryObserver(this);
+  timer_->Start(FROM_HERE, base::Seconds(kMemoryRefreshIntervalInSeconds),
+                base::BindRepeating(&MemoryAnswerResult::UpdateResult,
+                                    weak_factory_.GetWeakPtr()));
+}
+
+MemoryAnswerResult::~MemoryAnswerResult() {
+  timer_->Stop();
+  if (provider_ && this->IsInObserverList()) {
+    provider_->RemoveMemoryObserver(this);
+  }
+}
+
+void MemoryAnswerResult::OnMemoryUpdated(const double memory_usage_percentage,
+                                         const std::u16string& description) {
+  UpdateTitleAndDetails(u"", description);
+  UpdateBarChartPercentage(memory_usage_percentage);
+}
+
+void MemoryAnswerResult::UpdateResult() {
+  callback_.Run(/*create_result=*/false);
+}
+
+}  // namespace app_list
diff --git a/chrome/browser/ash/app_list/search/system_info/memory_answer_result.h b/chrome/browser/ash/app_list/search/system_info/memory_answer_result.h
new file mode 100644
index 0000000..b30e70c
--- /dev/null
+++ b/chrome/browser/ash/app_list/search/system_info/memory_answer_result.h
@@ -0,0 +1,51 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_SYSTEM_INFO_MEMORY_ANSWER_RESULT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_SYSTEM_INFO_MEMORY_ANSWER_RESULT_H_
+
+#include "ash/public/cpp/app_list/app_list_types.h"
+#include "base/functional/callback.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/ash/app_list/search/system_info/system_info_answer_result.h"
+#include "chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h"
+
+namespace app_list {
+
+class MemoryAnswerResult : public SystemInfoAnswerResult,
+                           public SystemInfoCardProvider::MemoryObserver {
+ public:
+  MemoryAnswerResult(
+      Profile* profile,
+      const std::u16string& query,
+      const std::string& url_path,
+      const gfx::ImageSkia& icon,
+      double relevance_score,
+      const std::u16string& title,
+      const std::u16string& description,
+      SystemInfoCategory system_info_category,
+      const ash::SystemInfoAnswerCardData& answer_card_info,
+      SystemInfoCardProvider::UpdateMemoryResultCallback callback,
+      std::unique_ptr<base::RepeatingTimer> timer,
+      SystemInfoCardProvider* provider);
+
+  ~MemoryAnswerResult() override;
+
+  MemoryAnswerResult(const MemoryAnswerResult& other) = delete;
+  MemoryAnswerResult& operator=(const MemoryAnswerResult& other) = delete;
+
+  void OnMemoryUpdated(const double memory_usage_percentage,
+                       const std::u16string& description) override;
+  void UpdateResult();
+
+ private:
+  SystemInfoCardProvider::UpdateMemoryResultCallback callback_;
+  std::unique_ptr<base::RepeatingTimer> timer_;
+  SystemInfoCardProvider* provider_;
+  base::WeakPtrFactory<MemoryAnswerResult> weak_factory_{this};
+};
+
+}  // namespace app_list
+
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_SYSTEM_INFO_MEMORY_ANSWER_RESULT_H_
diff --git a/chrome/browser/ash/app_list/search/system_info/system_info_answer_result.cc b/chrome/browser/ash/app_list/search/system_info/system_info_answer_result.cc
index ead2040..cb46d43a 100644
--- a/chrome/browser/ash/app_list/search/system_info/system_info_answer_result.cc
+++ b/chrome/browser/ash/app_list/search/system_info/system_info_answer_result.cc
@@ -20,6 +20,7 @@
 namespace {
 
 constexpr char kOsSettingsResultPrefix[] = "os-settings://";
+using AnswerCardInfo = ::ash::SystemInfoAnswerCardData;
 
 }  // namespace
 
@@ -32,7 +33,7 @@
     const std::u16string& title,
     const std::u16string& description,
     SystemInfoCategory system_info_category,
-    ash::SystemInfoAnswerCardData answer_card_info)
+    const AnswerCardInfo& answer_card_info)
     : system_info_category_(system_info_category),
       profile_(profile),
       query_(query),
@@ -90,4 +91,10 @@
   }
 }
 
+void SystemInfoAnswerResult::UpdateBarChartPercentage(
+    const double bar_chart_percentage) {
+  AnswerCardInfo answer_card_info(bar_chart_percentage);
+  SetSystemInfoAnswerCardData(answer_card_info);
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ash/app_list/search/system_info/system_info_answer_result.h b/chrome/browser/ash/app_list/search/system_info/system_info_answer_result.h
index 95549c0..dbde64f 100644
--- a/chrome/browser/ash/app_list/search/system_info/system_info_answer_result.h
+++ b/chrome/browser/ash/app_list/search/system_info/system_info_answer_result.h
@@ -24,7 +24,7 @@
                          const std::u16string& title,
                          const std::u16string& description,
                          SystemInfoCategory system_info_category,
-                         ash::SystemInfoAnswerCardData answer_card_info);
+                         const ash::SystemInfoAnswerCardData& answer_card_info);
   SystemInfoAnswerResult(const SystemInfoAnswerResult&) = delete;
   SystemInfoAnswerResult& operator=(const SystemInfoAnswerResult&) = delete;
 
@@ -37,6 +37,8 @@
   void UpdateTitleAndDetails(const std::u16string& title,
                              const std::u16string& description);
 
+  void UpdateBarChartPercentage(const double bar_chart_percentage);
+
  private:
   SystemInfoCategory const system_info_category_;
   Profile* const profile_;
diff --git a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc
index b813037..a2b905f 100644
--- a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc
+++ b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/ash/app_list/search/system_info/cpu_answer_result.h"
 #include "chrome/browser/ash/app_list/search/system_info/cpu_data.h"
 #include "chrome/browser/ash/app_list/search/system_info/cpu_usage_data.h"
+#include "chrome/browser/ash/app_list/search/system_info/memory_answer_result.h"
 #include "chrome/browser/ash/app_list/search/system_info/system_info_answer_result.h"
 #include "chrome/browser/ash/app_list/search/system_info/system_info_util.h"
 #include "chrome/browser/ash/app_list/vector_icons/vector_icons.h"
@@ -81,6 +82,7 @@
                      weak_factory_.GetWeakPtr()));
   StartObservingCalculators();
   cpu_usage_timer_ = std::make_unique<base::RepeatingTimer>();
+  memory_timer_ = std::make_unique<base::RepeatingTimer>();
 
   // TODO(b/261867385): We manually load the icon from the local codebase as
   // the icon load from proxy is flaky. When the flakiness if solved, we can
@@ -110,7 +112,7 @@
     relevance_ = max_relevance;
     switch (most_relevant_keyword_input->GetInputType()) {
       case SystemInfoInputType::kMemory:
-        UpdateMemoryUsage();
+        UpdateMemoryUsage(/*create_result=*/true);
         break;
       case SystemInfoInputType::kCPU:
         UpdateCpuUsage(/*create_result=*/true);
@@ -176,7 +178,8 @@
   probe_service_.reset();
 }
 
-void SystemInfoCardProvider::OnMemoryUsageUpdated(TelemetryInfoPtr info_ptr) {
+void SystemInfoCardProvider::OnMemoryUsageUpdated(bool create_result,
+                                                  TelemetryInfoPtr info_ptr) {
   if (info_ptr.is_null()) {
     LOG(ERROR) << "Null response from croshealthd::ProbeTelemetryInfo.";
     return;
@@ -203,23 +206,34 @@
       l10n_util::GetStringFUTF16(IDS_ASH_MEMORY_USAGE_IN_LAUNCHER_DESCRIPTION,
                                  available_memory_gb, total_memory_gb);
 
-  AnswerCardInfo answer_card_info(memory_usage_percentage);
-  SearchProvider::Results new_results;
-  new_results.emplace_back(std::make_unique<SystemInfoAnswerResult>(
-      profile_, last_query_, /*url_path=*/"", diagnostics_icon_, relevance_,
-      /*title=*/u"", description,
-      SystemInfoAnswerResult::SystemInfoCategory::kDiagnostics,
-      answer_card_info));
-  SwapResults(&new_results);
+  if (create_result) {
+    AnswerCardInfo answer_card_info(memory_usage_percentage);
+    SearchProvider::Results new_results;
+    DCHECK(memory_timer_);
+    new_results.emplace_back(std::make_unique<MemoryAnswerResult>(
+        profile_, last_query_, /*url_path=*/"", diagnostics_icon_, relevance_,
+        /*title=*/u"", description,
+        SystemInfoAnswerResult::SystemInfoCategory::kDiagnostics,
+        answer_card_info,
+        base::BindRepeating(&SystemInfoCardProvider::UpdateMemoryUsage,
+                            weak_factory_.GetWeakPtr()),
+        std::move(memory_timer_), this));
+    SwapResults(&new_results);
+    memory_timer_ = std::make_unique<base::RepeatingTimer>();
+  } else {
+    for (auto& observer : memory_observers_) {
+      observer.OnMemoryUpdated(memory_usage_percentage, description);
+    }
+  }
 }
 
-void SystemInfoCardProvider::UpdateMemoryUsage() {
+void SystemInfoCardProvider::UpdateMemoryUsage(bool create_result) {
   BindCrosHealthdProbeServiceIfNecessary();
 
   probe_service_->ProbeTelemetryInfo(
       {ProbeCategories::kMemory},
       base::BindOnce(&SystemInfoCardProvider::OnMemoryUsageUpdated,
-                     weak_factory_.GetWeakPtr()));
+                     weak_factory_.GetWeakPtr(), create_result));
 }
 
 void SystemInfoCardProvider::OnCpuUsageUpdated(bool create_result,
@@ -544,4 +558,17 @@
   cpu_usage_timer_ = std::move(timer);
 }
 
+void SystemInfoCardProvider::AddMemoryObserver(MemoryObserver* observer) {
+  memory_observers_.AddObserver(observer);
+}
+
+void SystemInfoCardProvider::RemoveMemoryObserver(MemoryObserver* observer) {
+  memory_observers_.RemoveObserver(observer);
+}
+
+void SystemInfoCardProvider::SetMemoryTimerForTesting(
+    std::unique_ptr<base::RepeatingTimer> timer) {
+  memory_timer_ = std::move(timer);
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h
index 70771be..3e34966 100644
--- a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h
+++ b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h
@@ -36,6 +36,8 @@
                                public ash::settings::SizeCalculator::Observer {
  public:
   using UpdateCpuResultCallback = base::RepeatingCallback<void(bool)>;
+  using UpdateMemoryResultCallback = base::RepeatingCallback<void(bool)>;
+
   // Implemented by clients that wish to be updated periodically about the
   // cpu usage of the device.
   class CpuDataObserver : public base::CheckedObserver {
@@ -44,6 +46,14 @@
                                   const std::u16string& description) = 0;
   };
 
+  // Implemented by clients that wish to be updated periodically about the
+  // cpu usage of the device.
+  class MemoryObserver : public base::CheckedObserver {
+   public:
+    virtual void OnMemoryUpdated(const double memory_usage_percentage,
+                                 const std::u16string& description) = 0;
+  };
+
   explicit SystemInfoCardProvider(Profile* profile);
   ~SystemInfoCardProvider() override;
 
@@ -64,7 +74,12 @@
   virtual void AddCpuDataObserver(CpuDataObserver* observer);
   virtual void RemoveCpuDataObserver(CpuDataObserver* observer);
 
+  // Adds and removes the Memory observer.
+  virtual void AddMemoryObserver(MemoryObserver* observer);
+  virtual void RemoveMemoryObserver(MemoryObserver* observer);
+
   void SetCpuUsageTimerForTesting(std::unique_ptr<base::RepeatingTimer> timer);
+  void SetMemoryTimerForTesting(std::unique_ptr<base::RepeatingTimer> timer);
 
  private:
   void BindCrosHealthdProbeServiceIfNecessary();
@@ -72,8 +87,9 @@
   double CalculateRelevance(const std::u16string& query,
                             const std::u16string& title);
 
-  void UpdateMemoryUsage();
+  void UpdateMemoryUsage(bool create_result);
   void OnMemoryUsageUpdated(
+      bool create_result,
       ash::cros_healthd::mojom::TelemetryInfoPtr info_ptr);
 
   void UpdateCpuUsage(bool create_result);
@@ -126,8 +142,9 @@
   gfx::ImageSkia diagnostics_icon_;
   std::vector<SystemInfoKeywordInput> keywords_;
   std::unique_ptr<base::RepeatingTimer> cpu_usage_timer_;
-
+  std::unique_ptr<base::RepeatingTimer> memory_timer_;
   base::ObserverList<SystemInfoCardProvider::CpuDataObserver> cpu_observers_;
+  base::ObserverList<SystemInfoCardProvider::MemoryObserver> memory_observers_;
 
   base::WeakPtrFactory<SystemInfoCardProvider> weak_factory_{this};
 };
diff --git a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider_unittest.cc b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider_unittest.cc
index bc74bac..43246a2 100644
--- a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider_unittest.cc
@@ -495,6 +495,11 @@
 }
 
 TEST_F(SystemInfoCardProviderTest, Memory) {
+  // Setup Timer
+  auto timer = std::make_unique<base::MockRepeatingTimer>();
+  auto* timer_ptr = timer.get();
+  provider_->SetMemoryTimerForTesting(std::move(timer));
+
   const uint32_t total_memory_kib = 8000000;
   const uint32_t free_memory_kib = 2000000;
   const uint32_t available_memory_kib = 4000000;
@@ -528,6 +533,31 @@
   EXPECT_EQ(details.GetType(), ash::SearchResultTextItemType::kString);
   EXPECT_EQ(details.GetText(), u"3.8 GB of 7.6 GB available");
   EXPECT_TRUE(details.GetTextTags().empty());
+
+  const uint32_t total_memory_kib_2 = 8000000;
+  const uint32_t free_memory_kib_2 = 2000000;
+  const uint32_t available_memory_kib_2 = 2000000;
+
+  SetCrosHealthdMemoryUsageResponse(total_memory_kib_2, free_memory_kib_2,
+                                    available_memory_kib_2);
+
+  timer_ptr->Fire();
+  Wait();
+
+  EXPECT_EQ(title.GetText(), u"");
+  EXPECT_EQ(details.GetText(), u"1.9 GB of 7.6 GB available");
+  EXPECT_EQ(results()[0]->system_info_answer_card_data()->bar_chart_percentage,
+            75);
+
+  StartSearch(u"memory usage");
+  Wait();
+
+  ASSERT_FALSE(results().empty());
+  EXPECT_EQ(results().size(), 1u);
+  const auto& details2 = results()[0]->details_text_vector()[0];
+  EXPECT_EQ(details2.GetText(), u"1.9 GB of 7.6 GB available");
+  EXPECT_EQ(results()[0]->system_info_answer_card_data()->bar_chart_percentage,
+            75);
 }
 
 TEST_F(SystemInfoCardProviderTest, MemoryProbeError) {
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc
index 7e215100..ad60b1d5 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h"
 
 #include <memory>
+#include <mutex>
 
 #include "ash/public/cpp/window_properties.h"
 #include "base/functional/bind.h"
@@ -18,6 +19,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_task.h"
 #include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h"
 #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
@@ -26,6 +28,8 @@
 #include "components/account_id/account_id.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "ui/aura/window.h"
 #include "ui/base/page_transition_types.h"
 #include "url/origin.h"
@@ -90,14 +94,14 @@
 
   observers_.NotifyAppInstalling();
   DCHECK(!is_installed_);
-  install_task_ = std::make_unique<web_app::WebAppInstallTask>(
-      profile_,
-      /*install_finalizer=*/nullptr, data_retriever_factory_.Run(),
-      /*registrar=*/nullptr, webapps::WebappInstallSource::MANAGEMENT_API);
-  install_task_->LoadAndRetrieveWebAppInstallInfoWithIcons(
+
+  web_contents_for_app_info_ =
+      web_app::WebAppInstallTask::CreateWebContents(profile_);
+  url_loader_->LoadUrl(
       WebKioskAppManager::Get()->GetAppByAccountId(account_id_)->install_url(),
-      url_loader_.get(),
-      base::BindOnce(&WebKioskAppLauncher::OnAppDataObtained,
+      web_contents_for_app_info_.get(),
+      web_app::WebAppUrlLoader::UrlComparison::kIgnoreQueryParamsAndRef,
+      base::BindOnce(&WebKioskAppLauncher::OnUrlLoaded,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
@@ -108,8 +112,49 @@
   return app;
 }
 
+void WebKioskAppLauncher::OnUrlLoaded(web_app::WebAppUrlLoader::Result result) {
+  if (web_contents_for_app_info_->IsBeingDestroyed() ||
+      profile_->ShutdownStarted()) {
+    OnAppDataObtained(webapps::InstallResultCode::kWebContentsDestroyed);
+    return;
+  }
+
+  if (result == web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded) {
+    OnAppDataObtained(webapps::InstallResultCode::kInstallURLRedirected);
+    return;
+  }
+
+  if (result == web_app::WebAppUrlLoader::Result::kFailedPageTookTooLong) {
+    OnAppDataObtained(webapps::InstallResultCode::kInstallURLLoadTimeOut);
+    return;
+  }
+
+  if (result != web_app::WebAppUrlLoader::Result::kUrlLoaded) {
+    OnAppDataObtained(webapps::InstallResultCode::kInstallURLLoadFailed);
+    return;
+  }
+
+  data_retriever_ = data_retriever_factory_.Run();
+
+  data_retriever_->GetWebAppInstallInfo(
+      web_contents_for_app_info_.get(),
+      base::BindOnce([](std::unique_ptr<WebAppInstallInfo> install_info) {
+        absl::variant<WebAppInstallInfo, webapps::InstallResultCode> result;
+        if (install_info) {
+          result = std::move(*install_info);
+        } else {
+          result = webapps::InstallResultCode::kGetWebAppInstallInfoFailed;
+        }
+        return result;
+      })
+          .Then(base::BindOnce(&WebKioskAppLauncher::OnAppDataObtained,
+                               weak_ptr_factory_.GetWeakPtr())));
+}
+
 void WebKioskAppLauncher::OnAppDataObtained(
-    web_app::WebAppInstallTask::WebAppInstallInfoOrErrorCode info) {
+    absl::variant<WebAppInstallInfo, webapps::InstallResultCode> info) {
+  web_contents_for_app_info_.reset();
+  data_retriever_.reset();
   if (absl::holds_alternative<webapps::InstallResultCode>(info)) {
     RecordKioskWebAppInstallError(absl::get<webapps::InstallResultCode>(info));
     // Notify about failed installation, let the controller decide what to do.
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h
index 4ebeccd..3cf049c0 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h
@@ -13,14 +13,16 @@
 #include "chrome/browser/ash/app_mode/kiosk_app_launcher.h"
 #include "chrome/browser/ash/crosapi/browser_manager.h"
 #include "chrome/browser/profiles/profile_observer.h"
-#include "chrome/browser/web_applications/web_app_install_task.h"
 #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
 #include "components/account_id/account_id.h"
 #include "components/exo/wm_helper.h"
+#include "components/webapps/browser/install_result_code.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 
 class Browser;
 class BrowserWindow;
 class Profile;
+struct WebAppInstallInfo;
 
 namespace web_app {
 class WebAppUrlLoader;
@@ -75,10 +77,12 @@
   // ProfileObserver:
   void OnProfileWillBeDestroyed(Profile* profile) override;
 
-  // Callback method triggered after web application and its icon are obtained
-  // from `WebKioskAppManager`.
+  void OnUrlLoaded(web_app::WebAppUrlLoader::Result result);
+
+  // Callback method triggered after web application and its icon are
+  // obtained from `WebKioskAppManager`.
   void OnAppDataObtained(
-      web_app::WebAppInstallTask::WebAppInstallInfoOrErrorCode);
+      absl::variant<WebAppInstallInfo, webapps::InstallResultCode> result);
 
   // Callback method triggered after the lacros-chrome window is created.
   void OnLacrosWindowCreated(crosapi::mojom::CreationResult result);
@@ -101,10 +105,12 @@
   KioskAppLauncher::ObserverList observers_;
   Browser* browser_ = nullptr;  // Browser instance that runs the web kiosk app.
 
-  std::unique_ptr<web_app::WebAppInstallTask>
-      install_task_;  // task that is used to install the app.
-  std::unique_ptr<web_app::WebAppUrlLoader>
-      url_loader_;  // Loads the app to be installed.
+  // Web contents used for loading app info.
+  std::unique_ptr<content::WebContents> web_contents_for_app_info_;
+  // URL loader that loads the app site in the web contents.
+  std::unique_ptr<web_app::WebAppUrlLoader> url_loader_;
+  // Retrieves the app info from the page's metadata.
+  std::unique_ptr<web_app::WebAppDataRetriever> data_retriever_;
 
   // Produces retrievers used to obtain app data during installation.
   base::RepeatingCallback<std::unique_ptr<web_app::WebAppDataRetriever>()>
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc
index af9be10..14e9b6e 100644
--- a/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc
@@ -140,8 +140,7 @@
       1 << views::CAPTION_BUTTON_ICON_MINIMIZE |
       1 << views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE |
       1 << views::CAPTION_BUTTON_ICON_CLOSE |
-      1 << views::CAPTION_BUTTON_ICON_BACK |
-      1 << views::CAPTION_BUTTON_ICON_MENU;
+      1 << views::CAPTION_BUTTON_ICON_BACK;
   shell_surface->SetFrameButtons(kAllButtonMask, kAllButtonMask);
   shell_surface->OnSetFrameColors(theme_color, theme_color);
 
diff --git a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc
index b1cce7f4..44b6d1c 100644
--- a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc
+++ b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc
@@ -9,6 +9,7 @@
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/mojom/app.mojom.h"
 #include "ash/components/arc/session/connection_holder.h"
+#include "ash/public/cpp/app_types_util.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/shell.h"
 #include "ash/wm/window_util.h"
@@ -145,6 +146,175 @@
 ArcInputOverlayManager::~ArcInputOverlayManager() = default;
 
 // static
+void ArcInputOverlayManager::EnsureFactoryBuilt() {
+  ArcInputOverlayManagerFactory::GetInstance();
+}
+
+void ArcInputOverlayManager::OnWindowInitialized(aura::Window* new_window) {
+  // |aura::client::kAppType| property is set in
+  // |AppServiceAppWindowShelfController::OnWindowInitialized()|.
+  // |AppServiceAppWindowShelfController::OnWindowInitialized()| is called
+  // before |ArcInputOverlayManager::OnWindowInitialized()|, so we can filter
+  // non-ARC apps here.
+  if (!new_window || !ash::IsArcWindow(new_window) ||
+      new_window != new_window->GetToplevelWindow() ||
+      window_observations_.IsObservingSource(new_window)) {
+    return;
+  }
+
+  window_observations_.AddObservation(new_window);
+}
+
+void ArcInputOverlayManager::OnWindowPropertyChanged(aura::Window* window,
+                                                     const void* key,
+                                                     intptr_t old) {
+  // There are two cases when launching an app.
+  // 1) Launch from Launcher: Receive {ash::kArcPackageNameKey, package_name}.
+  // 2) Restore the app: Receive {ash::kArcPackageNameKey, package_name} and
+  // {app_restore::kRealArcTaskWindow, true}. When |ash::kArcPackageNameKey| is
+  // changed, the ghost window overlay is not destroyed. The ghost window
+  // overlay is destroyed right before property
+  // {app_restore::kRealArcTaskWindow} is set.
+  if (!window || (key != ash::kArcPackageNameKey &&
+                  key != app_restore::kRealArcTaskWindow)) {
+    return;
+  }
+
+  DCHECK_EQ(window, window->GetToplevelWindow());
+  if (input_overlay_enabled_windows_.contains(window) ||
+      IsGhostWindowLoading(window) || loading_data_windows_.contains(window)) {
+    return;
+  }
+  std::string* package_name = window->GetProperty(ash::kArcPackageNameKey);
+  if (!package_name || package_name->empty()) {
+    return;
+  }
+
+  // Start to read data.
+  auto touch_injector = std::make_unique<TouchInjector>(
+      window, *package_name,
+      base::BindRepeating(&ArcInputOverlayManager::OnSaveProtoFile,
+                          weak_ptr_factory_.GetWeakPtr()));
+  loading_data_windows_.insert(window);
+  task_runner_->PostTaskAndReplyWithResult(
+      FROM_HERE,
+      base::BindOnce(&ArcInputOverlayManager::ReadDefaultData,
+                     std::move(touch_injector)),
+      base::BindOnce(&ArcInputOverlayManager::OnFinishReadDefaultData,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ArcInputOverlayManager::OnWindowDestroying(aura::Window* window) {
+  UnRegisterWindow(window);
+  input_overlay_enabled_windows_.erase(window);
+  loading_data_windows_.erase(window);
+  RemoveWindowObservation(window);
+}
+
+void ArcInputOverlayManager::OnWindowAddedToRootWindow(aura::Window* window) {
+  if (!window ||
+      ash::window_util::GetFocusedWindow()->GetToplevelWindow() != window) {
+    return;
+  }
+  RegisterWindow(window);
+}
+
+void ArcInputOverlayManager::OnWindowRemovingFromRootWindow(
+    aura::Window* window,
+    aura::Window* new_root) {
+  if (!window) {
+    return;
+  }
+  // There might be child window surface removing, we don't unregister window
+  // until the top_level_window is removed from the root.
+  UnRegisterWindow(window);
+}
+
+void ArcInputOverlayManager::Shutdown() {
+  UnRegisterWindow(registered_top_level_window_);
+  window_observations_.RemoveAllObservations();
+  if (ash::Shell::HasInstance()) {
+    if (ash::Shell::GetPrimaryRootWindow()) {
+      aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow())
+          ->RemoveObserver(this);
+    }
+
+    if (ash::Shell::Get()->tablet_mode_controller()) {
+      ash::Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
+    }
+
+    if (ash::Shell::Get()->display_manager()) {
+      ash::Shell::Get()->display_manager()->RemoveObserver(this);
+    }
+  }
+  if (aura::Env::HasInstance()) {
+    env_observation_.Reset();
+  }
+}
+
+void ArcInputOverlayManager::OnWindowFocused(aura::Window* gained_focus,
+                                             aura::Window* lost_focus) {
+  if (ash::Shell::Get()->tablet_mode_controller()->InTabletMode()) {
+    return;
+  }
+
+  aura::Window* lost_focus_top_level_window = nullptr;
+  aura::Window* gained_focus_top_level_window = nullptr;
+
+  if (lost_focus) {
+    lost_focus_top_level_window = lost_focus->GetToplevelWindow();
+  }
+
+  if (gained_focus) {
+    gained_focus_top_level_window = gained_focus->GetToplevelWindow();
+  }
+
+  if (lost_focus_top_level_window == gained_focus_top_level_window) {
+    return;
+  }
+
+  UnRegisterWindow(lost_focus_top_level_window);
+  RegisterWindow(gained_focus_top_level_window);
+}
+
+void ArcInputOverlayManager::OnTabletModeStarting() {
+  UnRegisterWindow(registered_top_level_window_);
+}
+
+void ArcInputOverlayManager::OnTabletModeEnded() {
+  RegisterFocusedWindow();
+}
+
+void ArcInputOverlayManager::OnDisplayMetricsChanged(
+    const display::Display& display,
+    uint32_t metrics) {
+  if (!registered_top_level_window_) {
+    return;
+  }
+
+  auto it = input_overlay_enabled_windows_.find(registered_top_level_window_);
+  if (it == input_overlay_enabled_windows_.end()) {
+    return;
+  }
+
+  it->second->UpdatePositionsForRegister();
+}
+
+void ArcInputOverlayManager::ResetForPendingTouchInjector(
+    std::unique_ptr<TouchInjector> touch_injector) {
+  auto* window = touch_injector->window();
+  loading_data_windows_.erase(window);
+  touch_injector.reset();
+  RemoveWindowObservation(window);
+}
+
+void ArcInputOverlayManager::RemoveWindowObservation(aura::Window* window) {
+  if (window_observations_.IsObservingSource(window)) {
+    window_observations_.RemoveObservation(window);
+  }
+}
+
+// static
 std::unique_ptr<TouchInjector> ArcInputOverlayManager::ReadDefaultData(
     std::unique_ptr<TouchInjector> touch_injector) {
   DCHECK(touch_injector);
@@ -191,6 +361,7 @@
     DCHECK(arc::IsArcAllowedForProfile(profile));
     connection_ = ArcAppListPrefs::Get(profile)->app_connection_holder();
     if (!connection_) {
+      ResetForPendingTouchInjector(std::move(touch_injector));
       LOG(ERROR) << "Unable to get access to GetAppCategory for nullptr "
                     "|connection_|.";
       return;
@@ -198,6 +369,7 @@
     auto* app_instance =
         ARC_GET_INSTANCE_FOR_METHOD(connection_, GetAppCategory);
     if (!app_instance) {
+      ResetForPendingTouchInjector(std::move(touch_injector));
       return;
     }
 
@@ -388,163 +560,4 @@
   display_overlay_controller_.reset();
 }
 
-void ArcInputOverlayManager::OnWindowInitialized(aura::Window* new_window) {
-  if (window_observations_.IsObservingSource(new_window)) {
-    return;
-  }
-
-  window_observations_.AddObservation(new_window);
-}
-
-void ArcInputOverlayManager::OnWindowPropertyChanged(aura::Window* window,
-                                                     const void* key,
-                                                     intptr_t old) {
-  // There are two cases when launching an app.
-  // 1) Launch from Launcher: Receive {ash::kArcPackageNameKey, package_name}.
-  // 2) Restore the app: Receive {ash::kArcPackageNameKey, package_name} and
-  // {app_restore::kRealArcTaskWindow, true}. When |ash::kArcPackageNameKey| is
-  // changed, the ghost window overlay is not destroyed. The ghost window
-  // overlay is destroyed right before property
-  // {app_restore::kRealArcTaskWindow} is set.
-  if (!window || (key != ash::kArcPackageNameKey &&
-                  key != app_restore::kRealArcTaskWindow)) {
-    return;
-  }
-
-  auto* top_level_window = window->GetToplevelWindow();
-  if (!top_level_window ||
-      input_overlay_enabled_windows_.contains(top_level_window) ||
-      IsGhostWindowLoading(top_level_window) ||
-      loading_data_windows_.contains(top_level_window)) {
-    return;
-  }
-  std::string* package_name =
-      top_level_window->GetProperty(ash::kArcPackageNameKey);
-  if (!package_name || package_name->empty()) {
-    return;
-  }
-
-  // Start to read data.
-  auto touch_injector = std::make_unique<TouchInjector>(
-      top_level_window, *package_name,
-      base::BindRepeating(&ArcInputOverlayManager::OnSaveProtoFile,
-                          weak_ptr_factory_.GetWeakPtr()));
-  loading_data_windows_.insert(top_level_window);
-  task_runner_->PostTaskAndReplyWithResult(
-      FROM_HERE,
-      base::BindOnce(&ArcInputOverlayManager::ReadDefaultData,
-                     std::move(touch_injector)),
-      base::BindOnce(&ArcInputOverlayManager::OnFinishReadDefaultData,
-                     weak_ptr_factory_.GetWeakPtr()));
-}
-
-void ArcInputOverlayManager::OnWindowDestroying(aura::Window* window) {
-  if (window_observations_.IsObservingSource(window)) {
-    window_observations_.RemoveObservation(window);
-  }
-  UnRegisterWindow(window);
-  input_overlay_enabled_windows_.erase(window);
-  loading_data_windows_.erase(window);
-}
-
-void ArcInputOverlayManager::OnWindowAddedToRootWindow(aura::Window* window) {
-  if (!window ||
-      ash::window_util::GetFocusedWindow()->GetToplevelWindow() != window) {
-    return;
-  }
-  RegisterWindow(window);
-}
-
-void ArcInputOverlayManager::OnWindowRemovingFromRootWindow(
-    aura::Window* window,
-    aura::Window* new_root) {
-  if (!window) {
-    return;
-  }
-  // There might be child window surface removing, we don't unregister window
-  // until the top_level_window is removed from the root.
-  UnRegisterWindow(window);
-}
-
-void ArcInputOverlayManager::Shutdown() {
-  UnRegisterWindow(registered_top_level_window_);
-  window_observations_.RemoveAllObservations();
-  if (ash::Shell::HasInstance()) {
-    if (ash::Shell::GetPrimaryRootWindow()) {
-      aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow())
-          ->RemoveObserver(this);
-    }
-
-    if (ash::Shell::Get()->tablet_mode_controller()) {
-      ash::Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
-    }
-
-    if (ash::Shell::Get()->display_manager()) {
-      ash::Shell::Get()->display_manager()->RemoveObserver(this);
-    }
-  }
-  if (aura::Env::HasInstance()) {
-    env_observation_.Reset();
-  }
-}
-
-void ArcInputOverlayManager::OnWindowFocused(aura::Window* gained_focus,
-                                             aura::Window* lost_focus) {
-  if (ash::Shell::Get()->tablet_mode_controller()->InTabletMode()) {
-    return;
-  }
-
-  aura::Window* lost_focus_top_level_window = nullptr;
-  aura::Window* gained_focus_top_level_window = nullptr;
-
-  if (lost_focus) {
-    lost_focus_top_level_window = lost_focus->GetToplevelWindow();
-  }
-
-  if (gained_focus) {
-    gained_focus_top_level_window = gained_focus->GetToplevelWindow();
-  }
-
-  if (lost_focus_top_level_window == gained_focus_top_level_window) {
-    return;
-  }
-
-  UnRegisterWindow(lost_focus_top_level_window);
-  RegisterWindow(gained_focus_top_level_window);
-}
-
-void ArcInputOverlayManager::OnTabletModeStarting() {
-  UnRegisterWindow(registered_top_level_window_);
-}
-
-void ArcInputOverlayManager::OnTabletModeEnded() {
-  RegisterFocusedWindow();
-}
-
-void ArcInputOverlayManager::OnDisplayMetricsChanged(
-    const display::Display& display,
-    uint32_t metrics) {
-  if (!registered_top_level_window_) {
-    return;
-  }
-
-  auto it = input_overlay_enabled_windows_.find(registered_top_level_window_);
-  if (it == input_overlay_enabled_windows_.end()) {
-    return;
-  }
-
-  it->second->UpdatePositionsForRegister();
-}
-
-void ArcInputOverlayManager::ResetForPendingTouchInjector(
-    std::unique_ptr<TouchInjector> touch_injector) {
-  loading_data_windows_.erase(touch_injector->window());
-  touch_injector.reset();
-}
-
-// static
-void ArcInputOverlayManager::EnsureFactoryBuilt() {
-  ArcInputOverlayManagerFactory::GetInstance();
-}
-
 }  // namespace arc::input_overlay
diff --git a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.h b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.h
index cf55894..57f2927 100644
--- a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.h
+++ b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.h
@@ -56,6 +56,8 @@
   ArcInputOverlayManager& operator=(const ArcInputOverlayManager&) = delete;
   ~ArcInputOverlayManager() override;
 
+  static void EnsureFactoryBuilt();
+
   // aura::EnvObserver:
   void OnWindowInitialized(aura::Window* new_window) override;
 
@@ -83,14 +85,14 @@
   void OnDisplayMetricsChanged(const display::Display& display,
                                uint32_t metrics) override;
 
-  static void EnsureFactoryBuilt();
-
  private:
   friend class ArcInputOverlayManagerTest;
   friend class TestArcInputOverlayManager;
 
   class InputMethodObserver;
 
+  // Remove |window| from observation list.
+  void RemoveWindowObservation(aura::Window* window);
   // Read default data.
   static std::unique_ptr<TouchInjector> ReadDefaultData(
       std::unique_ptr<TouchInjector> touch_injector);
diff --git a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager_unittest.cc b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager_unittest.cc
index 99ff46e..c89fe92 100644
--- a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager_unittest.cc
+++ b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager_unittest.cc
@@ -129,6 +129,11 @@
         ->TriggerWidgetBoundsChangedForTesting();
   }
 
+  bool IsObserving(aura::Window* window) const {
+    return arc_test_input_overlay_manager_->window_observations_
+        .IsObservingSource(window);
+  }
+
  protected:
   std::unique_ptr<ArcInputOverlayManager> arc_test_input_overlay_manager_;
 
@@ -155,22 +160,25 @@
   auto arc_window = CreateArcWindowSyncAndWait(
       task_environment(), ash::Shell::GetPrimaryRootWindow(),
       gfx::Rect(10, 10, 100, 100), kEnabledPackageName);
-  EXPECT_TRUE(IsInputOverlayEnabled(arc_window->GetNativeWindow()));
+  auto* arc_window_ptr = arc_window->GetNativeWindow();
+  EXPECT_TRUE(IsObserving(arc_window_ptr));
+  EXPECT_TRUE(IsInputOverlayEnabled(arc_window_ptr));
   // Input overlay registers the window after reading the data when the window
   // is still focused. In the test, the arc_window is considered as focused now.
   EXPECT_TRUE(GetRegisteredWindow());
-  focus_client->FocusWindow(arc_window->GetNativeWindow());
+  focus_client->FocusWindow(arc_window_ptr);
   EXPECT_TRUE(GetRegisteredWindow());
 
   // Test app with input overlay data when window is destroyed.
-  auto* arc_window_ptr = arc_window->GetNativeWindow();
   arc_window.reset();
+  EXPECT_FALSE(IsObserving(arc_window_ptr));
   EXPECT_FALSE(IsInputOverlayEnabled(arc_window_ptr));
 
   // Test app without input overlay data.
   auto arc_window_no_data = CreateArcWindowSyncAndWait(
       task_environment(), ash::Shell::GetPrimaryRootWindow(),
       gfx::Rect(10, 10, 100, 100), kRandomPackageName);
+  EXPECT_FALSE(IsObserving(arc_window_ptr));
   EXPECT_FALSE(IsInputOverlayEnabled(arc_window_no_data->GetNativeWindow()));
 }
 
diff --git a/chrome/browser/ash/arc/input_overlay/test/test_utils.cc b/chrome/browser/ash/arc/input_overlay/test/test_utils.cc
index fd7dc8f2..fc7b5f32 100644
--- a/chrome/browser/ash/arc/input_overlay/test/test_utils.cc
+++ b/chrome/browser/ash/arc/input_overlay/test/test_utils.cc
@@ -20,13 +20,16 @@
   params.bounds = bounds;
   params.context = root_window;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  // |aura::client::kAppType| property should be assigned before widget init.
+  // It simulates the situation that
+  // |AppServiceAppWindowShelfController::OnWindowInitialized()| is called
+  // before |ArcInputOverlayManager::OnWindowInitialized()|;
+  params.init_properties_container.SetProperty(
+      aura::client::kAppType, static_cast<int>(ash::AppType::ARC_APP));
   auto widget = std::make_unique<views::Widget>();
   widget->Init(std::move(params));
   widget->widget_delegate()->SetCanResize(true);
-  widget->SetBounds(bounds);
   widget->GetNativeWindow()->SetProperty(ash::kAppIDKey, std::string("app_id"));
-  widget->GetNativeWindow()->SetProperty(
-      aura::client::kAppType, static_cast<int>(ash::AppType::ARC_APP));
   widget->GetNativeWindow()->SetProperty(ash::kArcPackageNameKey, package_name);
   widget->Show();
   widget->Activate();
diff --git a/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc b/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc
index 0e1f4fa..e30e0049 100644
--- a/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc
@@ -88,7 +88,7 @@
     EXPECT_LT(base::TimeDelta(), forward_by);
     task_environment()->AdvanceClock(forward_by);
 
-    ExtensionServiceInitParams params = CreateDefaultInitParams();
+    ExtensionServiceInitParams params;
     params.profile_is_supervised = IsFamilyLink();
     InitializeExtensionService(params);
 
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index a4879c3..9f56e43 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -390,6 +390,8 @@
     "test_controller_ash.h",
     "test_crosapi_dependency_registry.cc",
     "test_crosapi_dependency_registry.h",
+    "test_crosapi_environment.cc",
+    "test_crosapi_environment.h",
   ]
   allow_circular_includes_from = [ "//chrome/test:test_support" ]
   deps = [
diff --git a/chrome/browser/ash/crosapi/test_crosapi_environment.cc b/chrome/browser/ash/crosapi/test_crosapi_environment.cc
new file mode 100644
index 0000000..f7c5c68
--- /dev/null
+++ b/chrome/browser/ash/crosapi/test_crosapi_environment.cc
@@ -0,0 +1,42 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/crosapi/test_crosapi_environment.h"
+
+#include "base/check.h"
+#include "chrome/browser/ash/crosapi/crosapi_manager.h"
+#include "chrome/browser/ash/crosapi/idle_service_ash.h"
+#include "chrome/browser/ash/crosapi/test_crosapi_dependency_registry.h"
+#include "chromeos/ash/components/login/login_state/login_state.h"
+
+namespace crosapi {
+
+TestCrosapiEnvironment::TestCrosapiEnvironment() = default;
+
+TestCrosapiEnvironment::~TestCrosapiEnvironment() = default;
+
+void TestCrosapiEnvironment::SetUp() {
+  // CrosapiAsh depends on ProfileManager.
+  CHECK(testing_profile_manager_.SetUp());
+  // Without this line, IdleServiceAsh gets initialized by CrosapiAsh and fails
+  // due to missing dependencies.
+  crosapi::IdleServiceAsh::DisableForTesting();
+  // CrosapiAsh depends on LoginState. We initialize it here only if it hasn't
+  // already been initialized by another test class such as AshTestBase.
+  if (!ash::LoginState::IsInitialized()) {
+    ash::LoginState::Initialize();
+    initialized_login_state_ = true;
+  }
+  crosapi_manager_ = crosapi::CreateCrosapiManagerWithTestRegistry();
+}
+
+void TestCrosapiEnvironment::TearDown() {
+  testing_profile_manager_.DeleteAllTestingProfiles();
+  crosapi_manager_.reset();
+  if (initialized_login_state_) {
+    ash::LoginState::Shutdown();
+  }
+}
+
+}  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/test_crosapi_environment.h b/chrome/browser/ash/crosapi/test_crosapi_environment.h
new file mode 100644
index 0000000..fa8d8b56
--- /dev/null
+++ b/chrome/browser/ash/crosapi/test_crosapi_environment.h
@@ -0,0 +1,43 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_CROSAPI_TEST_CROSAPI_ENVIRONMENT_H_
+#define CHROME_BROWSER_ASH_CROSAPI_TEST_CROSAPI_ENVIRONMENT_H_
+
+#include <memory>
+
+#include "base/allocator/partition_allocator/pointers/raw_ptr.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+
+namespace crosapi {
+
+class CrosapiManager;
+
+// Sets up classes needed by tests that depend on CrosapiManager.
+class TestCrosapiEnvironment {
+ public:
+  TestCrosapiEnvironment();
+  ~TestCrosapiEnvironment();
+
+  void SetUp();
+  void TearDown();
+
+  TestingProfileManager* profile_manager() { return &testing_profile_manager_; }
+
+ private:
+  // If we want to use `this` in a test fixture that provides its own
+  // ProfileManager, then we'd want to allow its injection into `this` to avoid
+  // having multiple ProfileManager instances.
+  TestingProfileManager testing_profile_manager_{
+      TestingBrowserProcess::GetGlobal()};
+
+  std::unique_ptr<crosapi::CrosapiManager> crosapi_manager_;
+  bool initialized_login_state_ = false;
+};
+
+}  // namespace crosapi
+
+#endif  // CHROME_BROWSER_ASH_CROSAPI_TEST_CROSAPI_ENVIRONMENT_H_
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc b/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc
index 5a68fbc..b54e15df 100644
--- a/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc
@@ -1194,12 +1194,12 @@
           GetSenderWebContents());
   base::Value::Dict info;
   if (caller.has_value()) {
-    if (caller->url_or_path.has_value()) {
-      info.Set("url", caller->url_or_path.value());
+    if (caller->url_or_path().has_value()) {
+      info.Set("url", caller->url_or_path().value());
     }
-    if (caller->component.has_value()) {
+    if (caller->component().has_value()) {
       info.Set("component",
-               DlpRulesManagerComponentToApiEnum(caller->component.value()));
+               DlpRulesManagerComponentToApiEnum(caller->component().value()));
     }
   }
 
diff --git a/chrome/browser/ash/extensions/install_limiter_unittest.cc b/chrome/browser/ash/extensions/install_limiter_unittest.cc
index fb5eee3..21090baf 100644
--- a/chrome/browser/ash/extensions/install_limiter_unittest.cc
+++ b/chrome/browser/ash/extensions/install_limiter_unittest.cc
@@ -117,8 +117,7 @@
   void SetUp() override {
     extensions::ExtensionServiceTestBase::SetUp();
 
-    extensions::ExtensionServiceTestBase::ExtensionServiceInitParams params =
-        CreateDefaultInitParams();
+    ExtensionServiceInitParams params;
     params.enable_install_limiter = true;
     InitializeExtensionService(params);
 
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
index e33e3e4..7158093 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -1052,7 +1052,9 @@
   std::unique_ptr<base::RunLoop> run_loop_;
 };
 
-IN_PROC_BROWSER_TEST_P(FileTransferConnectorFilesAppBrowserTest, Test) {
+// TODO(crbug.com/1425820): Re-enable this test
+IN_PROC_BROWSER_TEST_P(FileTransferConnectorFilesAppBrowserTest,
+                       DISABLED_Test) {
   StartTest();
 }
 
diff --git a/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc b/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc
index e5a1323..30ca1358 100644
--- a/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc
+++ b/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc
@@ -291,8 +291,7 @@
   }
 
   extensions::api::app_runtime::ActionData action_data;
-  action_data.action_type =
-      extensions::api::app_runtime::ActionType::ACTION_TYPE_NEW_NOTE;
+  action_data.action_type = extensions::api::app_runtime::ActionType::kNewNote;
   action_data.is_lock_screen_action = true;
   action_data.restore_last_action_state =
       primary_profile_->GetPrefs()->GetBoolean(
diff --git a/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc b/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
index 5e7c0d1c..9d8beae 100644
--- a/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
+++ b/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
@@ -120,7 +120,7 @@
             arg_value);
     ASSERT_TRUE(launch_data);
     ASSERT_TRUE(launch_data->action_data);
-    EXPECT_EQ(extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE,
+    EXPECT_EQ(extensions::api::app_runtime::ActionType::kNewNote,
               launch_data->action_data->action_type);
 
     ASSERT_TRUE(launch_data->action_data->is_lock_screen_action);
diff --git a/chrome/browser/ash/lock_screen_apps/lock_screen_apps.cc b/chrome/browser/ash/lock_screen_apps/lock_screen_apps.cc
index db9ecbe..9b684cf8 100644
--- a/chrome/browser/ash/lock_screen_apps/lock_screen_apps.cc
+++ b/chrome/browser/ash/lock_screen_apps/lock_screen_apps.cc
@@ -103,7 +103,7 @@
     return false;
   }
   return extensions::ActionHandlersInfo::HasLockScreenActionHandler(
-      chrome_app, app_runtime::ACTION_TYPE_NEW_NOTE);
+      chrome_app, app_runtime::ActionType::kNewNote);
 }
 
 // Gets the set of app IDs that are allowed to be launched on the lock screen,
diff --git a/chrome/browser/ash/lock_screen_apps/note_taking_browsertest.cc b/chrome/browser/ash/lock_screen_apps/note_taking_browsertest.cc
index 5345224..44b3fad 100644
--- a/chrome/browser/ash/lock_screen_apps/note_taking_browsertest.cc
+++ b/chrome/browser/ash/lock_screen_apps/note_taking_browsertest.cc
@@ -240,8 +240,7 @@
   // Launch note taking in regular, non lock screen context. The test will
   // verify the app cannot create lock screen enabled app windows in this case.
   extensions::api::app_runtime::ActionData action_data;
-  action_data.action_type =
-      extensions::api::app_runtime::ActionType::ACTION_TYPE_NEW_NOTE;
+  action_data.action_type = extensions::api::app_runtime::ActionType::kNewNote;
   apps::LaunchPlatformAppWithAction(profile(), app.get(),
                                     std::move(action_data));
 
diff --git a/chrome/browser/ash/lock_screen_apps/state_controller.cc b/chrome/browser/ash/lock_screen_apps/state_controller.cc
index 1ba7212..051621e 100644
--- a/chrome/browser/ash/lock_screen_apps/state_controller.cc
+++ b/chrome/browser/ash/lock_screen_apps/state_controller.cc
@@ -409,8 +409,9 @@
     const extensions::Extension* extension,
     extensions::api::app_runtime::ActionType action,
     std::unique_ptr<extensions::AppDelegate> app_delegate) {
-  if (action != extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE)
+  if (action != extensions::api::app_runtime::ActionType::kNewNote) {
     return nullptr;
+  }
 
   if (note_app_window_)
     return nullptr;
diff --git a/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc b/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
index e15f99f..e469acc 100644
--- a/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
+++ b/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
@@ -517,7 +517,7 @@
     return std::make_unique<TestAppWindow>(
         profile, state_controller()->CreateAppWindowForLockScreenAction(
                      profile, extension,
-                     extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE,
+                     extensions::api::app_runtime::ActionType::kNewNote,
                      std::make_unique<ChromeAppDelegate>(profile, true)));
   }
 
@@ -946,7 +946,7 @@
       ->extension_service()
       ->AddExtension(app.get());
   EXPECT_FALSE(state_controller()->CreateAppWindowForLockScreenAction(
-      profile(), app.get(), extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE,
+      profile(), app.get(), extensions::api::app_runtime::ActionType::kNewNote,
       std::make_unique<ChromeAppDelegate>(profile(), true)));
 }
 
@@ -1088,7 +1088,7 @@
             state_controller()->GetLockScreenNoteState());
 
   EXPECT_FALSE(state_controller()->CreateAppWindowForLockScreenAction(
-      profile(), app(), extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE,
+      profile(), app(), extensions::api::app_runtime::ActionType::kNewNote,
       std::make_unique<ChromeAppDelegate>(profile(), true)));
 
   ExpectObservedStatesMatch({TrayActionState::kAvailable},
@@ -1184,7 +1184,7 @@
 
   EXPECT_FALSE(state_controller()->CreateAppWindowForLockScreenAction(
       LockScreenProfile(), app(),
-      extensions::api::app_runtime::ACTION_TYPE_NONE,
+      extensions::api::app_runtime::ActionType::kNone,
       std::make_unique<ChromeAppDelegate>(LockScreenProfile(), true)));
 
   app_window = CreateNoteTakingWindow(LockScreenProfile(), app());
@@ -1424,7 +1424,7 @@
             state_controller()->GetLockScreenNoteState());
 
   EXPECT_FALSE(state_controller()->CreateAppWindowForLockScreenAction(
-      profile(), app(), extensions::api::app_runtime::ACTION_TYPE_NEW_NOTE,
+      profile(), app(), extensions::api::app_runtime::ActionType::kNewNote,
       std::make_unique<ChromeAppDelegate>(profile(), true)));
 
   ExpectObservedStatesMatch({TrayActionState::kAvailable},
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
index d1a11d3..1800c8d1 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
@@ -9,14 +9,17 @@
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/login_accelerators.h"
 #include "base/check_is_test.h"
+#include "base/debug/stack_trace.h"
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/functional/callback_helpers.h"
+#include "base/location.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
 #include "base/syslog_logging.h"
+#include "base/task/sequenced_task_runner.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/app_mode/app_launch_utils.h"
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h"
@@ -32,6 +35,7 @@
 #include "chrome/browser/ash/crosapi/browser_data_migrator.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ash/login/app_mode/force_install_observer.h"
+#include "chrome/browser/ash/login/app_mode/network_ui_controller.h"
 #include "chrome/browser/ash/login/enterprise_user_session_metrics.h"
 #include "chrome/browser/ash/login/screens/encryption_migration_screen.h"
 #include "chrome/browser/ash/login/ui/login_display_host.h"
@@ -65,12 +69,6 @@
 // tests.
 bool g_disable_login_operations = false;
 
-base::OnceClosure* network_timeout_callback = nullptr;
-KioskLaunchController::ReturnBoolCallback* can_configure_network_callback =
-    nullptr;
-KioskLaunchController::ReturnBoolCallback*
-    need_owner_auth_to_configure_network_callback = nullptr;
-
 // Enum types for Kiosk.LaunchType UMA so don't change its values.
 // KioskLaunchType in histogram.xml must be updated when making changes here.
 enum KioskLaunchType {
@@ -205,8 +203,16 @@
   return base::Seconds(min_time_in_seconds);
 }
 
+template <class T>
+void DeleteSoon(std::unique_ptr<T> pointer) {
+  base::SequencedTaskRunner::GetCurrentDefault()->DeleteSoon(
+      FROM_HERE, std::move(pointer));
+}
+
 }  // namespace
 
+using NetworkUIState = NetworkUiController::NetworkUIState;
+
 const char kKioskLaunchStateCrashKey[] = "kiosk-launch-state";
 const base::TimeDelta kDefaultKioskSplashScreenMinTime = base::Seconds(10);
 
@@ -242,7 +248,9 @@
     KioskAppLauncherFactory app_launcher_factory)
     : host_(host),
       splash_screen_view_(splash_screen),
-      app_launcher_factory_(std::move(app_launcher_factory)) {}
+      app_launcher_factory_(std::move(app_launcher_factory)),
+      network_ui_controller_(
+          std::make_unique<NetworkUiController>(*this, host, splash_screen)) {}
 
 KioskLaunchController::~KioskLaunchController() {
   if (splash_screen_view_) {
@@ -275,7 +283,7 @@
     }
   }
 
-  splash_screen_view_->SetDelegate(this);
+  splash_screen_view_->SetDelegate(network_ui_controller_.get());
   splash_screen_view_->Show(GetAppData());
 
   splash_wait_timer_.Start(FROM_HERE, GetSplashScreenMinTime(),
@@ -349,15 +357,12 @@
 
   // This is needed to trigger input method extensions being loaded.
   profile->InitChromeOSPreferences();
+  network_ui_controller_->SetProfile(profile);
 
   InitializeKeyboard();
 
-  // We have loaded the profile, so we can create and start the
-  // `KioskAppLauncher`. However, if the user has requested to configure the
-  // network beforehand, we will show the dialog instead and create the launcher
-  // when that's done.
-  if (network_ui_state_ == NetworkUIState::kNeedToShow) {
-    ShowNetworkConfigureUI();
+  if (network_ui_controller_->ShouldShowNetworkConfig()) {
+    network_ui_controller_->UserRequestedNetworkConfig();
   } else {
     InitializeLauncher();
   }
@@ -377,31 +382,12 @@
   DCHECK(!app_launcher_);
 
   app_state_ = kInitLauncher;
-  app_launcher_ = app_launcher_factory_.Run(profile_, kiosk_app_id_, this);
+  app_launcher_ = app_launcher_factory_.Run(profile_, kiosk_app_id_,
+                                            network_ui_controller_.get());
   app_launcher_observation_.Observe(app_launcher_.get());
   app_launcher_->Initialize();
 }
 
-void KioskLaunchController::OnConfigureNetwork() {
-  DCHECK(profile_);
-  if (network_ui_state_ == NetworkUIState::kShowing) {
-    return;
-  }
-
-  network_ui_state_ = NetworkUIState::kShowing;
-  if (CanConfigureNetwork() && NeedOwnerAuthToConfigureNetwork()) {
-    host_->VerifyOwnerForKiosk(
-        base::BindOnce(&KioskLaunchController::ShowNetworkConfigureUI,
-                       weak_ptr_factory_.GetWeakPtr()));
-  } else {
-    // If kiosk mode was configured through enterprise policy, we may
-    // not have an owner user.
-    // TODO(tengs): We need to figure out the appropriate security meausres
-    // for this case.
-    NOTREACHED();
-  }
-}
-
 void KioskLaunchController::OnCancelAppLaunch() {
   if (cleaned_up_) {
     return;
@@ -462,9 +448,15 @@
   splash_wait_timer_.Stop();
 
   splash_screen_view_ = nullptr;
-  force_install_observer_.reset();
 
-  kiosk_profile_loader_.reset();
+  app_launcher_observation_.Reset();
+
+  // Deleting the local objects later so they
+  DeleteSoon(std::move(kiosk_profile_loader_));
+  DeleteSoon(std::move(force_install_observer_));
+  DeleteSoon(std::move(app_launcher_));
+  DeleteSoon(std::move(network_ui_controller_));
+
   // Can be null in tests.
   if (host_) {
     host_->Finalize(base::OnceClosure());
@@ -515,7 +507,7 @@
     return;
   }
 
-  if (network_ui_state_ != NetworkUIState::kNotShowing) {
+  if (network_ui_controller_->IsShowingNetworkConfigScreen()) {
     return;
   }
 
@@ -538,55 +530,6 @@
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
-void KioskLaunchController::InitializeNetwork() {
-  if (!splash_screen_view_) {
-    return;
-  }
-
-  network_ui_state_ = NetworkUIState::kWaitingForNetwork;
-  network_wait_timer_.Start(FROM_HERE, g_network_wait_time, this,
-                            &KioskLaunchController::OnNetworkWaitTimedOut);
-
-  // When we are asked to initialize network, we should remember that this app
-  // requires network.
-  network_required_ = true;
-  splash_screen_view_->SetNetworkRequired();
-
-  splash_screen_view_->UpdateAppLaunchState(
-      AppLaunchSplashScreenView::AppLaunchState::kPreparingNetwork);
-
-  if (splash_screen_view_->IsNetworkReady()) {
-    OnNetworkStateChanged(true);
-  }
-}
-
-void KioskLaunchController::OnNetworkWaitTimedOut() {
-  DCHECK(network_ui_state_ == NetworkUIState::kNotShowing ||
-         network_ui_state_ == NetworkUIState::kWaitingForNetwork);
-
-  auto connection_type = network::mojom::ConnectionType::CONNECTION_UNKNOWN;
-  content::GetNetworkConnectionTracker()->GetConnectionType(&connection_type,
-                                                            base::DoNothing());
-  SYSLOG(WARNING) << "OnNetworkWaitTimedout... connection = "
-                  << connection_type;
-  network_wait_timedout_ = true;
-
-  MaybeShowNetworkConfigureUI();
-
-  if (network_timeout_callback) {
-    std::move(*network_timeout_callback).Run();
-    network_timeout_callback = nullptr;
-  }
-}
-
-bool KioskLaunchController::IsNetworkReady() const {
-  return splash_screen_view_ && splash_screen_view_->IsNetworkReady();
-}
-
-bool KioskLaunchController::IsShowingNetworkConfigScreen() const {
-  return network_ui_state_ == NetworkUIState::kShowing;
-}
-
 void KioskLaunchController::OnLaunchFailed(KioskAppLaunchError::Error error) {
   if (cleaned_up_) {
     return;
@@ -737,104 +680,24 @@
   migration_screen->SetupInitialView();
 }
 
-bool KioskLaunchController::CanConfigureNetwork() {
-  if (can_configure_network_callback) {
-    return can_configure_network_callback->Run();
-  }
-
-  if (IsDeviceEnterpriseManaged()) {
-    bool should_prompt;
-    if (CrosSettings::Get()->GetBoolean(
-            kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
-            &should_prompt)) {
-      return should_prompt;
-    }
-    // Default to true to allow network configuration if the policy is
-    // missing.
-    return true;
-  }
-
-  return user_manager::UserManager::Get()->GetOwnerAccountId().is_valid();
-}
-
-bool KioskLaunchController::NeedOwnerAuthToConfigureNetwork() {
-  if (need_owner_auth_to_configure_network_callback) {
-    return need_owner_auth_to_configure_network_callback->Run();
-  }
-
-  return !IsDeviceEnterpriseManaged();
-}
-
-void KioskLaunchController::MaybeShowNetworkConfigureUI() {
-  SYSLOG(INFO) << "Network configure UI was requested to be shown.";
-  if (!splash_screen_view_) {
-    return;
-  }
-
-  if (!profile_) {
-    SYSLOG(INFO)
-        << "Postponing configure network dialog till profile is loaded.";
-    splash_screen_view_->UpdateAppLaunchState(
-        AppLaunchSplashScreenView::AppLaunchState::kShowingNetworkConfigureUI);
-    network_ui_state_ = kNeedToShow;
-    return;
-  }
-
-  if (CanConfigureNetwork()) {
-    if (NeedOwnerAuthToConfigureNetwork()) {
-      if (!network_wait_timedout_) {
-        OnConfigureNetwork();
-      } else {
-        splash_screen_view_->ToggleNetworkConfig(true);
-      }
-    } else {
-      ShowNetworkConfigureUI();
-    }
-  } else {
-    splash_screen_view_->UpdateAppLaunchState(
-        AppLaunchSplashScreenView::AppLaunchState::kNetworkWaitTimeout);
-  }
-}
-
-void KioskLaunchController::ShowNetworkConfigureUI() {
-  DCHECK(profile_);
-
-  // We're about to show the network configure UI, so we destroy the
-  // app_launcher_ and effectively reset the installation state. A new launcher
-  // will be created in `OnNetworkConfigFinished`.
-  app_launcher_observation_.Reset();
-  app_launcher_.reset();
-  // We should stop timers since they may fire during network
-  // configure UI.
-  splash_wait_timer_.Stop();
-  network_wait_timer_.Stop();
-  launch_on_install_ = true;
-  app_state_ = kInitNetwork;
-  network_ui_state_ = NetworkUIState::kShowing;
-  splash_screen_view_->ShowNetworkConfigureUI();
-}
-
-void KioskLaunchController::CloseNetworkConfigureScreenIfOnline() {
-  if (network_ui_state_ == NetworkUIState::kShowing && network_wait_timedout_) {
-    SYSLOG(INFO) << "We are back online, closing network configure screen.";
-    splash_screen_view_->ToggleNetworkConfig(false);
-    splash_screen_view_->ContinueAppLaunch();
-    network_ui_state_ = NetworkUIState::kNotShowing;
-  }
-}
-
 void KioskLaunchController::OnNetworkConfigRequested() {
-  if (app_state_ == kLaunched) {
+  if (app_state_ == AppState::kLaunched) {
     // We do nothing since the splash screen is soon to be destroyed.
     return;
   }
 
-  MaybeShowNetworkConfigureUI();
+  network_ui_controller_->UserRequestedNetworkConfig();
 }
 
-void KioskLaunchController::OnNetworkConfigFinished() {
-  network_ui_state_ = NetworkUIState::kNotShowing;
+void KioskLaunchController::OnNetworkConfigureUiShowing() {
+  splash_wait_timer_.Stop();
+  app_state_ = kInitNetwork;
+  launch_on_install_ = true;
+  app_launcher_observation_.Reset();
+  app_launcher_.reset();
+}
 
+void KioskLaunchController::OnNetworkConfigureUiFinished() {
   if (splash_screen_view_) {
     splash_screen_view_->UpdateAppLaunchState(
         AppLaunchSplashScreenView::AppLaunchState::kPreparingProfile);
@@ -844,40 +707,13 @@
   InitializeLauncher();
 }
 
-void KioskLaunchController::OnNetworkStateChanged(bool online) {
-  if (online) {
-    OnNetworkOnline();
-  } else {
-    OnNetworkOffline();
-  }
+void KioskLaunchController::OnNetworkReady() {
+  app_launcher_->ContinueWithNetworkReady();
 }
 
-void KioskLaunchController::OnNetworkOnline() {
-  bool network_showing_after_timeout =
-      network_wait_timedout_ && network_ui_state_ == NetworkUIState::kShowing;
-
-  if (!network_showing_after_timeout &&
-      network_ui_state_ != NetworkUIState::kWaitingForNetwork) {
-    // The UI is not showing at all, or was requested by the user so we do
-    // nothing
-    return;
-  }
-
-  // Close the network UI and continue the app launch
-  network_wait_timer_.Stop();
-  CloseNetworkConfigureScreenIfOnline();
-  network_ui_state_ = kNotShowing;
-  if (app_launcher_) {
-    app_launcher_->ContinueWithNetworkReady();
-  }
-}
-
-void KioskLaunchController::OnNetworkOffline() {
-  if (network_required_ && (app_state_ == AppState::kInstallingApp ||
-                            app_state_ == AppState::kInstallingExtensions)) {
-    SYSLOG(WARNING)
-        << "Connection lost during installation, restarting launcher.";
-    OnNetworkWaitTimedOut();
+void KioskLaunchController::OnNetworkLost() {
+  if (app_state_ == kInstallingApp || app_state_ == kInstallingExtensions) {
+    network_ui_controller_->OnNetworkLostDuringInstallation();
   }
 }
 
@@ -895,6 +731,10 @@
   app_launcher_->LaunchApp();
 }
 
+NetworkUiController* KioskLaunchController::GetNetworkUiControllerForTesting() {
+  return network_ui_controller_.get();
+}
+
 // static
 std::unique_ptr<base::AutoReset<bool>>
 KioskLaunchController::DisableLoginOperationsForTesting() {
@@ -928,23 +768,4 @@
   return base::AutoReset<bool>(&g_block_exit_on_failure_for_testing, true);
 }
 
-// static
-void KioskLaunchController::SetNetworkTimeoutCallbackForTesting(
-    base::OnceClosure* callback) {
-  network_timeout_callback = callback;
-}
-
-// static
-void KioskLaunchController::SetCanConfigureNetworkCallbackForTesting(
-    ReturnBoolCallback* callback) {
-  can_configure_network_callback = callback;
-}
-
-// static
-void KioskLaunchController::
-    SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
-        ReturnBoolCallback* callback) {
-  need_owner_auth_to_configure_network_callback = callback;
-}
-
 }  // namespace ash
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h
index 58655c8f..65eb553 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 #include "chrome/browser/ash/app_mode/kiosk_profile_loader.h"
 #include "chrome/browser/ash/login/app_mode/force_install_observer.h"
+#include "chrome/browser/ash/login/app_mode/network_ui_controller.h"
 #include "chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h"
 
 namespace app_mode {
@@ -82,9 +83,8 @@
 // It is all encompassed within the combination of two states -- AppState and
 // NetworkUI state.
 class KioskLaunchController : public KioskProfileLoader::Delegate,
-                              public AppLaunchSplashScreenView::Delegate,
-                              public KioskAppLauncher::NetworkDelegate,
-                              public KioskAppLauncher::Observer {
+                              public KioskAppLauncher::Observer,
+                              public NetworkUiController::Observer {
  public:
   class KioskProfileLoadFailedObserver : public base::CheckedObserver {
    public:
@@ -120,18 +120,12 @@
   [[nodiscard]] static std::unique_ptr<base::AutoReset<bool>>
   BlockAppLaunchForTesting();
   [[nodiscard]] static base::AutoReset<bool> BlockExitOnFailureForTesting();
-  static void SetNetworkTimeoutCallbackForTesting(base::OnceClosure* callback);
-  static void SetCanConfigureNetworkCallbackForTesting(
-      ReturnBoolCallback* callback);
-  static void SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
-      ReturnBoolCallback* callback);
 
   bool waiting_for_network() const {
     return app_state_ == AppState::kInitNetwork;
   }
-  bool network_wait_timedout() const { return network_wait_timedout_; }
   bool showing_network_dialog() const {
-    return network_ui_state_ == NetworkUIState::kShowing;
+    return network_ui_controller_->IsShowingNetworkConfigScreen();
   }
 
   void Start(const KioskAppId& kiosk_app_id, bool auto_launch);
@@ -144,6 +138,18 @@
 
   bool HandleAccelerator(LoginAcceleratorAction action);
 
+  // `NetworkUiController::Observer`:
+  void OnNetworkConfigureUiShowing() override;
+  void OnNetworkConfigureUiFinished() override;
+  void OnNetworkReady() override;
+  void OnNetworkLost() override;
+
+  // Currently required for testing
+  NetworkUiController::NetworkUIState GetNetworkUiStateForTesting() const {
+    return network_ui_controller_->GetNetworkUiStateForTesting();
+  }
+  NetworkUiController* GetNetworkUiControllerForTesting();
+
  private:
   friend class KioskLaunchControllerTest;
 
@@ -158,31 +164,11 @@
     kInitNetwork,  // Waiting for the network to initialize.
   };
 
-  enum NetworkUIState {
-    kNotShowing = 0,     // Network configure UI is not being shown.
-    kNeedToShow,         // We need to show the UI as soon as we can.
-    kShowing,            // Network configure UI is being shown.
-    kWaitingForNetwork,  // App requested network. In this case we first wait
-                         // for 10s to see if network appears. If it does, we
-                         // continue the app launch, otherwise we show the
-                         // config network UI
-  };
-
   void OnCancelAppLaunch();
   void OnNetworkConfigRequested();
   void InitializeKeyboard();
   void InitializeLauncher();
 
-  // `AppLaunchSplashScreenView::Delegate`
-  void OnConfigureNetwork() override;
-  void OnNetworkConfigFinished() override;
-  void OnNetworkStateChanged(bool online) override;
-
-  // `KioskAppLauncher::NetworkDelegate`
-  void InitializeNetwork() override;
-  bool IsNetworkReady() const override;
-  bool IsShowingNetworkConfigScreen() const override;
-
   // `KioskAppLauncher::Observer`
   void OnLaunchFailed(KioskAppLaunchError::Error error) override;
   void OnAppInstalling() override;
@@ -201,14 +187,6 @@
 
   // Whether the network could be configured during launching.
   bool CanConfigureNetwork();
-  // Whether the owner password is needed to configure network.
-  bool NeedOwnerAuthToConfigureNetwork();
-  // Shows network configuration dialog if kiosk profile was already created or
-  // postpones the display upon creation.
-  void MaybeShowNetworkConfigureUI();
-  // Shows the network configuration dialog.
-  void ShowNetworkConfigureUI();
-  void CloseNetworkConfigureScreenIfOnline();
 
   void HandleWebAppInstallFailed();
 
@@ -217,7 +195,6 @@
   void FinishForcedExtensionsInstall(
       app_mode::ForceInstallObserver::Result result);
 
-  void OnNetworkWaitTimedOut();
   void OnNetworkOnline();
   void OnNetworkOffline();
   void OnTimerFire();
@@ -229,8 +206,6 @@
 
   // Current state of the controller.
   AppState app_state_ = AppState::kCreatingProfile;
-  // Current state of network configure dialog.
-  NetworkUIState network_ui_state_ = NetworkUIState::kNotShowing;
 
   // Not owned, destructed upon shutdown.
   raw_ptr<LoginDisplayHost> const host_;
@@ -241,12 +216,10 @@
   // Not owned.
   raw_ptr<Profile> profile_ = nullptr;
   const KioskAppLauncherFactory app_launcher_factory_;
+  std::unique_ptr<NetworkUiController> network_ui_controller_;
 
   // Whether app should be launched as soon as it is ready.
   bool launch_on_install_ = false;
-  bool network_wait_timedout_ = false;
-  // Whether the network is required for the installation.
-  bool network_required_ = false;
 
   // Whether the controller has already been cleaned-up.
   bool cleaned_up_ = false;
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc b/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc
index c0f993952..003712c 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc
@@ -87,7 +87,7 @@
 class KioskLaunchControllerTest : public extensions::ExtensionServiceTestBase {
  public:
   using AppState = KioskLaunchController::AppState;
-  using NetworkUIState = KioskLaunchController::NetworkUIState;
+  using NetworkUIState = NetworkUiController::NetworkUIState;
 
   KioskLaunchControllerTest()
       : extensions::ExtensionServiceTestBase(
@@ -136,12 +136,12 @@
 
   KioskLaunchController& controller() { return *controller_; }
 
-  KioskAppLauncher::NetworkDelegate& network_delegate() { return *controller_; }
+  KioskAppLauncher::NetworkDelegate& network_delegate() {
+    return *controller_->GetNetworkUiControllerForTesting();
+  }
 
   KioskProfileLoader::Delegate& profile_controls() { return *controller_; }
 
-  AppLaunchSplashScreenView::Delegate& view_controls() { return *controller_; }
-
   FakeKioskAppLauncher& launcher() { return *app_launcher_; }
 
   int num_launchers_created() { return app_launchers_created_; }
@@ -150,9 +150,9 @@
     return testing::AllOf(
         testing::Field("app_state", &KioskLaunchController::app_state_,
                        Eq(app_state)),
-        testing::Field("network_ui_state",
-                       &KioskLaunchController::network_ui_state_,
-                       Eq(network_state)));
+        testing::Property("network_ui_state",
+                          &KioskLaunchController::GetNetworkUiStateForTesting,
+                          Eq(network_state)));
   }
 
   auto HasViewState(AppLaunchSplashScreenView::AppLaunchState launch_state) {
diff --git a/chrome/browser/ash/login/app_mode/network_ui_controller.cc b/chrome/browser/ash/login/app_mode/network_ui_controller.cc
new file mode 100644
index 0000000..9ed87ba
--- /dev/null
+++ b/chrome/browser/ash/login/app_mode/network_ui_controller.cc
@@ -0,0 +1,267 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/login/app_mode/network_ui_controller.h"
+
+#include "base/syslog_logging.h"
+#include "chrome/browser/ash/login/app_mode/kiosk_launch_controller.h"
+#include "chrome/browser/ash/login/ui/login_display_host.h"
+#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part_ash.h"
+#include "chromeos/ash/components/settings/cros_settings_names.h"
+#include "components/user_manager/user_manager.h"
+#include "content/public/browser/network_service_instance.h"
+
+namespace {
+
+// Time of waiting for the network to be ready to start installation. Can be
+// changed in tests.
+constexpr base::TimeDelta kKioskNetworkWaitTime = base::Seconds(10);
+base::TimeDelta g_network_wait_time = kKioskNetworkWaitTime;
+
+base::RepeatingCallback<bool()>* g_can_configure_network_callback = nullptr;
+base::RepeatingCallback<bool()>*
+    g_need_owner_auth_to_configure_network_callback = nullptr;
+
+bool IsDeviceEnterpriseManaged() {
+  return g_browser_process->platform_part()
+      ->browser_policy_connector_ash()
+      ->IsDeviceEnterpriseManaged();
+}
+
+bool IsConsumerKiosk() {
+  if (g_need_owner_auth_to_configure_network_callback) {
+    return g_need_owner_auth_to_configure_network_callback->Run();
+  }
+
+  return !IsDeviceEnterpriseManaged();
+}
+
+bool CanConfigureNetworkForConsumerKiosk() {
+  return user_manager::UserManager::Get()->GetOwnerAccountId().is_valid();
+}
+
+bool CanConfigureNetworkForEnterpriseKiosk() {
+  bool should_prompt;
+  if (ash::CrosSettings::Get()->GetBoolean(
+          ash::kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
+          &should_prompt)) {
+    return should_prompt;
+  }
+  // Default to true to allow network configuration if the policy is
+  // missing.
+  return true;
+}
+
+network::mojom::ConnectionType GetCurrentConnectionType() {
+  auto connection_type = network::mojom::ConnectionType::CONNECTION_UNKNOWN;
+  content::GetNetworkConnectionTracker()->GetConnectionType(&connection_type,
+                                                            base::DoNothing());
+  return connection_type;
+}
+
+}  // namespace
+
+namespace ash {
+
+NetworkUiController::NetworkUiController(
+    Observer& observer,
+    LoginDisplayHost* host,
+    AppLaunchSplashScreenView* splash_screen)
+    : observer_(observer), host_(host), splash_screen_view_(splash_screen) {}
+
+NetworkUiController::~NetworkUiController() = default;
+
+void NetworkUiController::SetProfile(Profile* profile) {
+  profile_ = profile;
+}
+
+void NetworkUiController::UserRequestedNetworkConfig() {
+  if (!profile_) {
+    SYSLOG(INFO) << "Postponing network dialog till profile is loaded.";
+    network_ui_state_ = NetworkUIState::kNeedToShow;
+    splash_screen_view_->UpdateAppLaunchState(
+        AppLaunchSplashScreenView::AppLaunchState::kShowingNetworkConfigureUI);
+    return;
+  }
+
+  MaybeShowNetworkConfigureUI();
+}
+
+bool NetworkUiController::ShouldShowNetworkConfig() {
+  return network_ui_state_ == kNeedToShow;
+}
+
+void NetworkUiController::OnNetworkLostDuringInstallation() {
+  if (network_required_) {
+    SYSLOG(WARNING) << "Connection lost during installation.";
+    OnNetworkWaitTimeout();
+  }
+}
+
+void NetworkUiController::InitializeNetwork() {
+  if (!splash_screen_view_) {
+    return;
+  }
+
+  network_ui_state_ = NetworkUIState::kWaitingForNetwork;
+
+  network_wait_timer_.Start(FROM_HERE, g_network_wait_time, this,
+                            &NetworkUiController::OnNetworkWaitTimeout);
+
+  // When we are asked to initialize network, we should remember that this app
+  // requires network.
+  network_required_ = true;
+  splash_screen_view_->SetNetworkRequired();
+
+  splash_screen_view_->UpdateAppLaunchState(
+      AppLaunchSplashScreenView::AppLaunchState::kPreparingNetwork);
+
+  if (splash_screen_view_->IsNetworkReady()) {
+    OnNetworkOnline();
+  }
+}
+
+void NetworkUiController::OnConfigureNetwork() {
+  CHECK(IsConsumerKiosk());
+  CHECK(profile_);
+
+  if (network_ui_state_ == NetworkUIState::kShowing) {
+    return;
+  }
+
+  if (CanConfigureNetworkForConsumerKiosk()) {
+    host_->VerifyOwnerForKiosk(
+        base::BindOnce(&NetworkUiController::ShowNetworkConfigureUI,
+                       weak_ptr_factory_.GetWeakPtr()));
+  }
+}
+
+void NetworkUiController::OnNetworkConfigFinished() {
+  network_ui_state_ = NetworkUIState::kNotShowing;
+
+  observer_->OnNetworkConfigureUiFinished();
+}
+
+void NetworkUiController::OnNetworkStateChanged(bool online) {
+  if (online) {
+    OnNetworkOnline();
+  } else {
+    OnNetworkOffline();
+  }
+}
+
+void NetworkUiController::OnNetworkOnline() {
+  bool network_showing_after_timeout =
+      network_wait_timeout_ && network_ui_state_ == kShowing;
+  bool is_waiting_for_network = network_ui_state_ == kWaitingForNetwork;
+
+  if (!is_waiting_for_network && !network_showing_after_timeout) {
+    // The UI is not showing at all, or was requested by the user so we do
+    // nothing
+    return;
+  }
+
+  network_wait_timer_.Stop();
+  network_ui_state_ = kNotShowing;
+
+  if (network_showing_after_timeout) {
+    SYSLOG(INFO) << "We are back online, closing network configure screen.";
+    CloseNetworkConfigureUI();
+  } else {
+    observer_->OnNetworkReady();
+  }
+}
+
+void NetworkUiController::OnNetworkOffline() {
+  observer_->OnNetworkLost();
+}
+
+void NetworkUiController::CloseNetworkConfigureUI() {
+  splash_screen_view_->ToggleNetworkConfig(false);
+  splash_screen_view_->ContinueAppLaunch();
+}
+
+bool NetworkUiController::IsNetworkReady() const {
+  return splash_screen_view_ && splash_screen_view_->IsNetworkReady();
+}
+
+bool NetworkUiController::IsShowingNetworkConfigScreen() const {
+  return network_ui_state_ == NetworkUIState::kShowing;
+}
+
+void NetworkUiController::MaybeShowNetworkConfigureUI() {
+  SYSLOG(INFO) << "Network configure UI was requested to be shown.";
+  if (!splash_screen_view_) {
+    return;
+  }
+
+  if (!CanConfigureNetwork()) {
+    splash_screen_view_->UpdateAppLaunchState(
+        AppLaunchSplashScreenView::AppLaunchState::kNetworkWaitTimeout);
+    return;
+  }
+
+  if (IsConsumerKiosk()) {
+    MaybeShowNetworkConfigureUIForConsumerKiosk();
+  } else {
+    ShowNetworkConfigureUI();
+  }
+}
+
+void NetworkUiController::ShowNetworkConfigureUI() {
+  // We should stop timers since they may fire during network
+  // configure UI.
+  network_wait_timer_.Stop();
+  network_ui_state_ = NetworkUIState::kShowing;
+  splash_screen_view_->ShowNetworkConfigureUI();
+
+  observer_->OnNetworkConfigureUiShowing();
+}
+
+void NetworkUiController::OnNetworkWaitTimeout() {
+  DCHECK(network_ui_state_ == NetworkUIState::kNotShowing ||
+         network_ui_state_ == NetworkUIState::kWaitingForNetwork);
+
+  network::mojom::ConnectionType connection_type = GetCurrentConnectionType();
+  SYSLOG(WARNING) << __FUNCTION__ << " connection = " << connection_type;
+  network_wait_timeout_ = true;
+
+  MaybeShowNetworkConfigureUI();
+}
+
+bool NetworkUiController::CanConfigureNetwork() {
+  if (g_can_configure_network_callback) {
+    return g_can_configure_network_callback->Run();
+  }
+
+  if (IsDeviceEnterpriseManaged()) {
+    return CanConfigureNetworkForEnterpriseKiosk();
+  }
+
+  return CanConfigureNetworkForConsumerKiosk();
+}
+
+void NetworkUiController::MaybeShowNetworkConfigureUIForConsumerKiosk() {
+  if (!network_wait_timeout_) {
+    OnConfigureNetwork();
+  } else {
+    splash_screen_view_->ToggleNetworkConfig(true);
+  }
+}
+
+// static
+void NetworkUiController::SetCanConfigureNetworkCallbackForTesting(
+    base::RepeatingCallback<bool()>* callback) {
+  g_can_configure_network_callback = callback;
+}
+
+// static
+void NetworkUiController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
+    base::RepeatingCallback<bool()>* callback) {
+  g_need_owner_auth_to_configure_network_callback = callback;
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/login/app_mode/network_ui_controller.h b/chrome/browser/ash/login/app_mode/network_ui_controller.h
new file mode 100644
index 0000000..7f57e9dc
--- /dev/null
+++ b/chrome/browser/ash/login/app_mode/network_ui_controller.h
@@ -0,0 +1,102 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_LOGIN_APP_MODE_NETWORK_UI_CONTROLLER_H_
+#define CHROME_BROWSER_ASH_LOGIN_APP_MODE_NETWORK_UI_CONTROLLER_H_
+
+#include "base/timer/timer.h"
+#include "chrome/browser/ash/app_mode/kiosk_app_launcher.h"
+#include "chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h"
+
+class Profile;
+
+namespace ash {
+
+class LoginDisplayHost;
+
+class NetworkUiController : public AppLaunchSplashScreenView::Delegate,
+                            public KioskAppLauncher::NetworkDelegate {
+ public:
+  enum NetworkUIState {
+    kNotShowing = 0,     // Network configure UI is not being shown.
+    kNeedToShow,         // We need to show the UI as soon as we can.
+    kShowing,            // Network configure UI is being shown.
+    kWaitingForNetwork,  // App requested network and we're waiting for it
+  };
+
+  class Observer {
+   public:
+    Observer() = default;
+    Observer(const Observer&) = delete;
+    Observer& operator=(const Observer&) = delete;
+    ~Observer() = default;
+
+    virtual void OnNetworkConfigureUiShowing() = 0;
+    virtual void OnNetworkConfigureUiFinished() = 0;
+    virtual void OnNetworkReady() = 0;
+    virtual void OnNetworkLost() = 0;
+  };
+
+  NetworkUiController(Observer& observer,
+                      LoginDisplayHost* host,
+                      AppLaunchSplashScreenView* splash_screen);
+  NetworkUiController(const NetworkUiController&) = delete;
+  NetworkUiController& operator=(const NetworkUiController&) = delete;
+  ~NetworkUiController() override;
+
+  void SetProfile(Profile* profile);
+  void UserRequestedNetworkConfig();
+  bool ShouldShowNetworkConfig();
+  void OnNetworkLostDuringInstallation();
+
+  // `AppLaunchSplashScreenView::Delegate`
+  void OnConfigureNetwork() override;
+  void OnNetworkConfigFinished() override;
+  void OnNetworkStateChanged(bool online) override;
+
+  // `KioskAppLauncher::NetworkDelegate`
+  void InitializeNetwork() override;
+  bool IsNetworkReady() const override;
+  bool IsShowingNetworkConfigScreen() const override;
+
+  NetworkUIState GetNetworkUiStateForTesting() const {
+    return network_ui_state_;
+  }
+
+  static void SetCanConfigureNetworkCallbackForTesting(
+      base::RepeatingCallback<bool()>* callback);
+  static void SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
+      base::RepeatingCallback<bool()>* callback);
+
+ private:
+  void MaybeShowNetworkConfigureUI();
+  void MaybeShowNetworkConfigureUIForConsumerKiosk();
+  void ShowNetworkConfigureUI();
+  void CloseNetworkConfigureUI();
+
+  void OnNetworkWaitTimeout();
+  bool CanConfigureNetwork();
+
+  void OnNetworkOnline();
+  void OnNetworkOffline();
+
+  const raw_ref<Observer> observer_;
+  const raw_ptr<LoginDisplayHost> host_;
+  const raw_ptr<AppLaunchSplashScreenView> splash_screen_view_;
+  raw_ptr<Profile> profile_ = nullptr;
+
+  NetworkUIState network_ui_state_ = kNotShowing;
+  bool network_required_ = false;
+
+  // A timer that fires when the network was not prepared and we require user
+  // network configuration to continue.
+  base::OneShotTimer network_wait_timer_;
+  bool network_wait_timeout_ = false;
+
+  base::WeakPtrFactory<NetworkUiController> weak_ptr_factory_{this};
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_LOGIN_APP_MODE_NETWORK_UI_CONTROLLER_H_
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_base_test.cc b/chrome/browser/ash/login/app_mode/test/kiosk_base_test.cc
index d0d1fe16..82e565d 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_base_test.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_base_test.cc
@@ -16,11 +16,14 @@
 #include "base/logging.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
+#include "base/test/test_future.h"
 #include "base/values.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/ash/login/app_mode/kiosk_launch_controller.h"
+#include "chrome/browser/ash/login/app_mode/network_ui_controller.h"
 #include "chrome/browser/ash/login/app_mode/test/kiosk_apps_mixin.h"
 #include "chrome/browser/ash/login/app_mode/test/kiosk_test_helpers.h"
+#include "chrome/browser/ash/login/screens/error_screen.h"
 #include "chrome/browser/ash/login/startup_utils.h"
 #include "chrome/browser/ash/login/test/js_checker.h"
 #include "chrome/browser/ash/login/test/oobe_screen_waiter.h"
@@ -58,9 +61,8 @@
   std::move(runner_quit_task).Run();
 }
 
-// Helper function for WaitForNetworkTimeOut.
-void OnNetworkWaitTimedOut(base::OnceClosure runner_quit_task) {
-  std::move(runner_quit_task).Run();
+void WaitForNetworkConfigureLink() {
+  test::OobeJS().CreateVisibilityWaiter(true, kConfigNetwork)->Wait();
 }
 
 }  // namespace
@@ -185,7 +187,6 @@
 void KioskBaseTest::TearDownOnMainThread() {
   owner_settings_service_.reset();
   settings_helper_.RestoreRealDeviceSettingsProvider();
-  KioskLaunchController::SetNetworkTimeoutCallbackForTesting(nullptr);
 
   OobeBaseTest::TearDownOnMainThread();
 }
@@ -322,19 +323,6 @@
                               true /* terminate_app */);
 }
 
-void KioskBaseTest::WaitForAppLaunchNetworkTimeout() {
-  if (GetKioskLaunchController()->network_wait_timedout()) {
-    return;
-  }
-
-  base::RunLoop loop;
-  base::OnceClosure callback =
-      base::BindOnce(&OnNetworkWaitTimedOut, loop.QuitClosure());
-  KioskLaunchController::SetNetworkTimeoutCallbackForTesting(&callback);
-  loop.Run();
-  ASSERT_TRUE(GetKioskLaunchController()->network_wait_timedout());
-}
-
 void KioskBaseTest::RunAppLaunchNetworkDownTest() {
   // Mock network could be configured with owner's password.
   ScopedCanConfigureNetwork can_configure_network(true, true);
@@ -344,13 +332,12 @@
       NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE);
   OobeScreenWaiter splash_waiter(AppLaunchSplashScreenView::kScreenId);
   splash_waiter.Wait();
-  WaitForAppLaunchNetworkTimeout();
 
-  // Configure network link should be visible.
-  test::OobeJS().ExpectVisiblePath(kConfigNetwork);
+  WaitForNetworkConfigureLink();
 
   // Configure network should bring up lock screen for owner.
-  static_cast<AppLaunchSplashScreenView::Delegate*>(GetKioskLaunchController())
+  GetKioskLaunchController()
+      ->GetNetworkUiControllerForTesting()
       ->OnConfigureNetwork();
   EXPECT_FALSE(LoginScreenTestApi::IsOobeDialogVisible());
   // There should be only one owner pod on this screen.
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc
index 64d80d5..f51fe00b 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc
@@ -11,6 +11,7 @@
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/public/cpp/shelf_test_api.h"
 #include "base/barrier_closure.h"
+#include "base/functional/bind.h"
 #include "base/test/bind.h"
 #include "base/test/gtest_tags.h"
 #include "base/test/test_future.h"
@@ -24,6 +25,7 @@
 #include "chrome/browser/ash/login/test/js_checker.h"
 #include "chrome/browser/ash/login/test/login_manager_mixin.h"
 #include "chrome/browser/ash/login/test/oobe_screen_waiter.h"
+#include "chrome/browser/ash/login/test/test_predicate_waiter.h"
 #include "chrome/browser/ash/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_settings_navigation_throttle.h"
 #include "chrome/browser/lifetime/termination_notification.h"
@@ -38,6 +40,7 @@
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/browser/ui/webui/ash/login/error_screen_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h"
+#include "chrome/grit/generated_resources.h"
 #include "chromeos/ash/components/network/portal_detector/network_portal_detector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
@@ -54,6 +57,7 @@
 #include "extensions/test/result_catcher.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/accelerators/accelerator.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
@@ -65,6 +69,8 @@
 
 const test::UIPath kErrorMessageContinueButton = {"error-message",
                                                   "continueButton"};
+const test::UIPath kSplashScreenLaunchText = {"app-launch-splash",
+                                              "launchText"};
 
 // An app to test local access to file systems via the
 // chrome.fileSystem.requestFileSystem API.
@@ -91,6 +97,15 @@
   return params;
 }
 
+void WaitForNetworkTimeoutMessage() {
+  test::TestPredicateWaiter(base::BindRepeating([]() {
+    return test::OobeJS().GetString(
+               ash::test::GetOobeElementPath(kSplashScreenLaunchText) +
+               ".textContent") ==
+           l10n_util::GetStringUTF8(IDS_APP_START_NETWORK_WAIT_TIMEOUT_MESSAGE);
+  })).Wait();
+}
+
 // Helper class to replace settings urls for KioskSettingsNavigationThrottle.
 class ScopedSettingsPages {
  public:
@@ -386,7 +401,8 @@
       NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE);
   OobeScreenWaiter splash_waiter(AppLaunchSplashScreenView::kScreenId);
   splash_waiter.Wait();
-  WaitForAppLaunchNetworkTimeout();
+
+  WaitForNetworkTimeoutMessage();
 
   // Configure network link should not be visible.
   test::OobeJS().ExpectHiddenPath(kConfigNetwork);
@@ -408,8 +424,6 @@
   app_splash_waiter.set_no_assert_last_screen();
   app_splash_waiter.Wait();
 
-  WaitForAppLaunchNetworkTimeout();
-
   // Network error should show up automatically since this test does not
   // require owner auth to configure network.
   OobeScreenWaiter(ErrorScreenView::kScreenId).Wait();
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_test_helpers.cc b/chrome/browser/ash/login/app_mode/test/kiosk_test_helpers.cc
index a584802..de214a0b 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_test_helpers.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_test_helpers.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
+#include "chrome/browser/ash/login/app_mode/network_ui_controller.h"
 #include "chrome/browser/ash/ownership/fake_owner_settings_service.h"
 #include "chrome/browser/profiles/profile_manager.h"
 
@@ -49,14 +50,14 @@
       needs_owner_auth_callback_(base::BindRepeating(
           &ScopedCanConfigureNetwork::NeedsOwnerAuthToConfigureNetwork,
           base::Unretained(this))) {
-  KioskLaunchController::SetCanConfigureNetworkCallbackForTesting(
+  NetworkUiController::SetCanConfigureNetworkCallbackForTesting(
       &can_configure_network_callback_);
-  KioskLaunchController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
+  NetworkUiController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
       &needs_owner_auth_callback_);
 }
 ScopedCanConfigureNetwork::~ScopedCanConfigureNetwork() {
-  KioskLaunchController::SetCanConfigureNetworkCallbackForTesting(nullptr);
-  KioskLaunchController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
+  NetworkUiController::SetCanConfigureNetworkCallbackForTesting(nullptr);
+  NetworkUiController::SetNeedOwnerAuthToConfigureNetworkCallbackForTesting(
       nullptr);
 }
 
diff --git a/chrome/browser/ash/login/screens/theme_selection_screen.cc b/chrome/browser/ash/login/screens/theme_selection_screen.cc
index 63bc722..6d63edd 100644
--- a/chrome/browser/ash/login/screens/theme_selection_screen.cc
+++ b/chrome/browser/ash/login/screens/theme_selection_screen.cc
@@ -120,10 +120,6 @@
   Profile* profile = ProfileManager::GetActiveUserProfile();
   const std::string& action_id = args[0].GetString();
 
-  // Set the nudge shown count to 0 once the user goes through the Dark / Light
-  // setup to avoiding triggering Dark / Light nudge after OOBE.
-  profile->GetPrefs()->SetInteger(prefs::kDarkLightModeNudgeLeftToShowCount, 0);
-
   if (action_id == kUserActionSelect) {
     const SelectedTheme selected_theme =
         static_cast<SelectedTheme>(args[1].GetInt());
diff --git a/chrome/browser/ash/login/screens/theme_selection_screen_browsertest.cc b/chrome/browser/ash/login/screens/theme_selection_screen_browsertest.cc
index 5992568..da434dda 100644
--- a/chrome/browser/ash/login/screens/theme_selection_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/theme_selection_screen_browsertest.cc
@@ -124,12 +124,7 @@
 
 IN_PROC_BROWSER_TEST_F(ThemeSelectionScreenTest, ProceedWithDefaultTheme) {
   ShowThemeSelectionScreen();
-  Profile* profile = ProfileManager::GetActiveUserProfile();
   test::OobeJS().ClickOnPath(kNextButtonPath);
-  // Verify that remaining nudge shown count is 0 after proceeding with the
-  // default theme.
-  EXPECT_EQ(0, profile->GetPrefs()->GetInteger(
-                   prefs::kDarkLightModeNudgeLeftToShowCount));
   WaitForScreenExit();
 
   EXPECT_THAT(
@@ -170,10 +165,6 @@
   test::OobeJS().ClickOnPath(kNextButtonPath);
   EXPECT_THAT(histogram_tester_.GetAllSamples(kSelectedThemeHistogram),
               ElementsAre(base::Bucket(static_cast<int>(theme), 1)));
-
-  // Verify that remaining nudge shown count is 0 after user selects the theme.
-  EXPECT_EQ(0, profile->GetPrefs()->GetInteger(
-                   prefs::kDarkLightModeNudgeLeftToShowCount));
   WaitForScreenExit();
 }
 
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc
index ff54e98..7988053 100644
--- a/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc
+++ b/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc
@@ -337,6 +337,7 @@
 
 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveAndLoadUserImage) {
   // Setup a user with JPEG image.
+  LoginUser(test_account_id1_);
   run_loop_ = std::make_unique<base::RunLoop>();
   const gfx::ImageSkia& image = default_user_image::GetStubDefaultImage();
   UserImageManager* user_image_manager =
@@ -385,6 +386,7 @@
 // Verifies that SaveUserImage() correctly sets and persists the chosen user
 // image.
 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImage) {
+  LoginUser(test_account_id1_);
   const user_manager::User* user =
       user_manager::UserManager::Get()->FindUser(test_account_id1_);
   ASSERT_TRUE(user);
@@ -422,6 +424,7 @@
 // Verifies that SaveUserImageFromFile() correctly sets and persists the chosen
 // user image.
 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImageFromFile) {
+  LoginUser(test_account_id1_);
   const user_manager::User* user =
       user_manager::UserManager::Get()->FindUser(test_account_id1_);
   ASSERT_TRUE(user);
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc
index b752d73..e87dada 100644
--- a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc
+++ b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc
@@ -27,6 +27,7 @@
 #include "base/values.h"
 #include "chrome/browser/ash/login/helper.h"
 #include "chrome/browser/ash/login/users/avatar/user_image_loader.h"
+#include "chrome/browser/ash/login/users/avatar/user_image_prefs.h"
 #include "chrome/browser/ash/login/users/avatar/user_image_sync_observer.h"
 #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -35,12 +36,14 @@
 #include "chrome/browser/profiles/profile_downloader.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/common/chrome_paths.h"
+#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/user_manager/user_image/user_image.h"
 #include "components/user_manager/user_manager.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
@@ -658,23 +661,26 @@
 
 void UserImageManagerImpl::SaveUserImage(
     std::unique_ptr<user_manager::UserImage> user_image) {
-  if (IsUserImageManaged())
+  if (IsUserImageManaged() || !IsCustomizationSelectorsPrefEnabled()) {
     return;
+  }
   job_ = std::make_unique<Job>(this);
   job_->SetToImage(user_manager::User::USER_IMAGE_EXTERNAL,
                    std::move(user_image));
 }
 
 void UserImageManagerImpl::SaveUserImageFromFile(const base::FilePath& path) {
-  if (IsUserImageManaged())
+  if (IsUserImageManaged() || !IsCustomizationSelectorsPrefEnabled()) {
     return;
+  }
   job_ = std::make_unique<Job>(this);
   job_->SetToPath(path, user_manager::User::USER_IMAGE_EXTERNAL, GURL(), true);
 }
 
 void UserImageManagerImpl::SaveUserImageFromProfileImage() {
-  if (IsUserImageManaged())
+  if (IsUserImageManaged() || !IsCustomizationSelectorsPrefEnabled()) {
     return;
+  }
   // Use the profile image if it has been downloaded already. Otherwise, use a
   // stub image (gray avatar).
   std::unique_ptr<user_manager::UserImage> user_image;
@@ -904,11 +910,10 @@
   }
 }
 
-// TODO(b/271606439): Check IsCustomizationSelectorsPrefEnabled() to disable
-// image download by policy.
 bool UserImageManagerImpl::NeedProfileImage() const {
   const user_manager::User* user = GetUser();
   return IsUserLoggedInAndHasGaiaAccount() &&
+         IsCustomizationSelectorsPrefEnabled() &&
          (user->image_index() == user_manager::User::USER_IMAGE_PROFILE ||
           profile_image_requested_);
 }
@@ -1000,4 +1005,12 @@
   return user->is_logged_in() && user->HasGaiaAccount();
 }
 
+bool UserImageManagerImpl::IsCustomizationSelectorsPrefEnabled() const {
+  const user_manager::User* user = GetUser();
+  content::BrowserContext* browser_context =
+      BrowserContextHelper::Get()->GetBrowserContextByUser(user);
+  Profile* profile = Profile::FromBrowserContext(browser_context);
+  return user_image::prefs::IsCustomizationSelectorsPrefEnabled(profile);
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.h b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.h
index 5bb94986..09f72264 100644
--- a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.h
+++ b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.h
@@ -161,6 +161,10 @@
   // Returns true if user with `user_id_` is logged in and has gaia account.
   bool IsUserLoggedInAndHasGaiaAccount() const;
 
+  // Returns true if user avatar customization selectors are enabled. Profile
+  // image download will only occur if this returns true
+  bool IsCustomizationSelectorsPrefEnabled() const;
+
   // The user manager.
   user_manager::UserManager* user_manager_;
 
diff --git a/chrome/browser/ash/login/users/avatar/user_image_prefs.cc b/chrome/browser/ash/login/users/avatar/user_image_prefs.cc
index 5709cbe2..61f756e 100644
--- a/chrome/browser/ash/login/users/avatar/user_image_prefs.cc
+++ b/chrome/browser/ash/login/users/avatar/user_image_prefs.cc
@@ -18,8 +18,7 @@
   registry->RegisterBooleanPref(kUserAvatarCustomizationSelectorsEnabled, true);
 }
 
-bool IsCustomizationSelectorsPrefEnabled() {
-  Profile* profile = ProfileManager::GetPrimaryUserProfile();
+bool IsCustomizationSelectorsPrefEnabled(Profile* profile) {
   PrefService* pref_service = profile->GetPrefs();
   return pref_service->GetBoolean(
       user_image::prefs::kUserAvatarCustomizationSelectorsEnabled);
diff --git a/chrome/browser/ash/login/users/avatar/user_image_prefs.h b/chrome/browser/ash/login/users/avatar/user_image_prefs.h
index 35515dd..ec58423 100644
--- a/chrome/browser/ash/login/users/avatar/user_image_prefs.h
+++ b/chrome/browser/ash/login/users/avatar/user_image_prefs.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_USER_IMAGE_PREFS_H_
 #define CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_USER_IMAGE_PREFS_H_
 
+#include "chrome/browser/profiles/profile.h"
+
 class PrefRegistrySimple;
 
 namespace ash::user_image::prefs {
@@ -17,7 +19,7 @@
 void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
 // Returns boolean value of the kUserAvatarCustomizationSelectorsEnabled pref.
-bool IsCustomizationSelectorsPrefEnabled();
+bool IsCustomizationSelectorsPrefEnabled(Profile* profile);
 
 }  // namespace ash::user_image::prefs
 
diff --git a/chrome/browser/ash/note_taking_helper.cc b/chrome/browser/ash/note_taking_helper.cc
index 17bbce7f..5c8f6e6 100644
--- a/chrome/browser/ash/note_taking_helper.cc
+++ b/chrome/browser/ash/note_taking_helper.cc
@@ -658,7 +658,7 @@
     return LaunchResult::CHROME_APP_MISSING;
   }
   app_runtime::ActionData action_data;
-  action_data.action_type = app_runtime::ActionType::ACTION_TYPE_NEW_NOTE;
+  action_data.action_type = app_runtime::ActionType::kNewNote;
   launch_chrome_app_callback_.Run(profile, app, std::move(action_data));
   return LaunchResult::CHROME_SUCCESS;
 }
diff --git a/chrome/browser/ash/note_taking_helper_unittest.cc b/chrome/browser/ash/note_taking_helper_unittest.cc
index 62341b1..201003b 100644
--- a/chrome/browser/ash/note_taking_helper_unittest.cc
+++ b/chrome/browser/ash/note_taking_helper_unittest.cc
@@ -384,7 +384,7 @@
         extensions::ListBuilder()
             .Append(extensions::DictionaryBuilder()
                         .Set("action", app_runtime::ToString(
-                                           app_runtime::ACTION_TYPE_NEW_NOTE))
+                                           app_runtime::ActionType::kNewNote))
                         .Set("enabled_on_lock_screen", true)
                         .Build())
             .Build();
@@ -487,8 +487,7 @@
                        const extensions::Extension* extension,
                        app_runtime::ActionData action_data) {
     EXPECT_EQ(profile(), passed_context);
-    EXPECT_EQ(app_runtime::ActionType::ACTION_TYPE_NEW_NOTE,
-              action_data.action_type);
+    EXPECT_EQ(app_runtime::ActionType::kNewNote, action_data.action_type);
     launched_chrome_apps_.push_back(ChromeAppLaunchInfo{extension->id()});
   }
 
@@ -574,7 +573,7 @@
 
   base::Value::List lock_disabled_action_handler =
       extensions::ListBuilder()
-          .Append(app_runtime::ToString(app_runtime::ACTION_TYPE_NEW_NOTE))
+          .Append(app_runtime::ToString(app_runtime::ActionType::kNewNote))
           .Build();
 
   // Install Keep app that does not support lock screen note taking - it should
@@ -724,7 +723,7 @@
   scoped_refptr<const extensions::Extension> has_new_note = CreateExtension(
       kNewNoteId, kName, /*permissions=*/absl::nullopt,
       extensions::ListBuilder()
-          .Append(app_runtime::ToString(app_runtime::ACTION_TYPE_NEW_NOTE))
+          .Append(app_runtime::ToString(app_runtime::ActionType::kNewNote))
           .Build());
   InstallExtension(has_new_note.get(), profile());
   // "action_handlers": []
@@ -875,7 +874,7 @@
   scoped_refptr<const extensions::Extension> extension = CreateExtension(
       kProdKeepExtensionId, "Keep", /*permissions=*/absl::nullopt,
       extensions::ListBuilder()
-          .Append(app_runtime::ToString(app_runtime::ACTION_TYPE_NEW_NOTE))
+          .Append(app_runtime::ToString(app_runtime::ActionType::kNewNote))
           .Build());
   InstallExtension(extension.get(), profile());
 
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller.cc
index f66b84e..2ebf821 100644
--- a/chrome/browser/ash/policy/dlp/dlp_files_controller.cc
+++ b/chrome/browser/ash/policy/dlp/dlp_files_controller.cc
@@ -109,29 +109,24 @@
 }
 
 // Returns a `DlpFileDestination` with a source URL or component, based on
-// |app_update|.
-DlpFileDestination GetFileDestinationForApp(const apps::AppUpdate& app_update) {
-  DlpFileDestination destination;
+// |app_update|. If neither URL nor component can be found, returns nullopt.
+absl::optional<DlpFileDestination> GetFileDestinationForApp(
+    const apps::AppUpdate& app_update) {
   switch (app_update.AppType()) {
     case apps::AppType::kStandaloneBrowserChromeApp:
     case apps::AppType::kExtension:
     case apps::AppType::kStandaloneBrowserExtension:
     case apps::AppType::kChromeApp:
-      destination.url_or_path = base::StrCat(
-          {extensions::kExtensionScheme, "://", app_update.AppId()});
-      break;
+      return DlpFileDestination(base::StrCat(
+          {extensions::kExtensionScheme, "://", app_update.AppId()}));
     case apps::AppType::kArc:
-      destination.component = DlpRulesManager::Component::kArc;
-      break;
+      return DlpFileDestination(DlpRulesManager::Component::kArc);
     case apps::AppType::kCrostini:
-      destination.component = DlpRulesManager::Component::kCrostini;
-      break;
+      return DlpFileDestination(DlpRulesManager::Component::kCrostini);
     case apps::AppType::kPluginVm:
-      destination.component = DlpRulesManager::Component::kPluginVm;
-      break;
+      return DlpFileDestination(DlpRulesManager::Component::kPluginVm);
     case apps::AppType::kWeb:
-      destination.url_or_path = app_update.PublisherId();
-      break;
+      return DlpFileDestination(app_update.PublisherId());
     case apps::AppType::kUnknown:
     case apps::AppType::kBuiltIn:
     case apps::AppType::kMacOs:
@@ -140,9 +135,9 @@
     case apps::AppType::kBorealis:
     case apps::AppType::kBruschetta:
     case apps::AppType::kSystemWeb:
-      break;
+      return absl::nullopt;
   }
-  return destination;
+  return absl::nullopt;
 }
 
 std::vector<absl::optional<ino64_t>> GetFilesInodes(
@@ -188,12 +183,12 @@
 absl::optional<DlpRulesManager::Component> MaybeGetComponent(
     Profile* profile,
     const DlpFileDestination& destination) {
-  if (destination.component.has_value()) {
-    return destination.component;
+  if (destination.component().has_value()) {
+    return destination.component();
   }
-  DCHECK(destination.url_or_path.has_value());
-  return MapFilePathtoPolicyComponent(profile,
-                                      base::FilePath(*destination.url_or_path));
+  DCHECK(destination.url_or_path().has_value());
+  return MapFilePathtoPolicyComponent(
+      profile, base::FilePath(*destination.url_or_path()));
 }
 
 // Maps |component| to ::dlp::DlpComponent.
@@ -765,13 +760,13 @@
     return;
   }
 
-  if (!download_src.url_or_path.has_value()) {
+  if (!download_src.url_or_path().has_value()) {
     // Currently we only support urls as sources.
     std::move(result_callback).Run(true);
     return;
   }
 
-  FileDaemonInfo file_info({}, file_path, download_src.url_or_path.value());
+  FileDaemonInfo file_info({}, file_path, download_src.url_or_path().value());
   IsFilesTransferRestricted(
       {std::move(file_info)}, DlpFileDestination(file_path.value()),
       FileAction::kDownload,
@@ -803,7 +798,7 @@
 bool DlpFilesController::ShouldPromptBeforeDownload(
     const DlpFileDestination& download_src,
     const base::FilePath& file_path) {
-  if (!download_src.url_or_path.has_value()) {
+  if (!download_src.url_or_path().has_value()) {
     return false;
   }
   auto* profile = ProfileManager::GetPrimaryUserProfile();
@@ -817,7 +812,7 @@
   }
 
   DlpRulesManager::Level level = rules_manager_.IsRestrictedComponent(
-      GURL(download_src.url_or_path.value()), dst_component.value(),
+      GURL(download_src.url_or_path().value()), dst_component.value(),
       DlpRulesManager::Restriction::kFiles, /*out_source_pattern=*/nullptr,
       /*out_rule_metadata=*/nullptr);
   return level == DlpRulesManager::Level::kBlock ||
@@ -843,12 +838,15 @@
   request.set_file_action(intent->IsShareIntent() ? ::dlp::FileAction::SHARE
                                                   : ::dlp::FileAction::OPEN);
 
-  DlpFileDestination destination = GetFileDestinationForApp(app_update);
-  if (destination.url_or_path.has_value()) {
-    request.set_destination_url(destination.url_or_path.value());
-  } else if (destination.component.has_value()) {
-    request.set_destination_component(
-        MapPolicyComponentToProto(destination.component.value()));
+  absl::optional<DlpFileDestination> destination =
+      GetFileDestinationForApp(app_update);
+  if (destination.has_value()) {
+    if (destination->url_or_path().has_value()) {
+      request.set_destination_url(destination->url_or_path().value());
+    } else if (destination->component().has_value()) {
+      request.set_destination_component(
+          MapPolicyComponentToProto(destination->component().value()));
+    }
   }
 
   chromeos::DlpClient::Get()->CheckFilesTransfer(
@@ -863,23 +861,29 @@
     return false;
   }
 
-  DlpFileDestination destination = GetFileDestinationForApp(app_update);
+  absl::optional<DlpFileDestination> destination =
+      GetFileDestinationForApp(app_update);
+
+  if (!destination.has_value()) {
+    return false;
+  }
+
   for (const auto& file : intent->files) {
     if (!file->dlp_source_url.has_value()) {
       continue;
     }
-    if (destination.url_or_path.has_value()) {
+    if (destination->url_or_path().has_value()) {
       DlpRulesManager::Level level = rules_manager_.IsRestrictedDestination(
           GURL(file->dlp_source_url.value()),
-          GURL(destination.url_or_path.value()),
+          GURL(destination->url_or_path().value()),
           DlpRulesManager::Restriction::kFiles, /*out_source_pattern=*/nullptr,
           /*out_destination_pattern=*/nullptr, /*out_rule_metadata=*/nullptr);
       if (level == DlpRulesManager::Level::kBlock) {
         return true;
       }
-    } else if (destination.component.has_value()) {
+    } else if (destination->component().has_value()) {
       DlpRulesManager::Level level = rules_manager_.IsRestrictedComponent(
-          GURL(file->dlp_source_url.value()), destination.component.value(),
+          GURL(file->dlp_source_url.value()), destination->component().value(),
           DlpRulesManager::Restriction::kFiles, /*out_source_pattern=*/nullptr,
           /*out_rule_metadata=*/nullptr);
       if (level == DlpRulesManager::Level::kBlock) {
@@ -924,10 +928,10 @@
     } else {
       // TODO(crbug.com/1286366): Revisit whether passing files paths here
       // make sense.
-      DCHECK(destination.url_or_path.has_value());
+      DCHECK(destination.url_or_path().has_value());
       destination_pattern = std::string();
       level = rules_manager_.IsRestrictedDestination(
-          GURL(file.source_url), GURL(*destination.url_or_path),
+          GURL(file.source_url), GURL(*destination.url_or_path()),
           DlpRulesManager::Restriction::kFiles, &source_pattern,
           &destination_pattern.value(), &rule_metadata);
       MaybeReportEvent(file.inode, file.path, source_pattern, actual_dst,
@@ -1253,11 +1257,11 @@
         is_restricted_for_destination =
             dst_level == DlpRulesManager::Level::kBlock;
       } else {
-        DCHECK(destination->url_or_path.has_value());
+        DCHECK(destination->url_or_path().has_value());
         DlpRulesManager::Level dst_level =
             rules_manager_.IsRestrictedDestination(
                 GURL(metadata.source_url()),
-                GURL(destination->url_or_path.value()),
+                GURL(destination->url_or_path().value()),
                 DlpRulesManager::Restriction::kFiles, nullptr, nullptr,
                 nullptr);
         is_restricted_for_destination =
@@ -1371,11 +1375,11 @@
   event_builder->SetContentName(path.BaseName().value());
 
   if (dst_pattern.has_value()) {
-    DCHECK(!dst.component.has_value());
+    DCHECK(!dst.component().has_value());
     event_builder->SetDestinationPattern(dst_pattern.value());
   } else {
-    DCHECK(dst.component.has_value());
-    event_builder->SetDestinationComponent(dst.component.value());
+    DCHECK(dst.component().has_value());
+    event_builder->SetDestinationComponent(dst.component().value());
   }
   reporting_manager->ReportEvent(event_builder->Create());
 }
@@ -1439,12 +1443,12 @@
   for (const auto& file : uploaded_files) {
     request.add_files_paths(file.path().value());
   }
-  if (destination.component.has_value()) {
+  if (destination.component().has_value()) {
     request.set_destination_component(
-        MapPolicyComponentToProto(destination.component.value()));
+        MapPolicyComponentToProto(destination.component().value()));
   } else {
-    DCHECK(destination.url_or_path.has_value());
-    request.set_destination_url(destination.url_or_path.value());
+    DCHECK(destination.url_or_path().has_value());
+    request.set_destination_url(destination.url_or_path().value());
   }
   request.set_file_action(::dlp::FileAction::UPLOAD);
 
@@ -1470,12 +1474,12 @@
   for (const auto& file : dropped_files) {
     request.add_files_paths(file.path().value());
   }
-  if (destination.component.has_value()) {
+  if (destination.component().has_value()) {
     request.set_destination_component(
-        MapPolicyComponentToProto(destination.component.value()));
+        MapPolicyComponentToProto(destination.component().value()));
   } else {
-    DCHECK(destination.url_or_path.has_value());
-    request.set_destination_url(destination.url_or_path.value());
+    DCHECK(destination.url_or_path().has_value());
+    request.set_destination_url(destination.url_or_path().value());
   }
   request.set_file_action(::dlp::FileAction::MOVE);
 
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_event_storage.cc b/chrome/browser/ash/policy/dlp/dlp_files_event_storage.cc
index d180ecb..f5de9ab 100644
--- a/chrome/browser/ash/policy/dlp/dlp_files_event_storage.cc
+++ b/chrome/browser/ash/policy/dlp/dlp_files_event_storage.cc
@@ -48,10 +48,10 @@
     // Skip reporting if we don't know the destination (i.e., it is
     // kUnknownComponent) and at least an entry for `inode` is stored in
     // `events_`.
-    return (dst.component.has_value() &&
-            dst.component.value() !=
+    return (dst.component().has_value() &&
+            dst.component().value() !=
                 DlpRulesManager::Component::kUnknownComponent) ||
-           dst.url_or_path.has_value();
+           dst.url_or_path().has_value();
   }
 
   // Found existing (inode, dst) pair, update it
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl.cc
index 747bbfd..59d1ce25 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl.cc
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ash/camera_presence_notifier.h"
 #include "chrome/browser/ash/login/users/avatar/user_image_file_selector.h"
 #include "chrome/browser/ash/login/users/avatar/user_image_manager.h"
+#include "chrome/browser/ash/login/users/avatar/user_image_prefs.h"
 #include "chrome/browser/ash/login/users/chrome_user_manager.h"
 #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -26,6 +27,7 @@
 #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_manager_factory.h"
 #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_utils.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/prefs/pref_service.h"
 #include "components/user_manager/user_image/user_image.h"
 #include "components/user_manager/user_info.h"
 #include "components/user_manager/user_manager.h"
@@ -162,6 +164,10 @@
 }
 
 void PersonalizationAppUserProviderImpl::SelectImageFromDisk() {
+  if (!IsCustomizationSelectorsPrefEnabled()) {
+    user_receiver_.ReportBadMessage("Not allowed to select image file");
+    return;
+  }
   user_image_file_selector_->SelectFile(
       base::BindOnce(&PersonalizationAppUserProviderImpl::OnFileSelected,
                      weak_ptr_factory_.GetWeakPtr()),
@@ -186,6 +192,11 @@
 }
 
 void PersonalizationAppUserProviderImpl::SelectProfileImage() {
+  if (!IsCustomizationSelectorsPrefEnabled()) {
+    user_receiver_.ReportBadMessage("Not allowed to select profile image");
+    return;
+  }
+
   if (GetUser(profile_)->image_index() !=
       user_manager::User::USER_IMAGE_PROFILE) {
     ash::UserImageManager::RecordUserImageChanged(
@@ -201,6 +212,10 @@
 
 void PersonalizationAppUserProviderImpl::SelectCameraImage(
     ::mojo_base::BigBuffer data) {
+  if (!IsCustomizationSelectorsPrefEnabled()) {
+    user_receiver_.ReportBadMessage("Not allowed to select camera image");
+    return;
+  }
   // Make a copy of the data.
   auto ref_counted =
       base::MakeRefCounted<base::RefCountedBytes>(data.data(), data.size());
@@ -215,6 +230,12 @@
 }
 
 void PersonalizationAppUserProviderImpl::SelectLastExternalUserImage() {
+  if (!IsCustomizationSelectorsPrefEnabled()) {
+    user_receiver_.ReportBadMessage(
+        "Not allowed to select last external image");
+    return;
+  }
+
   if (!last_external_user_image_) {
     LOG(WARNING) << "No last external user image present";
     return;
@@ -385,6 +406,10 @@
           mojo_base::BigBuffer(std::move(encoded_png))));
 }
 
+bool PersonalizationAppUserProviderImpl::IsCustomizationSelectorsPrefEnabled() {
+  return user_image::prefs::IsCustomizationSelectorsPrefEnabled(profile_);
+}
+
 void PersonalizationAppUserProviderImpl::UpdateUserImageObserver(
     ash::personalization_app::mojom::UserImagePtr user_image) {
   user_image_observer_remote_->OnUserImageChanged(std::move(user_image));
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl.h b/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl.h
index c338fc1..7f032ec 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl.h
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl.h
@@ -66,6 +66,8 @@
   // avatar page for Personalization HaTS.
   void GetDefaultUserImages(GetDefaultUserImagesCallback callback) override;
 
+  bool IsCustomizationSelectorsPrefEnabled() override;
+
   void SelectImageFromDisk() override;
 
   void SelectDefaultImage(int index) override;
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl_unittest.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl_unittest.cc
index 105287d3..78a571b 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl_unittest.cc
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl_unittest.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ash/login/users/avatar/mock_user_image_manager.h"
 #include "chrome/browser/ash/login/users/avatar/user_image_manager.h"
 #include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h"
+#include "chrome/browser/ash/login/users/avatar/user_image_prefs.h"
 #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/ash/login/users/scoped_test_user_manager.h"
@@ -38,6 +39,7 @@
 #include "mojo/public/cpp/base/big_buffer.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -241,6 +243,11 @@
     return test_user_image_observer_.is_enterprise_managed();
   }
 
+  void disable_customization_selectors() {
+    profile()->GetPrefs()->SetBoolean(
+        user_image::prefs::kUserAvatarCustomizationSelectorsEnabled, false);
+  }
+
   const base::HistogramTester& histogram_tester() { return histogram_tester_; }
 
  private:
@@ -517,6 +524,46 @@
             current_user_image()->get_default_image().source_info->website);
 }
 
+TEST_F(PersonalizationAppUserProviderImplTest, SelectProfileImageDisabled) {
+  mojo::test::BadMessageObserver bad_message_observer;
+  disable_customization_selectors();
+
+  user_provider_remote()->get()->SelectProfileImage();
+  EXPECT_EQ(bad_message_observer.WaitForBadMessage(),
+            "Not allowed to select profile image");
+}
+
+TEST_F(PersonalizationAppUserProviderImplTest, SelectCameraImageDisabled) {
+  mojo::test::BadMessageObserver bad_message_observer;
+  disable_customization_selectors();
+
+  user_provider_remote()->get()->SelectCameraImage(FakeEncodedPngBuffer());
+
+  EXPECT_EQ(bad_message_observer.WaitForBadMessage(),
+            "Not allowed to select camera image");
+}
+
+TEST_F(PersonalizationAppUserProviderImplTest,
+       SelectLastExternalUserImageDisabled) {
+  mojo::test::BadMessageObserver bad_message_observer;
+  disable_customization_selectors();
+
+  user_provider_remote()->get()->SelectLastExternalUserImage();
+
+  EXPECT_EQ(bad_message_observer.WaitForBadMessage(),
+            "Not allowed to select last external image");
+}
+
+TEST_F(PersonalizationAppUserProviderImplTest, SelectImageFromDiskDisabled) {
+  mojo::test::BadMessageObserver bad_message_observer;
+  disable_customization_selectors();
+
+  user_provider_remote()->get()->SelectImageFromDisk();
+
+  EXPECT_EQ(bad_message_observer.WaitForBadMessage(),
+            "Not allowed to select image file");
+}
+
 class PersonalizationAppUserProviderImplWithMockTest
     : public PersonalizationAppUserProviderImplTest {
  protected:
diff --git a/chrome/browser/autocomplete/keyword_extensions_delegate_impl_unittest.cc b/chrome/browser/autocomplete/keyword_extensions_delegate_impl_unittest.cc
index 9b95917..0734b18 100644
--- a/chrome/browser/autocomplete/keyword_extensions_delegate_impl_unittest.cc
+++ b/chrome/browser/autocomplete/keyword_extensions_delegate_impl_unittest.cc
@@ -46,7 +46,7 @@
 
 void KeywordExtensionsDelegateImplTest::SetUp() {
   ExtensionServiceTestBase::SetUp();
-  InitializeExtensionService(CreateDefaultInitParams());
+  InitializeExtensionService(ExtensionServiceInitParams());
 }
 
 void KeywordExtensionsDelegateImplTest::RunTest(bool incognito) {
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 05e82e2..0b9467e 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -1444,7 +1444,6 @@
 };
 
 // Test the basic form-fill flow.
-// TODO(https://crbug.com/1045709): Check back if flakiness is fixed now.
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, BasicFormFill) {
   CreateTestProfile();
   SetTestUrlResponse(kTestShippingFormString);
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
index 9c637106..a10ec53 100644
--- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
+++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
@@ -34,6 +34,7 @@
  */
 public class BackPressManager implements Destroyable {
     private static final SparseIntArray sMetricsMap;
+    private static final int sMetricsMaxValue;
     static {
         // Max value is 18 - 1 obsolete value +1 for 0 indexing = 18 elements.
         SparseIntArray map = new SparseIntArray(18);
@@ -56,6 +57,7 @@
         map.put(Type.FIND_TOOLBAR, 16);
         map.put(Type.LOCATION_BAR, 17);
         map.put(Type.XR_DELEGATE, 18);
+        sMetricsMaxValue = 19;
         // Add new one here and update array size.
         sMetricsMap = map;
     }
@@ -97,12 +99,13 @@
      * @param type The {@link Type} which consumes the back press event.
      */
     public static void record(@Type int type) {
-        RecordHistogram.recordEnumeratedHistogram(HISTOGRAM, sMetricsMap.get(type), Type.NUM_TYPES);
+        RecordHistogram.recordEnumeratedHistogram(
+                HISTOGRAM, sMetricsMap.get(type), sMetricsMaxValue);
     }
 
     private static void recordFailure(@Type int type) {
         RecordHistogram.recordEnumeratedHistogram(
-                FAILURE_HISTOGRAM, sMetricsMap.get(type), Type.NUM_TYPES);
+                FAILURE_HISTOGRAM, sMetricsMap.get(type), sMetricsMaxValue);
     }
 
     public BackPressManager() {
@@ -217,6 +220,9 @@
                 removeHandler(i);
             }
         }
+        // All handlers have been removed, so no handler will consume the back event. As a result,
+        // the callback should be disabled so that the OS can handle the back press.
+        assert !mCallback.isEnabled();
     }
 
     private void assertListOfFailedHandlers(List<String> failed, int succeed) {
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandler.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandler.java
index cccab2c..3afd921 100644
--- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandler.java
+++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandler.java
@@ -42,6 +42,7 @@
     private final Callback<Tab> mOnTabChanged = this::onTabChanged;
     private final ObservableSupplier<Tab> mActivityTabSupplier;
     private final Runnable mCallbackOnBackPress;
+    private final boolean mUseSystemBack;
 
     private static Integer sVersionForTesting;
 
@@ -109,9 +110,10 @@
         mBackShouldCloseTab = backShouldCloseTab;
         mSendToBackground = sendToBackground;
         mActivityTabSupplier = activityTabSupplier;
-        mBackPressSupplier.set(!shouldUseSystemBack());
+        mUseSystemBack = shouldUseSystemBack();
+        mBackPressSupplier.set(!mUseSystemBack);
         mCallbackOnBackPress = callbackOnBackPress;
-        if (shouldUseSystemBack()) {
+        if (mUseSystemBack) {
             mActivityTabSupplier.addObserver(mOnTabChanged);
         }
     }
@@ -123,7 +125,7 @@
         Tab currentTab = mActivityTabSupplier.get();
 
         if (currentTab == null) {
-            assert !shouldUseSystemBack()
+            assert !mUseSystemBack
                 : "Should be disabled when there is no valid tab and back press will be consumed.";
             minimizeApp = true;
             shouldCloseTab = false;
@@ -150,7 +152,7 @@
                                   : MinimizeAppAndCloseTabType.MINIMIZE_APP);
             // If system back is enabled, we should let system handle the back press when
             // no tab is about to be closed.
-            assert shouldCloseTab || !shouldUseSystemBack();
+            assert shouldCloseTab || !mUseSystemBack;
             mSendToBackground.onResult(shouldCloseTab ? currentTab : null);
         } else { // shouldCloseTab is always true if minimizeApp is false.
             record(MinimizeAppAndCloseTabType.CLOSE_TAB);
@@ -171,7 +173,7 @@
     }
 
     private void onTabChanged(Tab tab) {
-        assert shouldUseSystemBack() : "Should not observe changes when system back is disabled";
+        assert mUseSystemBack : "Should not observe changes when system back is disabled";
         mBackPressSupplier.set(tab != null && mBackShouldCloseTab.test(tab));
     }
 
diff --git a/chrome/browser/banners/app_banner_manager_desktop.h b/chrome/browser/banners/app_banner_manager_desktop.h
index 607f02c..cd9ec00 100644
--- a/chrome/browser/banners/app_banner_manager_desktop.h
+++ b/chrome/browser/banners/app_banner_manager_desktop.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
+#include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/webapps/browser/banners/app_banner_manager.h"
 #include "content/public/browser/web_contents_user_data.h"
 
diff --git a/chrome/browser/chromeos/extensions/action_handlers/action_handlers_apitest.cc b/chrome/browser/chromeos/extensions/action_handlers/action_handlers_apitest.cc
index 764eeb3..ba3263e 100644
--- a/chrome/browser/chromeos/extensions/action_handlers/action_handlers_apitest.cc
+++ b/chrome/browser/chromeos/extensions/action_handlers/action_handlers_apitest.cc
@@ -22,13 +22,13 @@
   const extensions::Extension* app = LoadExtension(path);
   ASSERT_TRUE(app);
   EXPECT_TRUE(extensions::ActionHandlersInfo::HasActionHandler(
-      app, app_runtime::ACTION_TYPE_NEW_NOTE));
+      app, app_runtime::ActionType::kNewNote));
   EXPECT_TRUE(loader.WaitUntilSatisfied());
 
   // Fire a "new_note" action type, assert that app has received it.
   ExtensionTestMessageListener new_note("hasNewNote = true");
   app_runtime::ActionData action_data;
-  action_data.action_type = app_runtime::ActionType::ACTION_TYPE_NEW_NOTE;
+  action_data.action_type = app_runtime::ActionType::kNewNote;
   apps::LaunchPlatformAppWithAction(profile(), app, std::move(action_data));
   EXPECT_TRUE(new_note.WaitUntilSatisfied());
 }
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_file_destination.cc b/chrome/browser/chromeos/policy/dlp/dlp_file_destination.cc
index ac2e659..22f70da 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_file_destination.cc
+++ b/chrome/browser/chromeos/policy/dlp/dlp_file_destination.cc
@@ -6,12 +6,11 @@
 
 namespace policy {
 
-DlpFileDestination::DlpFileDestination() = default;
 DlpFileDestination::DlpFileDestination(const std::string& url)
-    : url_or_path(url) {}
+    : url_or_path_(url) {}
 DlpFileDestination::DlpFileDestination(
     const DlpRulesManager::Component component)
-    : component(component) {}
+    : component_(component) {}
 
 DlpFileDestination::DlpFileDestination(const DlpFileDestination&) = default;
 DlpFileDestination& DlpFileDestination::operator=(const DlpFileDestination&) =
@@ -20,24 +19,24 @@
 DlpFileDestination& DlpFileDestination::operator=(DlpFileDestination&&) =
     default;
 bool DlpFileDestination::operator==(const DlpFileDestination& other) const {
-  return component == other.component && url_or_path == other.url_or_path;
+  return component_ == other.component_ && url_or_path_ == other.url_or_path_;
 }
 bool DlpFileDestination::operator!=(const DlpFileDestination& other) const {
   return !(*this == other);
 }
 bool DlpFileDestination::operator<(const DlpFileDestination& other) const {
-  if (component.has_value() && other.component.has_value()) {
-    return static_cast<int>(component.value()) <
-           static_cast<int>(other.component.value());
+  if (component_.has_value() && other.component_.has_value()) {
+    return static_cast<int>(component_.value()) <
+           static_cast<int>(other.component_.value());
   }
-  if (component.has_value()) {
+  if (component_.has_value()) {
     return true;
   }
-  if (other.component.has_value()) {
+  if (other.component_.has_value()) {
     return false;
   }
-  DCHECK(url_or_path.has_value() && other.url_or_path.has_value());
-  return url_or_path.value() < other.url_or_path.value();
+  DCHECK(url_or_path_.has_value() && other.url_or_path_.has_value());
+  return url_or_path_.value() < other.url_or_path_.value();
 }
 bool DlpFileDestination::operator<=(const DlpFileDestination& other) const {
   return *this == other || *this < other;
@@ -51,4 +50,13 @@
 
 DlpFileDestination::~DlpFileDestination() = default;
 
+absl::optional<std::string> DlpFileDestination::url_or_path() const {
+  return url_or_path_;
+}
+
+absl::optional<DlpRulesManager::Component> DlpFileDestination::component()
+    const {
+  return component_;
+}
+
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_file_destination.h b/chrome/browser/chromeos/policy/dlp/dlp_file_destination.h
index b92feb5c..a136e25 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_file_destination.h
+++ b/chrome/browser/chromeos/policy/dlp/dlp_file_destination.h
@@ -13,9 +13,9 @@
 namespace policy {
 // DlpFileDestination represents the destination for file transfer. It either
 // has a url or a component.
-// TODO(b/275302531): Change to a class.
-struct DlpFileDestination {
-  DlpFileDestination();
+class DlpFileDestination {
+ public:
+  DlpFileDestination() = delete;
   explicit DlpFileDestination(const std::string& url);
   explicit DlpFileDestination(const DlpRulesManager::Component component);
 
@@ -33,10 +33,15 @@
 
   ~DlpFileDestination();
 
+  absl::optional<std::string> url_or_path() const;
+
+  absl::optional<DlpRulesManager::Component> component() const;
+
+ private:
   // Destination url or destination path.
-  absl::optional<std::string> url_or_path;
+  absl::optional<std::string> url_or_path_;
   // Destination component.
-  absl::optional<DlpRulesManager::Component> component;
+  absl::optional<DlpRulesManager::Component> component_;
 };
 
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_warn_dialog.cc b/chrome/browser/chromeos/policy/dlp/dlp_warn_dialog.cc
index 5242fd52..d4418f8 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_warn_dialog.cc
+++ b/chrome/browser/chromeos/policy/dlp/dlp_warn_dialog.cc
@@ -88,9 +88,9 @@
 // obtained, or the full value otherwise, converted to u16string. Fails if
 // |url_or_path| is empty.
 std::u16string GetDestinationURLForFiles(DlpFileDestination destination) {
-  DCHECK(destination.url_or_path.has_value());
-  DCHECK(!destination.url_or_path->empty());
-  std::string url = destination.url_or_path.value();
+  DCHECK(destination.url_or_path().has_value());
+  DCHECK(!destination.url_or_path()->empty());
+  std::string url = destination.url_or_path().value();
   GURL gurl(url);
   if (gurl.is_valid() && gurl.has_host()) {
     return base::UTF8ToUTF16(gurl.host());
@@ -102,8 +102,8 @@
 // if |component| is empty.
 const std::u16string GetDestinationComponentForFiles(
     DlpFileDestination destination) {
-  DCHECK(destination.component.has_value());
-  switch (destination.component.value()) {
+  DCHECK(destination.component().has_value());
+  switch (destination.component().value()) {
     case DlpRulesManager::Component::kArc:
       return l10n_util::GetStringUTF16(
           IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL);
@@ -126,7 +126,7 @@
 // Returns the u16string formatted |destination|. Fails if both |component| and
 // |url_or_path| are empty. Returns the |component| if both are non-empty.
 const std::u16string GetDestinationForFiles(DlpFileDestination destination) {
-  return destination.component.has_value()
+  return destination.component().has_value()
              ? GetDestinationComponentForFiles(destination)
              : GetDestinationURLForFiles(destination);
 }
diff --git a/chrome/browser/creator/android/java/res/values/ids.xml b/chrome/browser/creator/android/java/res/values/ids.xml
index d776e90..2d439d78 100644
--- a/chrome/browser/creator/android/java/res/values/ids.xml
+++ b/chrome/browser/creator/android/java/res/values/ids.xml
@@ -9,4 +9,7 @@
 <resources>
   <!-- Id to use for Content Previews RecyclerView. -->
   <item type="id" name="creator_feed_stream_recycler_view" />
+
+  <!-- Id to use for Content Preview Bottom Sheet. -->
+  <item type="id" name="creator_content_preview_bottom_sheet" />
 </resources>
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
index 2bb3665c..bad1b13 100644
--- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
+++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
@@ -374,6 +374,7 @@
         }, mCreatorViewGroup, mActivity.getResources().getColor(R.color.default_scrim_color));
 
         mBottomSheetContainer = new FrameLayout(mActivity);
+        mBottomSheetContainer.setId(R.id.creator_content_preview_bottom_sheet);
         mBottomSheetContainer.setLayoutParams(
                 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
         mCreatorViewGroup.addView(mBottomSheetContainer);
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java
index 9764be1..336c802b 100644
--- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java
+++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java
@@ -316,4 +316,16 @@
                 mFeedActionDelegate, mHelpAndFeedbackLauncher, mShareDelegateSupplier);
         verify(mWebFeedBridgeJniMock).queryWebFeed(anyString(), any());
     }
+
+    @Test
+    public void testCreatorCoordinator_InitializeBottomSheetView() {
+        CreatorCoordinator creatorCoordinator = newCreatorCoordinator(
+                mUrlDefault, mWebFeedIdDefault, mEntryPointDefault, mFollowingDefault);
+        ViewGroup creatorViewGroup = creatorCoordinator.getView();
+        assertEquals(creatorViewGroup.getChildCount(), 2);
+        View contentPreviewsBottomSheet =
+                creatorViewGroup.findViewById(R.id.creator_content_preview_bottom_sheet);
+        assertNotNull(
+                "Content Previews Bottom Sheet is not initialized", contentPreviewsBottomSheet);
+    }
 }
diff --git a/chrome/browser/download/bubble/download_bubble_ui_controller_unittest.cc b/chrome/browser/download/bubble/download_bubble_ui_controller_unittest.cc
index 28be732..2afa0a5 100644
--- a/chrome/browser/download/bubble/download_bubble_ui_controller_unittest.cc
+++ b/chrome/browser/download/bubble/download_bubble_ui_controller_unittest.cc
@@ -128,7 +128,7 @@
               (const override));
 
  private:
-  Profile* profile_;
+  raw_ptr<Profile> profile_;
   std::vector<ModelType> model_types_;
   const std::vector<std::unique_ptr<StrictMockDownloadItem>>& download_items_;
   const OfflineItemList& offline_items_;
diff --git a/chrome/browser/download/bubble/download_display_controller_unittest.cc b/chrome/browser/download/bubble/download_display_controller_unittest.cc
index 4d52292..c66334b 100644
--- a/chrome/browser/download/bubble/download_display_controller_unittest.cc
+++ b/chrome/browser/download/bubble/download_display_controller_unittest.cc
@@ -175,7 +175,7 @@
               (const override));
 
  private:
-  Profile* profile_;
+  raw_ptr<Profile> profile_;
   std::vector<ModelType> model_types_;
   const std::vector<std::unique_ptr<StrictMockDownloadItem>>& download_items_;
   const OfflineItemList& offline_items_;
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index 423bdad..5661ffa2 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -828,6 +828,15 @@
       CompleteSafeBrowsingScan();
       SetOpenWhenComplete(true);
 #endif
+      if (GetDangerType() == download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING) {
+        base::UmaHistogramEnumeration(
+            "SBClientDownload.DeepScanEvent",
+            safe_browsing::DeepScanEvent::kScanCanceled);
+      } else {
+        base::UmaHistogramEnumeration(
+            "SBClientDownload.DeepScanEvent",
+            safe_browsing::DeepScanEvent::kPromptBypassed);
+      }
       [[fallthrough]];
     case DownloadCommands::KEEP:
 #if BUILDFLAG(FULL_SAFE_BROWSING)
@@ -922,8 +931,11 @@
               &ChromeDownloadManagerDelegate::CheckClientDownloadDone,
               delegate->GetWeakPtr(), download_->GetId()),
           safe_browsing::DeepScanningRequest::DeepScanTrigger::
-              TRIGGER_APP_PROMPT,
+              TRIGGER_CONSUMER_PROMPT,
           safe_browsing::DownloadCheckResult::UNKNOWN, std::move(settings));
+      base::UmaHistogramEnumeration(
+          "SBClientDownload.DeepScanEvent",
+          safe_browsing::DeepScanEvent::kPromptAccepted);
       break;
   }
 }
diff --git a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api_unittest.cc b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api_unittest.cc
index cb7b24f..a742904 100644
--- a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api_unittest.cc
@@ -31,7 +31,7 @@
   void SetUp() override {
     ExtensionServiceTestBase::SetUp();
 
-    ExtensionServiceInitParams params = CreateDefaultInitParams();
+    ExtensionServiceInitParams params;
     params.enable_bookmark_model = true;
     InitializeExtensionService(params);
 
diff --git a/chrome/browser/extensions/api/bookmarks/bookmarks_api_unittest.cc b/chrome/browser/extensions/api/bookmarks/bookmarks_api_unittest.cc
index ec9ae9a..2d39d6f 100644
--- a/chrome/browser/extensions/api/bookmarks/bookmarks_api_unittest.cc
+++ b/chrome/browser/extensions/api/bookmarks/bookmarks_api_unittest.cc
@@ -26,7 +26,7 @@
   void SetUp() override {
     ExtensionServiceTestBase::SetUp();
 
-    ExtensionServiceInitParams params = CreateDefaultInitParams();
+    ExtensionServiceInitParams params;
     params.enable_bookmark_model = true;
     InitializeExtensionService(params);
 
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
index cc2cce1..76cfedc6 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -97,6 +97,7 @@
 // TODO(https://crbug.com/1060801): Here and elsewhere, possibly switch build
 // flag to #if BUILDFLAG(IS_CHROMEOS)
 #include "chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.h"
+#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
 #endif
 
 namespace extensions {
@@ -400,9 +401,11 @@
 }
 
 std::unique_ptr<SupervisedUserExtensionsDelegate>
-ChromeExtensionsAPIClient::CreateSupervisedUserExtensionsDelegate() const {
+ChromeExtensionsAPIClient::CreateSupervisedUserExtensionsDelegate(
+    content::BrowserContext* browser_context) const {
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
-  return std::make_unique<SupervisedUserExtensionsDelegateImpl>();
+  return std::make_unique<SupervisedUserExtensionsDelegateImpl>(
+      browser_context);
 #else
   return nullptr;
 #endif
@@ -494,7 +497,14 @@
 
 std::vector<KeyedServiceBaseFactory*>
 ChromeExtensionsAPIClient::GetFactoryDependencies() {
-  return {InstantServiceFactory::GetInstance()};
+  // clang-format off
+  return {
+      InstantServiceFactory::GetInstance(),
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+      SupervisedUserServiceFactory::GetInstance(),
+#endif
+  };
+  // clang-format on
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.h b/chrome/browser/extensions/api/chrome_extensions_api_client.h
index 8d620da7..e13b68a8 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.h
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.h
@@ -78,7 +78,8 @@
       content::BrowserContext* browser_context) const override;
   ManagementAPIDelegate* CreateManagementAPIDelegate() const override;
   std::unique_ptr<SupervisedUserExtensionsDelegate>
-  CreateSupervisedUserExtensionsDelegate() const override;
+  CreateSupervisedUserExtensionsDelegate(
+      content::BrowserContext* browser_context) const override;
 
   std::unique_ptr<DisplayInfoProvider> CreateDisplayInfoProvider()
       const override;
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index ba5fa6844..8f102256 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -504,11 +504,7 @@
 void DeveloperPrivateApiUnitTest::SetUp() {
   ExtensionServiceTestBase::SetUp();
 
-  // By not specifying a pref_file filepath, we get a
-  // sync_preferences::TestingPrefServiceSyncable
-  // - see BuildTestingProfile in extension_service_test_base.cc.
-  ExtensionServiceInitParams init_params = CreateDefaultInitParams();
-  init_params.pref_file.clear();
+  ExtensionServiceInitParams init_params;
   init_params.profile_is_supervised = ProfileIsSupervised();
   InitializeExtensionService(init_params);
 
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
index 30bab93..735c15b 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -124,7 +124,7 @@
 
   // Returns the initialization parameters for the extension service.
   virtual ExtensionServiceInitParams GetExtensionServiceInitParams() {
-    return CreateDefaultInitParams();
+    return {};
   }
 
   void OnInfoGenerated(std::unique_ptr<developer::ExtensionInfo>* info_out,
@@ -968,8 +968,6 @@
   ExtensionServiceInitParams GetExtensionServiceInitParams() override {
     ExtensionServiceInitParams params =
         ExtensionInfoGeneratorUnitTest::GetExtensionServiceInitParams();
-    // Force a TestingPrefServiceSyncable to be created.
-    params.pref_file.clear();
     params.profile_is_supervised = true;
     return params;
   }
diff --git a/chrome/browser/extensions/api/management/management_api_unittest.cc b/chrome/browser/extensions/api/management/management_api_unittest.cc
index ce7cc34b..62be629 100644
--- a/chrome/browser/extensions/api/management/management_api_unittest.cc
+++ b/chrome/browser/extensions/api/management/management_api_unittest.cc
@@ -7,6 +7,7 @@
 
 #include "base/functional/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/stringprintf.h"
@@ -21,6 +22,7 @@
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/test_browser_window.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/test/web_contents_tester.h"
 #include "extensions/browser/api/management/management_api.h"
 #include "extensions/browser/api/management/management_api_constants.h"
@@ -103,7 +105,7 @@
 
   // Returns the initialization parameters for the extension service.
   virtual ExtensionServiceInitParams GetExtensionServiceInitParams() {
-    return CreateDefaultInitParams();
+    return ExtensionServiceInitParams();
   }
 
   // ExtensionServiceTestBase:
@@ -942,34 +944,33 @@
 class TestSupervisedUserExtensionsDelegate
     : public SupervisedUserExtensionsDelegate {
  public:
-  TestSupervisedUserExtensionsDelegate() = default;
+  explicit TestSupervisedUserExtensionsDelegate(
+      content::BrowserContext* context)
+      : context_(context) {}
   ~TestSupervisedUserExtensionsDelegate() override = default;
 
   // SupervisedUserExtensionsDelegate:
-  bool IsChild(content::BrowserContext* context) const override { return true; }
+  bool IsChild() const override { return true; }
 
   bool IsExtensionAllowedByParent(
-      const extensions::Extension& extension,
-      content::BrowserContext* context) const override {
+      const extensions::Extension& extension) const override {
     SupervisedUserService* supervised_user_service =
-        SupervisedUserServiceFactory::GetForBrowserContext(context);
+        SupervisedUserServiceFactory::GetForBrowserContext(context_);
     return supervised_user_service->IsExtensionAllowed(extension);
   }
 
   void RequestToAddExtensionOrShowError(
       const extensions::Extension& extension,
-      content::BrowserContext* context,
       content::WebContents* contents,
       const gfx::ImageSkia& icon,
       ExtensionApprovalDoneCallback extension_approval_callback) override {
     // Preconditions.
-    DCHECK(IsChild(context));
-    DCHECK(!IsExtensionAllowedByParent(extension, context));
+    DCHECK(IsChild());
+    DCHECK(!IsExtensionAllowedByParent(extension));
 
-    if (CanInstallExtensions(context)) {
+    if (CanInstallExtensions()) {
       ShowParentPermissionDialogForExtension(
-          extension, context, contents, std::move(extension_approval_callback),
-          icon);
+          extension, contents, std::move(extension_approval_callback), icon);
     } else {
       ShowInstallBlockedByParentDialogForExtension(
           extension, contents,
@@ -982,16 +983,15 @@
 
   void RequestToEnableExtensionOrShowError(
       const extensions::Extension& extension,
-      content::BrowserContext* context,
       content::WebContents* contents,
       ExtensionApprovalDoneCallback extension_approval_callback) override {
     // Preconditions.
-    DCHECK(IsChild(context));
-    DCHECK(!IsExtensionAllowedByParent(extension, context));
+    DCHECK(IsChild());
+    DCHECK(!IsExtensionAllowedByParent(extension));
 
-    if (CanInstallExtensions(context)) {
+    if (CanInstallExtensions()) {
       ShowParentPermissionDialogForExtension(
-          extension, context, contents, std::move(extension_approval_callback),
+          extension, contents, std::move(extension_approval_callback),
           gfx::ImageSkia());
     } else {
       ShowInstallBlockedByParentDialogForExtension(
@@ -1012,11 +1012,11 @@
   int show_block_dialog_count() const { return show_block_dialog_count_; }
 
  private:
-  // Returns true if |context| represents a supervised child account who may
+  // Returns true if |context_| represents a supervised child account who may
   // install extensions with parent permission.
-  bool CanInstallExtensions(content::BrowserContext* context) const {
+  bool CanInstallExtensions() const {
     SupervisedUserService* supervised_user_service =
-        SupervisedUserServiceFactory::GetForBrowserContext(context);
+        SupervisedUserServiceFactory::GetForBrowserContext(context_);
     return supervised_user_service->CanInstallExtensions();
   }
 
@@ -1024,7 +1024,6 @@
   // when it completes.
   void ShowParentPermissionDialogForExtension(
       const extensions::Extension& extension,
-      content::BrowserContext* context,
       content::WebContents* contents,
       extensions::SupervisedUserExtensionsDelegate::
           ExtensionApprovalDoneCallback done_callback,
@@ -1047,6 +1046,7 @@
     std::move(done_callback).Run();
   }
 
+  const raw_ptr<content::BrowserContext> context_;
   ExtensionApprovalResult dialog_result_ = ExtensionApprovalResult::kFailed;
   int show_dialog_count_ = 0;
   int show_block_dialog_count_ = 0;
@@ -1061,9 +1061,7 @@
 
   // ManagementApiUnitTest:
   ExtensionServiceInitParams GetExtensionServiceInitParams() override {
-    ExtensionServiceInitParams params = CreateDefaultInitParams();
-    // Force a TestingPrefServiceSyncable to be created.
-    params.pref_file.clear();
+    ExtensionServiceInitParams params;
     params.profile_is_supervised = true;
     return params;
   }
@@ -1090,7 +1088,8 @@
     management_api_ = ManagementAPI::GetFactoryInstance()->Get(profile());
 
     // Install a SupervisedUserExtensionsDelegate to sense the dialog state.
-    supervised_user_delegate_ = new TestSupervisedUserExtensionsDelegate;
+    supervised_user_delegate_ =
+        new TestSupervisedUserExtensionsDelegate(profile());
     management_api_->set_supervised_user_extensions_delegate_for_test(
         base::WrapUnique(supervised_user_delegate_));
   }
diff --git a/chrome/browser/extensions/api/runtime/runtime_apitest.cc b/chrome/browser/extensions/api/runtime/runtime_apitest.cc
index fbbaf15..42d98ff 100644
--- a/chrome/browser/extensions/api/runtime/runtime_apitest.cc
+++ b/chrome/browser/extensions/api/runtime/runtime_apitest.cc
@@ -5,6 +5,7 @@
 #include <memory>
 
 #include "base/json/json_reader.h"
+#include "base/memory/raw_ptr.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/bind.h"
@@ -693,7 +694,7 @@
   }
 
  private:
-  const Extension* extension_ = nullptr;
+  raw_ptr<const Extension, DanglingUntriaged> extension_ = nullptr;
   TestExtensionDir test_dir_;
   ScopedCurrentChannel channel_override_{version_info::Channel::UNKNOWN};
   base::test::ScopedFeatureList feature_list_;
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
index 8a4bd53..4e315a4 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
@@ -36,6 +36,7 @@
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "ui/gl/gl_switches.h"
 #include "url/url_constants.h"
 
 namespace extensions {
@@ -52,6 +53,7 @@
     // Specify smallish window size to make testing of tab capture less CPU
     // intensive.
     command_line->AppendSwitchASCII(::switches::kWindowSize, "300,300");
+    command_line->AppendSwitch(::switches::kUseGpuInTests);
   }
 
   void AddExtensionToCommandLineAllowlist() {
diff --git a/chrome/browser/extensions/api/tabs/windows_util_unittest.cc b/chrome/browser/extensions/api/tabs/windows_util_unittest.cc
index 11a3244..1390265 100644
--- a/chrome/browser/extensions/api/tabs/windows_util_unittest.cc
+++ b/chrome/browser/extensions/api/tabs/windows_util_unittest.cc
@@ -23,7 +23,7 @@
  public:
   void SetUp() override {
     ExtensionServiceTestBase::SetUp();
-    InitializeExtensionService(CreateDefaultInitParams());
+    InitializeExtensionService(ExtensionServiceInitParams());
   }
 };
 
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index 0290398..14a9673 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -541,7 +541,7 @@
       // are allowed, the install prompt will be shown before the request
       // permission dialog is shown.
       supervised_user_extensions_delegate->RequestToAddExtensionOrShowError(
-          *dummy_extension_, profile_, web_contents,
+          *dummy_extension_, web_contents,
           gfx::ImageSkia::CreateFrom1xBitmap(icon_),
           std::move(extension_approval_callback));
       return;
@@ -687,7 +687,7 @@
   // were disabled, the block dialog would have been shown at the install prompt
   // step.
   supervised_user_extensions_delegate->RequestToAddExtensionOrShowError(
-      *dummy_extension_, profile_, web_contents,
+      *dummy_extension_, web_contents,
       gfx::ImageSkia::CreateFrom1xBitmap(icon_),
       std::move(extension_approval_callback));
 
diff --git a/chrome/browser/extensions/chrome_app_icon_unittest.cc b/chrome/browser/extensions/chrome_app_icon_unittest.cc
index f71a645..2589a1fd 100644
--- a/chrome/browser/extensions/chrome_app_icon_unittest.cc
+++ b/chrome/browser/extensions/chrome_app_icon_unittest.cc
@@ -201,11 +201,10 @@
   void SetUp() override {
     ExtensionServiceTestBase::SetUp();
 
-    const base::FilePath source_install_dir =
-        data_dir().AppendASCII("app_list").AppendASCII("Extensions");
-    const base::FilePath pref_path =
-        source_install_dir.DirName().Append(chrome::kPreferencesFilename);
-    InitializeInstalledExtensionService(pref_path, source_install_dir);
+    ExtensionServiceInitParams params;
+    ASSERT_TRUE(params.ConfigureByTestDataDirectory(
+        data_dir().AppendASCII("app_list")));
+    InitializeExtensionService(params);
     service_->Init();
   }
 };
diff --git a/chrome/browser/extensions/extension_allowlist_unittest.cc b/chrome/browser/extensions/extension_allowlist_unittest.cc
index fbb69a6..09d320b 100644
--- a/chrome/browser/extensions/extension_allowlist_unittest.cc
+++ b/chrome/browser/extensions/extension_allowlist_unittest.cc
@@ -42,7 +42,10 @@
  protected:
   // Creates a test extension service with 3 installed extensions.
   void CreateExtensionService(bool enhanced_protection_enabled) {
-    InitializeGoodInstalledExtensionService();
+    ExtensionServiceInitParams params;
+    ASSERT_TRUE(
+        params.ConfigureByTestDataDirectory(data_dir().AppendASCII("good")));
+    InitializeExtensionService(params);
     extension_prefs_ = ExtensionPrefs::Get(profile());
 
     if (enhanced_protection_enabled) {
@@ -53,10 +56,7 @@
   }
 
   void CreateEmptyExtensionService() {
-    ExtensionServiceTestBase::ExtensionServiceInitParams params =
-        CreateDefaultInitParams();
-    params.pref_file = base::FilePath();
-    InitializeExtensionService(params);
+    InitializeExtensionService(ExtensionServiceInitParams());
     extension_prefs_ = ExtensionPrefs::Get(profile());
     safe_browsing::SetSafeBrowsingState(
         profile()->GetPrefs(),
diff --git a/chrome/browser/extensions/extension_error_controller_unittest.cc b/chrome/browser/extensions/extension_error_controller_unittest.cc
index c1c317a..59c523b0 100644
--- a/chrome/browser/extensions/extension_error_controller_unittest.cc
+++ b/chrome/browser/extensions/extension_error_controller_unittest.cc
@@ -122,7 +122,7 @@
 
   // We don't want a first-run ExtensionService, since we ignore warnings
   // for new profiles.
-  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  ExtensionServiceInitParams params;
   params.is_first_run = false;
   InitializeExtensionService(params);
 }
diff --git a/chrome/browser/extensions/extension_garbage_collector_unittest.cc b/chrome/browser/extensions/extension_garbage_collector_unittest.cc
index 329c8123..e93ff582 100644
--- a/chrome/browser/extensions/extension_garbage_collector_unittest.cc
+++ b/chrome/browser/extensions/extension_garbage_collector_unittest.cc
@@ -118,12 +118,10 @@
 TEST_F(ExtensionGarbageCollectorUnitTest, GarbageCollectWithPendingUpdates) {
   InitPluginService();
 
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("pending_updates").AppendASCII("Extensions");
-  base::FilePath pref_path =
-      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
-
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(params.ConfigureByTestDataDirectory(
+      data_dir().AppendASCII("pending_updates")));
+  InitializeExtensionService(params);
 
   // This is the directory that is going to be deleted, so make sure it actually
   // is there before the garbage collection.
@@ -148,12 +146,10 @@
 TEST_F(ExtensionGarbageCollectorUnitTest, UpdateOnStartup) {
   InitPluginService();
 
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("pending_updates").AppendASCII("Extensions");
-  base::FilePath pref_path =
-      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
-
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(params.ConfigureByTestDataDirectory(
+      data_dir().AppendASCII("pending_updates")));
+  InitializeExtensionService(params);
 
   // This is the directory that is going to be deleted, so make sure it actually
   // is there before the garbage collection.
diff --git a/chrome/browser/extensions/extension_migrator_unittest.cc b/chrome/browser/extensions/extension_migrator_unittest.cc
index 4d8ef5e..de8dfc3 100644
--- a/chrome/browser/extensions/extension_migrator_unittest.cc
+++ b/chrome/browser/extensions/extension_migrator_unittest.cc
@@ -42,11 +42,10 @@
 
  protected:
   void InitWithExistingProfile() {
-    ExtensionServiceInitParams params = CreateDefaultInitParams();
-    params.is_first_run = false;
+    ExtensionServiceInitParams params;
     // Create prefs file to make the profile not new.
-    const char prefs[] = "{}";
-    EXPECT_TRUE(base::WriteFile(params.pref_file, prefs));
+    params.prefs_content = "{}";
+    params.is_first_run = false;
     InitializeExtensionService(params);
     service()->Init();
     AddMigratorProvider();
diff --git a/chrome/browser/extensions/extension_service_sync_unittest.cc b/chrome/browser/extensions/extension_service_sync_unittest.cc
index 75300904..904c9a0 100644
--- a/chrome/browser/extensions/extension_service_sync_unittest.cc
+++ b/chrome/browser/extensions/extension_service_sync_unittest.cc
@@ -316,12 +316,10 @@
 
 TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
   // Start the extensions service with one external extension already installed.
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("good").AppendASCII("Extensions");
-  base::FilePath pref_path =
-      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
-
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(
+      params.ConfigureByTestDataDirectory(data_dir().AppendASCII("good")));
+  InitializeExtensionService(params);
 
   // The user has enabled sync.
   syncer::SyncService* sync_service =
@@ -497,12 +495,10 @@
 
 TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
   // Start the extension service with three extensions already installed.
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("good").AppendASCII("Extensions");
-  base::FilePath pref_path =
-      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
-
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(
+      params.ConfigureByTestDataDirectory(data_dir().AppendASCII("good")));
+  InitializeExtensionService(params);
 
   // The user has enabled sync.
   syncer::SyncService* sync_service =
@@ -558,12 +554,10 @@
 
 TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
   // Start the extension service with three extensions already installed.
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("good").AppendASCII("Extensions");
-  base::FilePath pref_path =
-      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
-
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(
+      params.ConfigureByTestDataDirectory(data_dir().AppendASCII("good")));
+  InitializeExtensionService(params);
 
   // The user has enabled sync.
   SyncServiceFactory::GetForProfile(profile())
diff --git a/chrome/browser/extensions/extension_service_test_base.cc b/chrome/browser/extensions/extension_service_test_base.cc
index d428bad..06baa8a 100644
--- a/chrome/browser/extensions/extension_service_test_base.cc
+++ b/chrome/browser/extensions/extension_service_test_base.cc
@@ -63,21 +63,40 @@
 
 // Create a testing profile according to |params|.
 std::unique_ptr<TestingProfile> BuildTestingProfile(
-    const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
+    const ExtensionServiceTestBase::ExtensionServiceInitParams& params,
+    base::ScopedTempDir& temp_dir,
+    policy::PolicyService* policy_service) {
   TestingProfile::Builder profile_builder;
-  // Create a PrefService that only contains user defined preference values and
-  // policies.
-  sync_preferences::PrefServiceMockFactory factory;
+
+  if (!temp_dir.CreateUniqueTempDir()) {
+    return nullptr;
+  }
+
+  base::FilePath profile_dir =
+      temp_dir.GetPath().Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
+  if (base::File::Error error = base::File::FILE_OK;
+      !base::CreateDirectoryAndGetError(profile_dir, &error)) {
+    LOG(ERROR) << "Failed to create profile directory: " << error;
+    return nullptr;
+  }
+
   // If pref_file is empty, TestingProfile automatically creates
   // sync_preferences::TestingPrefServiceSyncable instance.
-  if (!params.pref_file.empty()) {
-    factory.SetUserPrefsFile(
-        params.pref_file,
-        base::SingleThreadTaskRunner::GetCurrentDefault().get());
-    if (params.policy_service) {
-      factory.SetManagedPolicies(params.policy_service,
-                                 g_browser_process->browser_policy_connector());
+  if (params.prefs_content.has_value()) {
+    base::FilePath prefs_path =
+        profile_dir.Append(chrome::kPreferencesFilename);
+    if (!base::WriteFile(prefs_path, params.prefs_content.value())) {
+      LOG(ERROR) << "Failed to write a prefs file";
+      return nullptr;
     }
+
+    // Create a PrefService that only contains user defined preference values
+    // and policies.
+    sync_preferences::PrefServiceMockFactory factory;
+    factory.SetUserPrefsFile(
+        prefs_path, base::SingleThreadTaskRunner::GetCurrentDefault().get());
+    factory.SetManagedPolicies(policy_service,
+                               g_browser_process->browser_policy_connector());
     scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
         new user_prefs::PrefRegistrySyncable);
     std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs(
@@ -86,6 +105,26 @@
     profile_builder.SetPrefService(std::move(prefs));
   }
 
+  base::FilePath extensions_install_dir =
+      profile_dir.AppendASCII(extensions::kInstallDirectoryName);
+  if (!base::DeletePathRecursively(extensions_install_dir)) {
+    LOG(ERROR) << "Failed to clean extensions directory";
+    return nullptr;
+  }
+  if (params.extensions_dir.empty()) {
+    if (base::File::Error error = base::File::FILE_OK;
+        !base::CreateDirectoryAndGetError(extensions_install_dir, &error)) {
+      LOG(ERROR) << "Failed to create extensions directory: " << error;
+      return nullptr;
+    }
+  } else {
+    if (!base::CopyDirectory(params.extensions_dir, extensions_install_dir,
+                             true)) {
+      LOG(ERROR) << "Failed to copy extensions directory";
+      return nullptr;
+    }
+  }
+
   if (params.profile_is_supervised) {
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
     profile_builder.SetIsSupervisedProfile();
@@ -116,19 +155,41 @@
   profile_builder.AddTestingFactory(SyncServiceFactory::GetInstance(),
                                     SyncServiceFactory::GetDefaultFactory());
 
-  profile_builder.SetPath(params.profile_path);
+  profile_builder.SetPath(profile_dir);
   return profile_builder.Build();
 }
 
 }  // namespace
 
 ExtensionServiceTestBase::ExtensionServiceInitParams::
-    ExtensionServiceInitParams() {}
+    ExtensionServiceInitParams() = default;
 
 ExtensionServiceTestBase::ExtensionServiceInitParams::
     ExtensionServiceInitParams(const ExtensionServiceInitParams& other) =
         default;
 
+ExtensionServiceTestBase::ExtensionServiceInitParams::
+    ~ExtensionServiceInitParams() = default;
+
+bool ExtensionServiceTestBase::ExtensionServiceInitParams::
+    SetPrefsContentFromFile(const base::FilePath& filepath) {
+  std::string content;
+  if (!base::ReadFileToString(filepath, &content)) {
+    return false;
+  }
+  prefs_content.emplace(std::move(content));
+  return true;
+}
+
+bool ExtensionServiceTestBase::ExtensionServiceInitParams::
+    ConfigureByTestDataDirectory(const base::FilePath& filepath) {
+  if (!SetPrefsContentFromFile(filepath.Append(chrome::kPreferencesFilename))) {
+    return false;
+  }
+  extensions_dir = filepath.AppendASCII(extensions::kInstallDirectoryName);
+  return true;
+}
+
 ExtensionServiceTestBase::ExtensionServiceTestBase()
     : ExtensionServiceTestBase(
           std::make_unique<content::BrowserTaskEnvironment>(
@@ -160,37 +221,13 @@
   profile_.reset();
 }
 
-ExtensionServiceTestBase::ExtensionServiceInitParams
-ExtensionServiceTestBase::CreateDefaultInitParams() {
-  ExtensionServiceInitParams params;
-  EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
-  base::FilePath path = temp_dir_.GetPath();
-  path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
-  EXPECT_TRUE(base::DeletePathRecursively(path));
-  base::File::Error error = base::File::FILE_OK;
-  EXPECT_TRUE(base::CreateDirectoryAndGetError(path, &error)) << error;
-  base::FilePath prefs_filename =
-      path.Append(FILE_PATH_LITERAL("TestPreferences"));
-  base::FilePath extensions_install_dir =
-      path.Append(FILE_PATH_LITERAL("Extensions"));
-  EXPECT_TRUE(base::DeletePathRecursively(extensions_install_dir));
-  EXPECT_TRUE(base::CreateDirectoryAndGetError(extensions_install_dir, &error))
-      << error;
-
-  params.profile_path = path;
-  params.pref_file = prefs_filename;
-  params.extensions_install_dir = extensions_install_dir;
-
-  params.policy_service = policy_service_.get();
-  return params;
-}
-
 void ExtensionServiceTestBase::InitializeExtensionService(
     const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
-  profile_ = BuildTestingProfile(params);
-  CreateExtensionService(params);
+  profile_ = BuildTestingProfile(params, temp_dir_, policy_service_.get());
+  extensions_install_dir_ =
+      profile_->GetPath().AppendASCII(extensions::kInstallDirectoryName);
 
-  extensions_install_dir_ = params.extensions_install_dir;
+  CreateExtensionService(params);
   registry_ = ExtensionRegistry::Get(profile());
 
   // Garbage collector is typically NULL during tests, so give it a build.
@@ -200,48 +237,20 @@
 }
 
 void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
-  InitializeExtensionService(CreateDefaultInitParams());
-}
-
-void ExtensionServiceTestBase::InitializeInstalledExtensionService(
-    const base::FilePath& prefs_file,
-    const base::FilePath& source_install_dir,
-    const ExtensionServiceInitParams& additional_params) {
-  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-  base::FilePath path = temp_dir_.GetPath();
-
-  path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
-  ASSERT_TRUE(base::DeletePathRecursively(path));
-
-  base::File::Error error = base::File::FILE_OK;
-  ASSERT_TRUE(base::CreateDirectoryAndGetError(path, &error)) << error;
-
-  base::FilePath temp_prefs = path.Append(chrome::kPreferencesFilename);
-  ASSERT_TRUE(base::CopyFile(prefs_file, temp_prefs));
-
-  base::FilePath extensions_install_dir =
-      path.Append(FILE_PATH_LITERAL("Extensions"));
-  ASSERT_TRUE(base::DeletePathRecursively(extensions_install_dir));
-  ASSERT_TRUE(
-      base::CopyDirectory(source_install_dir, extensions_install_dir, true));
-
-  ExtensionServiceInitParams params = additional_params;
-  params.profile_path = path;
-  params.pref_file = temp_prefs;
-  params.extensions_install_dir = extensions_install_dir;
+  ExtensionServiceInitParams params;
+  params.prefs_content = "";
   InitializeExtensionService(params);
 }
 
 void ExtensionServiceTestBase::InitializeGoodInstalledExtensionService() {
-  base::FilePath source_install_dir =
-      data_dir_.AppendASCII("good").AppendASCII("Extensions");
-  base::FilePath pref_path =
-      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(
+      params.ConfigureByTestDataDirectory(data_dir().AppendASCII("good")));
+  InitializeExtensionService(params);
 }
 
 void ExtensionServiceTestBase::InitializeExtensionServiceWithUpdater() {
-  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  ExtensionServiceInitParams params;
   params.autoupdate_enabled = true;
   InitializeExtensionService(params);
   service_->updater()->Start();
@@ -249,7 +258,7 @@
 
 void ExtensionServiceTestBase::
     InitializeExtensionServiceWithExtensionsDisabled() {
-  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  ExtensionServiceInitParams params;
   params.extensions_enabled = false;
   InitializeExtensionService(params);
 }
@@ -393,7 +402,7 @@
     ExtensionPrefs::Get(profile())->SetAlertSystemFirstRun();
 
   service_ = system->CreateExtensionService(
-      base::CommandLine::ForCurrentProcess(), params.extensions_install_dir,
+      base::CommandLine::ForCurrentProcess(), extensions_install_dir_,
       params.autoupdate_enabled, params.extensions_enabled);
 
   service_->component_loader()->set_ignore_allowlist_for_testing(true);
diff --git a/chrome/browser/extensions/extension_service_test_base.h b/chrome/browser/extensions/extension_service_test_base.h
index 0e3cd4f..8e1c1d4 100644
--- a/chrome/browser/extensions/extension_service_test_base.h
+++ b/chrome/browser/extensions/extension_service_test_base.h
@@ -62,9 +62,16 @@
 class ExtensionServiceTestBase : public testing::Test {
  public:
   struct ExtensionServiceInitParams {
-    base::FilePath profile_path;
-    base::FilePath pref_file;
-    base::FilePath extensions_install_dir;
+    // If set, even if it is empty string, creates a pref file in the profile
+    // directory with the given content, and initializes user prefs store
+    // referring the file.
+    // If not, sync_preferences::TestingPrefServiceSyncable is used.
+    absl::optional<std::string> prefs_content;
+
+    // If not empty, copies the directory to the profile's extension
+    // directory.
+    base::FilePath extensions_dir;
+
     bool autoupdate_enabled = false;
     bool extensions_enabled = true;
     bool is_first_run = true;
@@ -73,12 +80,21 @@
     bool enable_bookmark_model = false;
     bool enable_install_limiter = false;
 
-    raw_ptr<policy::PolicyService> policy_service = nullptr;
-
-    // Though you could use this constructor, you probably want to use
-    // CreateDefaultInitParams(), and then make a change or two.
     ExtensionServiceInitParams();
     ExtensionServiceInitParams(const ExtensionServiceInitParams& other);
+    ~ExtensionServiceInitParams();
+
+    // Sets the prefs_content to the content in the given file.
+    [[nodiscard]] bool SetPrefsContentFromFile(const base::FilePath& filepath);
+
+    // Configures prefs_content and extensions_dir from the test data directory
+    // specified by the `filepath`.
+    // There must be a file named "Preferences" in the test data directory
+    // containing the prefs content.
+    // Also, there must be a directory named "Extensions" containing extensions
+    // data for testing.
+    [[nodiscard]] bool ConfigureByTestDataDirectory(
+        const base::FilePath& filepath);
   };
 
   ExtensionServiceTestBase(const ExtensionServiceTestBase&) = delete;
@@ -100,9 +116,6 @@
   void SetUp() override;
   void TearDown() override;
 
-  // Create a set of InitParams to install an ExtensionService into |temp_dir_|.
-  ExtensionServiceInitParams CreateDefaultInitParams();
-
   // Initialize an ExtensionService according to the given |params|.
   virtual void InitializeExtensionService(
       const ExtensionServiceInitParams& params);
@@ -110,14 +123,6 @@
   // Initialize an empty ExtensionService using the default init params.
   void InitializeEmptyExtensionService();
 
-  // Initialize an ExtensionService with the associated |prefs_file| and
-  // |source_install_dir|.
-  void InitializeInstalledExtensionService(
-      const base::FilePath& prefs_file,
-      const base::FilePath& source_install_dir,
-      const ExtensionServiceInitParams& additional_params =
-          ExtensionServiceInitParams{});
-
   // Initialize an ExtensionService with a few already-installed extensions.
   void InitializeGoodInstalledExtensionService();
 
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 7bd0cb05..8b775b53 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -870,10 +870,7 @@
   }
 
   void InitializeEmptyExtensionServiceWithTestingPrefs() {
-    ExtensionServiceTestBase::ExtensionServiceInitParams params =
-        CreateDefaultInitParams();
-    params.pref_file = base::FilePath();
-    InitializeExtensionService(params);
+    InitializeExtensionService(ExtensionServiceInitParams());
   }
 
   ManagementPolicy* GetManagementPolicy() {
@@ -1041,12 +1038,10 @@
 // Test loading bad extensions from the profile directory.
 TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectoryFail) {
   // Initialize the test dir with a bad Preferences/extensions.
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("bad").AppendASCII("Extensions");
-  base::FilePath pref_path =
-      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
-
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(
+      params.ConfigureByTestDataDirectory(data_dir().AppendASCII("bad")));
+  InitializeExtensionService(params);
 
   service()->Init();
 
@@ -1082,13 +1077,10 @@
 TEST_F(ExtensionServiceTest, PendingImports) {
   InitPluginService();
 
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("pending_updates_with_imports").AppendASCII(
-          "Extensions");
-  base::FilePath pref_path =
-      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
-
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(params.ConfigureByTestDataDirectory(
+      data_dir().AppendASCII("pending_updates_with_imports")));
+  InitializeExtensionService(params);
 
   // Verify there are no pending extensions initially.
   EXPECT_FALSE(service()->pending_extension_manager()->HasPendingExtensions());
@@ -1498,17 +1490,16 @@
 // This extension shown in preferences file requires an experimental permission.
 // It could not be loaded without such permission.
 TEST_F(ExtensionServiceTest, UninstallingNotLoadedExtension) {
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("good").AppendASCII("Extensions");
+  base::FilePath test_data_dir = data_dir().AppendASCII("good");
+  ExtensionServiceInitParams params;
   // The preference contains an external extension
   // that requires 'experimental' permission.
-  base::FilePath pref_path = source_install_dir
-      .DirName()
-      .AppendASCII("PreferencesExperimental");
-
+  ASSERT_TRUE(params.SetPrefsContentFromFile(
+      test_data_dir.AppendASCII("PreferencesExperimental")));
+  params.extensions_dir = test_data_dir.AppendASCII("Extensions");
   // Aforementioned extension will not be loaded if
   // there is no '--enable-experimental-extension-apis' command line flag.
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  InitializeExtensionService(params);
 
   service()->Init();
 
@@ -5848,13 +5839,12 @@
 // providers can't account for them.
 TEST_F(ExtensionServiceTest, ExternalUninstall) {
   // Start the extensions service with one external extension already installed.
-  base::FilePath source_install_dir =
-      data_dir().AppendASCII("good").AppendASCII("Extensions");
-  base::FilePath pref_path = source_install_dir
-      .DirName()
-      .AppendASCII("PreferencesExternal");
-
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  base::FilePath test_data_dir = data_dir().AppendASCII("good");
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(params.SetPrefsContentFromFile(
+      test_data_dir.AppendASCII("PreferencesExternal")));
+  params.extensions_dir = test_data_dir.AppendASCII("Extensions");
+  InitializeExtensionService(params);
   service()->Init();
 
   ASSERT_EQ(0u, GetErrors().size());
@@ -6310,10 +6300,12 @@
   extension_l10n_util::ScopedLocaleForTest testLocale("en");
 
   // Initialize the test dir with a good Preferences/extensions.
-  base::FilePath source_install_dir = data_dir().AppendASCII("l10n");
-  base::FilePath pref_path =
-      source_install_dir.Append(chrome::kPreferencesFilename);
-  InitializeInstalledExtensionService(pref_path, source_install_dir);
+  base::FilePath test_data_dir = data_dir().AppendASCII("l10n");
+  ExtensionServiceInitParams params;
+  ASSERT_TRUE(params.SetPrefsContentFromFile(
+      test_data_dir.Append(chrome::kPreferencesFilename)));
+  params.extensions_dir = test_data_dir;
+  InitializeExtensionService(params);
 
   service()->Init();
 
@@ -7256,7 +7248,7 @@
       FeatureSwitch::prompt_for_external_extensions(), true);
   // This sets up the ExtensionPrefs used by our ExtensionService to be
   // post-first run.
-  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  ExtensionServiceInitParams params;
   params.is_first_run = false;
   InitializeExtensionService(params);
 
@@ -7363,7 +7355,7 @@
       FeatureSwitch::prompt_for_external_extensions(), true);
   // This sets up the ExtensionPrefs used by our ExtensionService to be
   // post-first run.
-  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  ExtensionServiceInitParams params;
   params.is_first_run = false;
   InitializeExtensionService(params);
 
@@ -7449,7 +7441,7 @@
 
   // This sets up the ExtensionPrefs used by our ExtensionService to be
   // post-first run.
-  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  ExtensionServiceInitParams params;
   params.is_first_run = false;
   InitializeExtensionService(params);
 
@@ -7500,7 +7492,7 @@
   FeatureSwitch::ScopedOverride prompt(
       FeatureSwitch::prompt_for_external_extensions(), true);
 
-  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  ExtensionServiceInitParams params;
   params.is_first_run = false;
   InitializeExtensionService(params);
 
@@ -7539,7 +7531,7 @@
   FeatureSwitch::ScopedOverride prompt(
       FeatureSwitch::prompt_for_external_extensions(), true);
 
-  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  ExtensionServiceInitParams params;
   params.is_first_run = false;
   InitializeExtensionService(params);
 
@@ -8120,7 +8112,7 @@
 // https://crbug.com/917700.
 TEST_P(ExternalExtensionPriorityTest, PolicyForegroundFetch) {
   ExtensionUpdater::ScopedSkipScheduledCheckForTest skip_scheduled_checks;
-  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  ExtensionServiceInitParams params;
   params.autoupdate_enabled = true;
   InitializeExtensionService(params);
 
diff --git a/chrome/browser/extensions/external_provider_impl_unittest.cc b/chrome/browser/extensions/external_provider_impl_unittest.cc
index 17b443d..030772c 100644
--- a/chrome/browser/extensions/external_provider_impl_unittest.cc
+++ b/chrome/browser/extensions/external_provider_impl_unittest.cc
@@ -169,11 +169,10 @@
   }
 
   void InitializeExtensionServiceWithUpdaterAndPrefs() {
-    ExtensionServiceInitParams params = CreateDefaultInitParams();
-    params.autoupdate_enabled = true;
+    ExtensionServiceInitParams params;
     // Create prefs file to make the profile not new.
-    const char prefs[] = "{}";
-    EXPECT_TRUE(base::WriteFile(params.pref_file, prefs));
+    params.prefs_content = "{}";
+    params.autoupdate_enabled = true;
     InitializeExtensionService(params);
     service_->updater()->Start();
     content::RunAllTasksUntilIdle();
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 6daac9a..2df0a89 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -209,7 +209,7 @@
   {
     "name": "app-store-rating",
     "owners": [ "hiramahmood@google.com", "bling-flags@google.com" ],
-    "expiry_milestone": 114
+    "expiry_milestone": 115
   },
   {
     "name": "arc-custom-tabs-experiment",
@@ -1237,7 +1237,7 @@
   {
     "name": "cormorant",
     "owners": [ "jeffreycohen", "markeh", "wissemgamra", "chrome-with-friends-robots@google.com" ],
-    "expiry_milestone": 114
+    "expiry_milestone": 119
   },
   {
     "name": "cpu-affinity-restrict-to-little-cores",
@@ -2526,7 +2526,7 @@
     // A temporary flag to control hardware mirroring until it is decided
     // whether to permanently remove hardware mirroring. See crbug.com/1161556
     // for more details.
-    "expiry_milestone": 114
+    "expiry_milestone": 134
   },
   {
     "name": "enable-hardware-secure-decryption",
@@ -2960,7 +2960,7 @@
   {
     "name": "enable-privacy-indicators",
     "owners": [ "leandre" ],
-    "expiry_milestone": 114
+    "expiry_milestone": 117
   },
   {
     "name": "enable-projector",
@@ -4503,7 +4503,7 @@
   {
     "name": "ios-new-post-restore-experience",
     "owners": [ "scottyoder@google.com", "bling-flags@google.com" ],
-    "expiry_milestone": 114
+    "expiry_milestone": 115
   },
   {
     "name": "ios-new-tab-page-retention",
@@ -5017,7 +5017,7 @@
   {
     "name": "new-overflow-menu-share-chrome-action",
     "owners": [ "scottyoder@google.com", "bling-flags@google.com" ],
-    "expiry_milestone": 114
+    "expiry_milestone": 116
   },
   {
     "name": "new-shortcut-mapping",
@@ -5732,6 +5732,11 @@
     "expiry_milestone": 115
   },
   {
+    "name": "page-content-annotations-remote-page-metadata",
+    "owners": [ "sophiechang", "chrome-intelligence-core@google.com"],
+    "expiry_milestone": 115
+  },
+  {
     "name": "page-entities-page-content-annotations",
     "owners": [ "sophiechang", "mcrouse", "chrome-intelligence-core@google.com"],
     "expiry_milestone": 115
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 910c2eb..d198ce9 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2444,6 +2444,11 @@
 const char kPageContentAnnotationsPersistSalientImageMetadataDescription[] =
     "Enables salient image metadata per page load to be persisted on-device.";
 
+const char kPageContentAnnotationsRemotePageMetadataName[] =
+    "Page content annotations - Remote page metadata";
+const char kPageContentAnnotationsRemotePageMetadataDescription[] =
+    "Enables fetching of page load metadata to be persisted on-device.";
+
 const char kPageEntitiesPageContentAnnotationsName[] =
     "Page entities content annotations";
 const char kPageEntitiesPageContentAnnotationsDescription[] =
@@ -2896,11 +2901,6 @@
     "behaviors for the web, this flag is likely to break your experience on "
     "sites you visit today.";
 
-const char kWebViewTagSiteIsolationName[] = "Site isolation for <webview> tags";
-const char kWebViewTagSiteIsolationDescription[] =
-    "Enables site isolation for content rendered inside <webview> tags. This "
-    "increases security for Chrome Apps and WebUI pages that use <webview>.";
-
 const char kSiteIsolationOptOutName[] = "Disable site isolation";
 const char kSiteIsolationOptOutDescription[] =
     "Disables site isolation "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index f37a49e..1456c821 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1367,6 +1367,9 @@
 extern const char
     kPageContentAnnotationsPersistSalientImageMetadataDescription[];
 
+extern const char kPageContentAnnotationsRemotePageMetadataName[];
+extern const char kPageContentAnnotationsRemotePageMetadataDescription[];
+
 extern const char kPageEntitiesPageContentAnnotationsName[];
 extern const char kPageEntitiesPageContentAnnotationsDescription[];
 
@@ -1642,9 +1645,6 @@
 extern const char kIsolationByDefaultName[];
 extern const char kIsolationByDefaultDescription[];
 
-extern const char kWebViewTagSiteIsolationName[];
-extern const char kWebViewTagSiteIsolationDescription[];
-
 extern const char kSiteIsolationOptOutName[];
 extern const char kSiteIsolationOptOutDescription[];
 extern const char kSiteIsolationOptOutChoiceDefault[];
diff --git a/chrome/browser/lacros/input_method_lacros_browsertest.cc b/chrome/browser/lacros/input_method_lacros_browsertest.cc
index 867b0b35..52b5f31 100644
--- a/chrome/browser/lacros/input_method_lacros_browsertest.cc
+++ b/chrome/browser/lacros/input_method_lacros_browsertest.cc
@@ -364,43 +364,55 @@
   return ExecJs(web_content, script);
 }
 
-mojom::KeyEventPtr CreateKeyPressEvent(ui::DomKey dom_key,
-                                       ui::DomCode dom_code,
-                                       ui::EventFlags flags = ui::EF_NONE) {
+mojom::KeyEventPtr CreateKeyPressEvent(
+    ui::DomKey dom_key,
+    ui::DomCode dom_code,
+    ui::KeyboardCode key_code = ui::KeyboardCode::VKEY_UNKNOWN,
+    ui::EventFlags flags = ui::EF_NONE) {
   return mojom::KeyEvent::New(
       mojom::KeyEventType::kKeyPress, static_cast<int>(dom_key),
-      static_cast<int>(dom_code),
-      static_cast<int>(ui::KeyboardCode::VKEY_UNKNOWN), flags);
+      static_cast<int>(dom_code), static_cast<int>(key_code), flags);
 }
 
-mojom::KeyEventPtr CreateKeyReleaseEvent(ui::DomKey dom_key,
-                                         ui::DomCode dom_code,
-                                         ui::EventFlags flags = ui::EF_NONE) {
+mojom::KeyEventPtr CreateKeyReleaseEvent(
+    ui::DomKey dom_key,
+    ui::DomCode dom_code,
+    ui::KeyboardCode key_code = ui::KeyboardCode::VKEY_UNKNOWN,
+    ui::EventFlags flags = ui::EF_NONE) {
   return mojom::KeyEvent::New(
       mojom::KeyEventType::kKeyRelease, static_cast<int>(dom_key),
-      static_cast<int>(dom_code),
-      static_cast<int>(ui::KeyboardCode::VKEY_UNKNOWN), flags);
+      static_cast<int>(dom_code), static_cast<int>(key_code), flags);
 }
 
 class KeySequenceBuilder {
  public:
-  KeySequenceBuilder Press(ui::DomKey dom_key, ui::DomCode dom_code) && {
+  KeySequenceBuilder Press(
+      ui::DomKey dom_key,
+      ui::DomCode dom_code,
+      ui::KeyboardCode key_code = ui::KeyboardCode::VKEY_UNKNOWN) && {
     UpdateModifiersFromDomKey(dom_key, true);
-    key_events_.push_back(
-        CreateKeyPressEvent(dom_key, dom_code, active_modifiers_.ToFlags()));
+    key_events_.push_back(CreateKeyPressEvent(dom_key, dom_code, key_code,
+                                              active_modifiers_.ToFlags()));
     return std::move(*this);
   }
 
-  KeySequenceBuilder Release(ui::DomKey dom_key, ui::DomCode dom_code) && {
+  KeySequenceBuilder Release(
+      ui::DomKey dom_key,
+      ui::DomCode dom_code,
+      ui::KeyboardCode key_code = ui::KeyboardCode::VKEY_UNKNOWN) && {
     UpdateModifiersFromDomKey(dom_key, false);
-    key_events_.push_back(
-        CreateKeyReleaseEvent(dom_key, dom_code, active_modifiers_.ToFlags()));
+    key_events_.push_back(CreateKeyReleaseEvent(dom_key, dom_code, key_code,
+                                                active_modifiers_.ToFlags()));
     return std::move(*this);
   }
 
-  KeySequenceBuilder PressAndRelease(ui::DomKey dom_key,
-                                     ui::DomCode dom_code) && {
-    return std::move(*this).Press(dom_key, dom_code).Release(dom_key, dom_code);
+  KeySequenceBuilder PressAndRelease(
+      ui::DomKey dom_key,
+      ui::DomCode dom_code,
+      ui::KeyboardCode key_code = ui::KeyboardCode::VKEY_UNKNOWN) && {
+    return std::move(*this)
+        .Press(dom_key, dom_code, key_code)
+        .Release(dom_key, dom_code, key_code);
   }
 
   std::vector<mojom::KeyEventPtr> Build() && { return std::move(key_events_); }
@@ -875,9 +887,12 @@
   SendKeyEventsSync(
       input_method_async_waiter,
       KeySequenceBuilder()
-          .PressAndRelease(ui::DomKey::FromCharacter('a'), ui::DomCode::US_A)
-          .PressAndRelease(ui::DomKey::FromCharacter('b'), ui::DomCode::US_B)
-          .PressAndRelease(ui::DomKey::FromCharacter('c'), ui::DomCode::US_C)
+          .PressAndRelease(ui::DomKey::FromCharacter('a'), ui::DomCode::US_A,
+                           ui::KeyboardCode::VKEY_A)
+          .PressAndRelease(ui::DomKey::FromCharacter('b'), ui::DomCode::US_B,
+                           ui::KeyboardCode::VKEY_B)
+          .PressAndRelease(ui::DomKey::FromCharacter('c'), ui::DomCode::US_C,
+                           ui::KeyboardCode::VKEY_C)
           .Build());
 
   EXPECT_TRUE(WaitUntilInputFieldHasText(GetActiveWebContents(browser()), id,
diff --git a/chrome/browser/lacros/lacros_file_system_provider.cc b/chrome/browser/lacros/lacros_file_system_provider.cc
index b79955f..35025a6 100644
--- a/chrome/browser/lacros/lacros_file_system_provider.cc
+++ b/chrome/browser/lacros/lacros_file_system_provider.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/lacros/lacros_file_system_provider.h"
 
 #include "base/functional/bind.h"
-#include "base/memory/ref_counted.h"
 #include "base/ranges/algorithm.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/extensions/file_system_provider/service_worker_lifetime_manager.h"
@@ -25,57 +24,61 @@
 #include "ui/gfx/image/image_skia.h"
 
 namespace {
-
-// TODO(b/266519645): scope object lifetime to the lifetime of
-//                    `LacrosFileSystemProvider`.
-class IconLoadTask : public base::RefCounted<IconLoadTask> {
- public:
-  using Callback =
-      base::OnceCallback<void(const gfx::Image&, const gfx::Image&)>;
-  IconLoadTask(content::BrowserContext* browser_context,
-               const extensions::Extension* extension,
-               Callback callback)
-      : callback_(std::move(callback)) {
-    LoadExtensionIcon(browser_context, extension, icon16x16_, 16);
-    LoadExtensionIcon(browser_context, extension, icon32x32_, 32);
+// Returns the single main profile, or nullptr if none is found.
+Profile* GetMainProfile() {
+  auto profiles = g_browser_process->profile_manager()->GetLoadedProfiles();
+  const auto main_it = base::ranges::find_if(profiles, &Profile::IsMainProfile);
+  if (main_it == profiles.end()) {
+    return nullptr;
   }
-  // Loads an icon of a single size.
-  void LoadExtensionIcon(content::BrowserContext* browser_context,
-                         const extensions::Extension* extension,
-                         absl::optional<gfx::Image>& target,
-                         int size) {
-    extensions::ExtensionResource icon = extensions::IconsInfo::GetIconResource(
-        extension, size, ExtensionIconSet::MatchType::MATCH_BIGGER);
+  return *main_it;
+}
 
-    extensions::ImageLoader::Get(browser_context)
-        ->LoadImageAsync(extension, icon, gfx::Size(size, size),
-                         base::BindOnce(&IconLoadTask::OnIconLoaded, this,
-                                        std::ref(target)));
+const extensions::Extension* GetEnabledExtension(
+    content::BrowserContext* browser_context,
+    const extensions::ExtensionId& extension_id) {
+  extensions::ExtensionRegistry* registry =
+      extensions::ExtensionRegistry::Get(browser_context);
+  return registry->GetExtensionById(extension_id,
+                                    extensions::ExtensionRegistry::ENABLED);
+}
+
+// Loads an icon of a single size.
+void LoadExtensionIcon(content::BrowserContext* browser_context,
+                       const extensions::ExtensionId& extension_id,
+                       int size,
+                       extensions::ImageLoaderImageCallback callback) {
+  const extensions::Extension* extension =
+      GetEnabledExtension(browser_context, extension_id);
+  if (!extension) {
+    return;
+  }
+  extensions::ExtensionResource icon = extensions::IconsInfo::GetIconResource(
+      extension, size, ExtensionIconSet::MatchType::MATCH_BIGGER);
+  extensions::ImageLoader::Get(browser_context)
+      ->LoadImageAsync(extension, icon, gfx::Size(size, size),
+                       std::move(callback));
+}
+
+void OnLoadedIcon32x32(base::WeakPtr<Profile> weak_profile_ptr,
+                       const extensions::ExtensionId& extension_id,
+                       const gfx::Image& icon16x16,
+                       const gfx::Image& icon32x32) {
+  Profile* profile = weak_profile_ptr.get();
+  if (!profile) {
+    return;
+  }
+  const extensions::Extension* extension =
+      GetEnabledExtension(profile, extension_id);
+  if (!extension) {
+    return;
+  }
+  auto* capabilities =
+      extensions::FileSystemProviderCapabilities::Get(extension);
+  if (!capabilities) {
+    return;
   }
 
- private:
-  ~IconLoadTask() = default;
-  friend base::RefCounted<IconLoadTask>;
-
-  void OnIconLoaded(absl::optional<gfx::Image>& target,
-                    const gfx::Image& icon) {
-    target = icon;
-    if (icon16x16_ && icon32x32_) {
-      std::move(callback_).Run(*icon16x16_, *icon32x32_);
-    }
-  }
-
-  Callback callback_;
-  absl::optional<gfx::Image> icon16x16_;
-  absl::optional<gfx::Image> icon32x32_;
-};
-
-void NotifyAshExtensionLoaded(
-    const std::string& id,
-    const std::string& name,
-    const extensions::FileSystemProviderCapabilities& capabilities,
-    const gfx::Image& icon16x16,
-    const gfx::Image& icon32x32) {
   chromeos::LacrosService* service = chromeos::LacrosService::Get();
   int fsp_service_version = service->GetInterfaceVersion(
       crosapi::mojom::FileSystemProviderService::Uuid_);
@@ -86,7 +89,7 @@
   }
 
   crosapi::mojom::FileSystemSource source;
-  switch (capabilities.source()) {
+  switch (capabilities->source()) {
     case extensions::FileSystemProviderSource::SOURCE_FILE:
       source = crosapi::mojom::FileSystemSource::kFile;
       break;
@@ -104,25 +107,30 @@
       int{crosapi::mojom::FileSystemProviderService::MethodMinVersions::
               kExtensionLoadedMinVersion}) {
     fsp_service->ExtensionLoadedDeprecated(
-        capabilities.configurable(), capabilities.watchable(),
-        capabilities.multiple_mounts(), source, name, id);
+        capabilities->configurable(), capabilities->watchable(),
+        capabilities->multiple_mounts(), source, extension->name(),
+        extension->id());
     return;
   }
 
   fsp_service->ExtensionLoaded(
-      capabilities.configurable(), capabilities.watchable(),
-      capabilities.multiple_mounts(), source, name, id, icon16x16.AsImageSkia(),
-      icon32x32.AsImageSkia());
+      capabilities->configurable(), capabilities->watchable(),
+      capabilities->multiple_mounts(), source, extension->name(),
+      extension->id(), icon16x16.AsImageSkia(), icon32x32.AsImageSkia());
 }
 
-// Returns the single main profile, or nullptr if none is found.
-Profile* GetMainProfile() {
-  auto profiles = g_browser_process->profile_manager()->GetLoadedProfiles();
-  const auto main_it = base::ranges::find_if(profiles, &Profile::IsMainProfile);
-  if (main_it == profiles.end())
-    return nullptr;
-  return *main_it;
+void OnLoadedIcon16x16(base::WeakPtr<Profile> weak_profile_ptr,
+                       const extensions::ExtensionId& extension_id,
+                       const gfx::Image& icon16x16) {
+  Profile* profile = weak_profile_ptr.get();
+  if (!profile) {
+    return;
+  }
+  LoadExtensionIcon(profile, extension_id, 32,
+                    base::BindOnce(&OnLoadedIcon32x32, profile->GetWeakPtr(),
+                                   extension_id, icon16x16));
 }
+
 }  // namespace
 
 LacrosFileSystemProvider::LacrosFileSystemProvider() : receiver_{this} {
@@ -283,16 +291,14 @@
           extensions::mojom::APIPermissionID::kFileSystemProvider)) {
     return;
   }
-  const extensions::FileSystemProviderCapabilities* const capabilities =
-      extensions::FileSystemProviderCapabilities::Get(extension);
-  if (!capabilities) {
+  if (!extensions::FileSystemProviderCapabilities::Get(extension)) {
     return;
   }
 
-  base::MakeRefCounted<IconLoadTask>(
-      browser_context, extension,
-      base::BindOnce(&NotifyAshExtensionLoaded, extension->id(),
-                     extension->name(), *capabilities));
+  Profile* profile = Profile::FromBrowserContext(browser_context);
+  LoadExtensionIcon(profile, extension->id(), 16,
+                    base::BindOnce(&OnLoadedIcon16x16, profile->GetWeakPtr(),
+                                   extension->id()));
 }
 
 void LacrosFileSystemProvider::OnExtensionUnloaded(
diff --git a/chrome/browser/lacros/lacros_file_system_provider.h b/chrome/browser/lacros/lacros_file_system_provider.h
index 4f769f01..c01f3e10 100644
--- a/chrome/browser/lacros/lacros_file_system_provider.h
+++ b/chrome/browser/lacros/lacros_file_system_provider.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_LACROS_LACROS_FILE_SYSTEM_PROVIDER_H_
 #define CHROME_BROWSER_LACROS_LACROS_FILE_SYSTEM_PROVIDER_H_
 
+#include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
 #include "chromeos/crosapi/mojom/file_system_provider.mojom.h"
 #include "extensions/browser/extension_registry.h"
diff --git a/chrome/browser/media/router/discovery/mdns/dns_sd_registry.cc b/chrome/browser/media/router/discovery/mdns/dns_sd_registry.cc
index f151154..1e82ae4 100644
--- a/chrome/browser/media/router/discovery/mdns/dns_sd_registry.cc
+++ b/chrome/browser/media/router/discovery/mdns/dns_sd_registry.cc
@@ -169,6 +169,11 @@
     service_data_map_.erase(it);
 }
 
+void DnsSdRegistry::ResetForTest() {
+  service_data_map_.clear();
+  service_discovery_client_.reset();
+}
+
 void DnsSdRegistry::ServiceChanged(const std::string& service_type,
                                    bool added,
                                    const DnsSdService& service) {
diff --git a/chrome/browser/media/router/discovery/mdns/dns_sd_registry.h b/chrome/browser/media/router/discovery/mdns/dns_sd_registry.h
index fc85104e..e648010 100644
--- a/chrome/browser/media/router/discovery/mdns/dns_sd_registry.h
+++ b/chrome/browser/media/router/discovery/mdns/dns_sd_registry.h
@@ -60,6 +60,8 @@
   virtual void RegisterDnsSdListener(const std::string& service_type);
   virtual void UnregisterDnsSdListener(const std::string& service_type);
 
+  void ResetForTest();
+
  protected:
   // Data class for managing all the resources and information related to a
   // particular service type.
diff --git a/chrome/browser/media/router/providers/dial/dial_media_route_provider.cc b/chrome/browser/media/router/providers/dial/dial_media_route_provider.cc
index e95a9e92..734f3877 100644
--- a/chrome/browser/media/router/providers/dial/dial_media_route_provider.cc
+++ b/chrome/browser/media/router/providers/dial/dial_media_route_provider.cc
@@ -12,7 +12,6 @@
 #include "base/no_destructor.h"
 #include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/task/sequenced_task_runner.h"
 #include "chrome/browser/media/router/data_decoder_util.h"
 #include "chrome/browser/media/router/providers/dial/dial_media_route_provider_metrics.h"
@@ -447,9 +446,9 @@
         activity.launch_info.client_id, sink));
     message_sender_->SendMessages(route_id, std::move(messages));
     activity_manager_->StopApp(
-        route_id, base::BindOnce(&DialMediaRouteProvider::HandleStopAppResult,
-                                 base::Unretained(this), route_id,
-                                 std::move(callback), sink));
+        route_id,
+        base::BindOnce(&DialMediaRouteProvider::HandleStopAppResult,
+                       base::Unretained(this), route_id, std::move(callback)));
   } else {
     logger_->LogError(
         mojom::LogCategory::kRoute, kLoggerComponent,
@@ -466,7 +465,6 @@
 void DialMediaRouteProvider::HandleStopAppResult(
     const MediaRoute::Id& route_id,
     TerminateRouteCallback callback,
-    const MediaSinkInternal& sink,
     const absl::optional<std::string>& message,
     mojom::RouteRequestResultCode result_code) {
   switch (result_code) {
@@ -495,9 +493,9 @@
           "", MediaRoute::GetMediaSourceIdFromMediaRouteId(route_id),
           MediaRoute::GetPresentationIdFromMediaRouteId(route_id));
       media_router_->OnIssue(
-          {l10n_util::GetStringFUTF8(IDS_MEDIA_ROUTER_ISSUE_CANNOT_TERMINATE,
-                                     base::UTF8ToUTF16(sink.sink().name())),
-           IssueInfo::Severity::WARNING, sink.id()});
+          {l10n_util::GetStringUTF8(IDS_MEDIA_ROUTER_ISSUE_CANNOT_TERMINATE),
+           IssueInfo::Severity::WARNING,
+           MediaRoute::GetSinkIdFromMediaRouteId(route_id)});
   }
   // We set the PresentationConnection state to "terminated" per the API spec:
   // https://w3c.github.io/presentation-api/#terminating-a-presentation-in-a-controlling-browsing-context
diff --git a/chrome/browser/media/router/providers/dial/dial_media_route_provider.h b/chrome/browser/media/router/providers/dial/dial_media_route_provider.h
index f749cb7..0182fb1 100644
--- a/chrome/browser/media/router/providers/dial/dial_media_route_provider.h
+++ b/chrome/browser/media/router/providers/dial/dial_media_route_provider.h
@@ -170,7 +170,6 @@
                         TerminateRouteCallback callback);
   void HandleStopAppResult(const MediaRoute::Id& route_id,
                            TerminateRouteCallback callback,
-                           const MediaSinkInternal& sink,
                            const absl::optional<std::string>& message,
                            mojom::RouteRequestResultCode result_code);
   void NotifyAllOnRoutesUpdated();
diff --git a/chrome/browser/media/webrtc/capture_handle_browsertest.cc b/chrome/browser/media/webrtc/capture_handle_browsertest.cc
index 267e09a..9b79746a5 100644
--- a/chrome/browser/media/webrtc/capture_handle_browsertest.cc
+++ b/chrome/browser/media/webrtc/capture_handle_browsertest.cc
@@ -30,6 +30,7 @@
 #include "content/public/test/browser_test_base.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/prerender_test_util.h"
+#include "ui/gl/gl_switches.h"
 
 using content::WebContents;
 
@@ -221,6 +222,7 @@
         switches::kEnableExperimentalWebPlatformFeatures);
     command_line->AppendSwitchASCII(
         switches::kAutoSelectTabCaptureSourceByTitle, kCapturedTabTitle);
+    command_line->AppendSwitch(switches::kUseGpuInTests);
   }
 
   void TearDownOnMainThread() override {
diff --git a/chrome/browser/media/webrtc/conditional_focus_browsertest.cc b/chrome/browser/media/webrtc/conditional_focus_browsertest.cc
index fb7f31bc..b9bcb49 100644
--- a/chrome/browser/media/webrtc/conditional_focus_browsertest.cc
+++ b/chrome/browser/media/webrtc/conditional_focus_browsertest.cc
@@ -19,6 +19,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test.h"
 #include "third_party/blink/public/common/switches.h"
+#include "ui/gl/gl_switches.h"
 
 namespace {
 
@@ -73,6 +74,7 @@
         switches::kAutoSelectTabCaptureSourceByTitle, kCapturedPageTitle);
     command_line->AppendSwitchASCII(blink::switches::kConditionalFocusWindowMs,
                                     "5000");
+    command_line->AppendSwitch(switches::kUseGpuInTests);
   }
 
   WebContents* OpenTestPageInNewTab(const std::string& test_url) {
diff --git a/chrome/browser/media/webrtc/region_capture_browsertest.cc b/chrome/browser/media/webrtc/region_capture_browsertest.cc
index f28a3af..c699d74 100644
--- a/chrome/browser/media/webrtc/region_capture_browsertest.cc
+++ b/chrome/browser/media/webrtc/region_capture_browsertest.cc
@@ -33,6 +33,7 @@
 #include "content/public/test/prerender_test_util.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "third_party/blink/public/common/features.h"
+#include "ui/gl/gl_switches.h"
 
 // TODO(crbug.com/1215089): Enable this test suite on Lacros.
 #if !BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -293,6 +294,7 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(
         switches::kEnableExperimentalWebPlatformFeatures);
+    command_line->AppendSwitch(switches::kUseGpuInTests);
     command_line_ = command_line;
   }
 
diff --git a/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc b/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
index 78a9a6c6..d430468a 100644
--- a/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
@@ -39,6 +39,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "media/base/media_switches.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "ui/gl/gl_switches.h"
 
 namespace {
 static const char kMainWebrtcTestHtmlPage[] = "/webrtc/webrtc_jsep01_test.html";
@@ -231,6 +232,7 @@
     command_line->AppendSwitchASCII(switches::kAutoSelectDesktopCaptureSource,
                                     "Entire screen");
     command_line->AppendSwitch(switches::kEnableUserMediaScreenCapturing);
+    command_line->AppendSwitch(switches::kUseGpuInTests);
   }
 
  protected:
diff --git a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
index df68b2b8..b6c8afc 100644
--- a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
@@ -44,6 +44,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/features.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gl/gl_switches.h"
 
 #if BUILDFLAG(IS_MAC)
 #include "base/mac/mac_util.h"
@@ -411,6 +412,7 @@
         switches::kUseFakeDeviceForMediaStream,
         base::StringPrintf("display-media-type=%s",
                            test_config_.display_surface));
+    command_line->AppendSwitch(switches::kUseGpuInTests);
   }
 
   bool PreferCurrentTab() const override {
@@ -584,6 +586,7 @@
         switches::kEnableExperimentalWebPlatformFeatures);
     command_line->AppendSwitchASCII(
         switches::kAutoSelectTabCaptureSourceByTitle, kAppWindowTitle);
+    command_line->AppendSwitch(switches::kUseGpuInTests);
   }
 
   void SetUpOnMainThread() override {
@@ -649,6 +652,7 @@
         switches::kEnableExperimentalWebPlatformFeatures);
     command_line->AppendSwitchASCII(
         switches::kAutoSelectTabCaptureSourceByTitle, kSameOriginRenamedTitle);
+    command_line->AppendSwitch(switches::kUseGpuInTests);
   }
 
   void SetUpOnMainThread() override {
@@ -818,6 +822,7 @@
         switches::kUseFakeDeviceForMediaStream,
         base::StrCat({"display-media-type=",
                       DisplaySurfaceTypeAsString(display_surface_type_)}));
+    command_line->AppendSwitch(switches::kUseGpuInTests);
   }
 
   std::string GetVideoTrackType() {
@@ -1114,6 +1119,8 @@
         switches::kEnableExperimentalWebPlatformFeatures);
     command_line->AppendSwitchASCII(
         switches::kAutoSelectTabCaptureSourceByTitle, kCapturedTabTitle);
+    command_line->AppendSwitch(switches::kUseGpuInTests);
+
     if (!user_shared_audio_) {
       command_line->AppendSwitch(switches::kScreenCaptureAudioDefaultUnchecked);
     }
@@ -1327,6 +1334,7 @@
 
     command_line->AppendSwitchASCII(
         switches::kAutoSelectTabCaptureSourceByTitle, kMainHtmlTitle);
+    command_line->AppendSwitch(switches::kUseGpuInTests);
   }
 
   std::string GetConstraints(bool prefer_current_tab = false) {
diff --git a/chrome/browser/media/webrtc/webrtc_logging_controller_unittest.cc b/chrome/browser/media/webrtc/webrtc_logging_controller_unittest.cc
index 828bd20..dbfabf6 100644
--- a/chrome/browser/media/webrtc/webrtc_logging_controller_unittest.cc
+++ b/chrome/browser/media/webrtc/webrtc_logging_controller_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/memory/raw_ptr.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -143,7 +144,7 @@
   std::unique_ptr<MockRenderProcessHost> rph_;
 
   // Class under test.
-  WebRtcLoggingController* webrtc_logging_controller_ = nullptr;
+  raw_ptr<WebRtcLoggingController> webrtc_logging_controller_ = nullptr;
   std::unique_ptr<WebRtcLogUploader> webrtc_log_uploader_ = nullptr;
 
   // Testing utilities.
diff --git a/chrome/browser/media/webrtc/webrtc_mediadevices_interactive_uitest.cc b/chrome/browser/media/webrtc/webrtc_mediadevices_interactive_uitest.cc
index 0e7f077d..c3fbb65e 100644
--- a/chrome/browser/media/webrtc/webrtc_mediadevices_interactive_uitest.cc
+++ b/chrome/browser/media/webrtc/webrtc_mediadevices_interactive_uitest.cc
@@ -99,20 +99,21 @@
     bool found_audio_input = false;
     bool found_video_input = false;
 
-    for (const auto& dict : values.GetList()) {
-      ASSERT_TRUE(dict.is_dict());
+    for (const auto& value : values.GetList()) {
+      const base::Value::Dict* dict = value.GetIfDict();
+      ASSERT_TRUE(dict);
       MediaDeviceInfo device;
-      ASSERT_TRUE(dict.FindStringPath("deviceId"));
-      device.device_id = *dict.FindStringPath("deviceId");
+      ASSERT_TRUE(dict->FindString("deviceId"));
+      device.device_id = *dict->FindString("deviceId");
 
-      ASSERT_TRUE(dict.FindStringPath("kind"));
-      device.kind = *dict.FindStringPath("kind");
+      ASSERT_TRUE(dict->FindString("kind"));
+      device.kind = *dict->FindString("kind");
 
-      ASSERT_TRUE(dict.FindStringPath("label"));
-      device.label = *dict.FindStringPath("label");
+      ASSERT_TRUE(dict->FindString("label"));
+      device.label = *dict->FindString("label");
 
-      ASSERT_TRUE(dict.FindStringPath("groupId"));
-      device.group_id = *dict.FindStringPath("groupId");
+      ASSERT_TRUE(dict->FindString("groupId"));
+      device.group_id = *dict->FindString("groupId");
 
       // Should be HMAC SHA256.
       if (!media::AudioDeviceDescription::IsDefaultDevice(device.device_id) &&
diff --git a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider.cc b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider.cc
index ec2cd79a..ad7ac89 100644
--- a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider.cc
+++ b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
+#include "chrome/browser/ash/login/demo_mode/demo_session.h"
 #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
 #include "chrome/browser/ash/policy/core/user_cloud_policy_manager_ash.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -87,6 +88,11 @@
 
 UserTypeByDeviceTypeMetricsProvider::UserSegment
 UserTypeByDeviceTypeMetricsProvider::GetUserSegment(Profile* profile) {
+  // Check for Demo Session
+  if (profiles::IsDemoSession()) {
+    return UserSegment::kDemoMode;
+  }
+
   // Check for Managed Guest Session
   if (profiles::IsPublicSession()) {
     return UserSegment::kManagedGuestSession;
diff --git a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider.h b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider.h
index 20ae4d8..37b6de9 100644
--- a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider.h
+++ b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider.h
@@ -39,6 +39,10 @@
     kNonProfit = 3,
     // Primary profile is for a user belonging to an enterprise organization.
     kEnterprise = 4,
+    // Primary profile is for a demo session.
+    // This value is not present in MetricsLogSegment and must not collide with
+    // any values found there.
+    kDemoMode = 65533,
     // Primary profile is for a kiosk app.
     // This value is not present in MetricsLogSegment and must not collide with
     // any values found there.
diff --git a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
index fa430f3..3cd4d53 100644
--- a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
+++ b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
@@ -13,6 +13,8 @@
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "chrome/browser/ash/login/app_mode/kiosk_launch_controller.h"
 #include "chrome/browser/ash/login/app_mode/test/kiosk_test_helpers.h"
+#include "chrome/browser/ash/login/demo_mode/demo_session.h"
+#include "chrome/browser/ash/login/demo_mode/demo_setup_test_utils.h"
 #include "chrome/browser/ash/login/existing_user_controller.h"
 #include "chrome/browser/ash/login/test/embedded_policy_test_server_mixin.h"
 #include "chrome/browser/ash/login/test/logged_in_user_mixin.h"
@@ -76,6 +78,7 @@
     case UserSegment::kUnmanaged:
     case UserSegment::kKioskApp:
     case UserSegment::kManagedGuestSession:
+    case UserSegment::kDemoMode:
       return absl::nullopt;
   }
   NOTREACHED();
@@ -130,6 +133,9 @@
       case UserSegment::kManagedGuestSession:
         test_name += "ManagedGuestSession";
         break;
+      case UserSegment::kDemoMode:
+        test_name += "DemoMode";
+        break;
     }
 
     test_name += "_on_";
@@ -168,6 +174,10 @@
 
   bool IsKioskApp() const { return GetUserSegment() == UserSegment::kKioskApp; }
 
+  bool IsDemoSession() const {
+    return GetUserSegment() == UserSegment::kDemoMode;
+  }
+
   TestCase& ExpectUmaOutput() {
     uma_expected_ = true;
     return *this;
@@ -202,12 +212,23 @@
   return test_case;
 }
 
+TestCase DemoModeCase() {
+  TestCase test_case(UserSegment::kDemoMode, policy::MarketSegment::ENTERPRISE);
+  return test_case;
+}
 }  // namespace
 
 class UserTypeByDeviceTypeMetricsProviderTest
     : public policy::DevicePolicyCrosBrowserTest,
       public testing::WithParamInterface<TestCase> {
  public:
+  UserTypeByDeviceTypeMetricsProviderTest() {
+    if (GetParam().IsDemoSession()) {
+      device_state_.SetState(
+          ash::DeviceStateMixin::State::OOBE_COMPLETED_DEMO_MODE);
+    }
+  }
+
   void SetUpInProcessBrowserTestFixture() override {
     policy::DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
     LOG(INFO) << "UserTypeByDeviceTypeMetricsProviderTest::"
@@ -317,6 +338,17 @@
     controller->Login(user_context, ash::SigninSpecifics());
   }
 
+  void StartDemoSession() {
+    // Set Demo Mode config to online.
+    ash::DemoSession::SetDemoConfigForTesting(
+        ash::DemoSession::DemoModeConfig::kOnline);
+    ash::test::LockDemoDeviceInstallAttributes();
+    ash::DemoSession::StartIfInDemoMode();
+
+    // Start the public session, Demo Mode is a special public session.
+    StartPublicSession();
+  }
+
   void PrepareAppLaunch() {
     std::vector<policy::DeviceLocalAccount> device_local_accounts = {
         policy::DeviceLocalAccount(
@@ -386,7 +418,7 @@
   std::unique_ptr<ScopedDeviceSettings> settings_;
 };
 
-// Flacky on CrOS (http://crbug.com/1248669).
+// Flaky on CrOS (http://crbug.com/1248669).
 #if BUILDFLAG(IS_CHROMEOS)
 #define MAYBE_Uma DISABLED_Uma
 #else
@@ -408,6 +440,8 @@
     StartPublicSession();
   } else if (GetParam().IsKioskApp()) {
     StartKioskApp();
+  } else if (GetParam().IsDemoSession()) {
+    StartDemoSession();
   } else {
     LogInUser();
   }
@@ -450,4 +484,5 @@
         KioskCase(policy::MarketSegment::ENTERPRISE),
         MgsCase(policy::MarketSegment::UNKNOWN).DontExpectUmaOutput(),
         MgsCase(policy::MarketSegment::EDUCATION),
-        MgsCase(policy::MarketSegment::ENTERPRISE)));
+        MgsCase(policy::MarketSegment::ENTERPRISE),
+        DemoModeCase()));
diff --git a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc
index d0745c6..70552dd3 100644
--- a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc
+++ b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc
@@ -110,10 +110,11 @@
     EXPECT_EQ("", result.error);
     const auto& list = result.value.GetList();
     EXPECT_EQ(1u, list.size());
-    const std::string* url = list[0].FindStringPath("url");
+    ASSERT_TRUE(list[0].is_dict());
+    const std::string* url = list[0].GetDict().FindString("url");
     EXPECT_TRUE(url);
     EXPECT_EQ(*url, expected_url[i]);
-    lcp_timestamps[i] = list[0].FindDoublePath("time");
+    lcp_timestamps[i] = list[0].GetDict().FindDouble("time");
     EXPECT_TRUE(lcp_timestamps[i].has_value());
 
     waiter->Wait();
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index d6fddb57..786d60cd 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -20,8 +20,10 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/trace_event_analyzer.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -75,6 +77,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/tracing_controller.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_paths.h"
@@ -114,6 +117,9 @@
 using NoStatePrefetch = ukm::builders::NoStatePrefetch;
 using PageLoad = ukm::builders::PageLoad;
 using HistoryNavigation = ukm::builders::HistoryNavigation;
+using trace_analyzer::Query;
+using trace_analyzer::TraceAnalyzer;
+using trace_analyzer::TraceEventVector;
 
 namespace {
 
@@ -2570,6 +2576,7 @@
 class SoftNavigationBrowserTest : public PageLoadMetricsBrowserTest {
  public:
   void TestSoftNavigation(bool wait_for_second_lcp) {
+    StartTracing();
     embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
     content::SetupCrossSiteRedirector(embedded_test_server());
     ASSERT_TRUE(embedded_test_server()->Start());
@@ -2651,6 +2658,64 @@
     // The histogram value represents the low end of the bucket, not the actual
     // value. Therefore it is lower or equal to the web exposed value.
     ASSERT_LE(lcp_value_bucket_start, lcp_start_before);
+
+    VerifyTraceEvents(StopTracing(), wait_for_second_lcp ? 3UL : 1UL);
+  }
+
+ private:
+  void StartTracing() {
+    base::RunLoop wait_for_tracing;
+    content::TracingController::GetInstance()->StartTracing(
+        base::trace_event::TraceConfig(
+            "{\"included_categories\": [\"devtools.timeline\"]}"),
+        wait_for_tracing.QuitClosure());
+    wait_for_tracing.Run();
+  }
+
+  std::string StopTracing() {
+    base::RunLoop wait_for_tracing;
+    std::string trace_output;
+    content::TracingController::GetInstance()->StopTracing(
+        content::TracingController::CreateStringEndpoint(
+            base::BindLambdaForTesting(
+                [&](std::unique_ptr<std::string> trace_str) {
+                  trace_output = std::move(*trace_str);
+                  wait_for_tracing.Quit();
+                })));
+    wait_for_tracing.Run();
+    return trace_output;
+  }
+
+  void VerifyTraceEvents(const std::string& trace_str,
+                         size_t expected_event_number) {
+    std::unique_ptr<TraceAnalyzer> analyzer(TraceAnalyzer::Create(trace_str));
+    TraceEventVector events;
+    auto query =
+        Query::EventNameIs("SoftNavigationHeuristics_SoftNavigationDetected") ||
+        Query::EventNameIs("largestContentfulPaint::Candidate");
+    size_t num_events = analyzer->FindEvents(query, &events);
+    EXPECT_EQ(expected_event_number, num_events);
+
+    std::string previous_frame;
+    double soft_navigation_timestamp = 0.0;
+    for (auto* event : events) {
+      EXPECT_TRUE(event->HasStringArg("frame"));
+      std::string frame = event->GetKnownArgAsString("frame");
+      if (!previous_frame.empty()) {
+        EXPECT_EQ(frame, previous_frame);
+      }
+      previous_frame = frame;
+      if (event->name == "SoftNavigationHeuristics_SoftNavigationDetected") {
+        soft_navigation_timestamp = event->timestamp;
+      } else if (soft_navigation_timestamp > 0.0) {
+        EXPECT_LE(soft_navigation_timestamp, event->timestamp);
+      }
+    }
+    // If we have more than one event, one of them needs to be a soft
+    // navigation.
+    if (expected_event_number > 1) {
+      EXPECT_TRUE(soft_navigation_timestamp > 0);
+    }
   }
 };
 
diff --git a/chrome/browser/payments/secure_payment_confirmation_authenticator_browsertest.cc b/chrome/browser/payments/secure_payment_confirmation_authenticator_browsertest.cc
index f4893b6..f28b2bc 100644
--- a/chrome/browser/payments/secure_payment_confirmation_authenticator_browsertest.cc
+++ b/chrome/browser/payments/secure_payment_confirmation_authenticator_browsertest.cc
@@ -13,7 +13,6 @@
 #include "components/payments/core/journey_logger.h"
 #include "components/payments/core/secure_payment_confirmation_metrics.h"
 #include "content/public/browser/scoped_authenticator_environment_for_testing.h"
-#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "device/fido/virtual_fido_device_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -250,6 +249,77 @@
     SecurePaymentConfirmationAuthenticatorTestBase;
 
 IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationAuthenticatorGetTest,
+                       ConfirmPaymentInCrossOriginIframe) {
+  NavigateTo("a.com", "/secure_payment_confirmation.html");
+  auto scoped_auth_env = ReplaceFidoDiscoveryFactory(/*should_succeed=*/true);
+
+  PaymentCredentialInfo credential_info;
+  CreatePaymentCredential(&credential_info);
+
+  // Load a cross-origin iframe that can initiate SPC.
+  content::WebContents* tab = GetActiveWebContents();
+  GURL iframe_url = https_server()->GetURL(
+      "b.com", "/secure_payment_confirmation_iframe.html");
+  EXPECT_TRUE(content::NavigateIframeToURL(tab, "test", iframe_url));
+
+  test_controller()->SetHasAuthenticator(true);
+  confirm_payment_ = true;
+
+  // Trigger SPC and capture the response.
+  // EvalJs waits for JavaScript promise to resolve.
+  content::RenderFrameHost* iframe = content::FrameMatchingPredicate(
+      tab->GetPrimaryPage(),
+      base::BindRepeating(&content::FrameHasSourceUrl, iframe_url));
+  std::string response =
+      content::EvalJs(
+          iframe, content::JsReplace("requestPayment($1);", credential_info.id))
+          .ExtractString();
+
+  ASSERT_EQ(std::string::npos, response.find("Error"));
+  absl::optional<base::Value> value = base::JSONReader::Read(response);
+  ASSERT_TRUE(value.has_value());
+  ASSERT_TRUE(value->is_dict());
+  const base::Value::Dict& value_dict = value->GetDict();
+  const std::string* type = value_dict.FindString("type");
+  ASSERT_NE(nullptr, type) << response;
+  EXPECT_EQ("payment.get", *type);
+
+  const std::string* origin = value_dict.FindString("origin");
+  ASSERT_NE(nullptr, origin) << response;
+  EXPECT_EQ(https_server()->GetURL("b.com", "/"), GURL(*origin));
+
+  absl::optional<bool> cross_origin = value_dict.FindBool("crossOrigin");
+  ASSERT_TRUE(cross_origin.has_value()) << response;
+  EXPECT_TRUE(cross_origin.value());
+
+  const std::string* payee_name =
+      value_dict.FindStringByDottedPath("payment.payeeName");
+  ASSERT_EQ(nullptr, payee_name) << response;
+
+  const std::string* payee_origin =
+      value_dict.FindStringByDottedPath("payment.payeeOrigin");
+  ASSERT_NE(nullptr, payee_origin) << response;
+  EXPECT_EQ(GURL("https://example-payee-origin.test"), GURL(*payee_origin));
+
+  const std::string* top_origin =
+      value_dict.FindStringByDottedPath("payment.topOrigin");
+  ASSERT_NE(nullptr, top_origin) << response;
+  EXPECT_EQ(https_server()->GetURL("a.com", "/"), GURL(*top_origin));
+  const std::string* rpId = value_dict.FindStringByDottedPath("payment.rpId");
+  ASSERT_NE(nullptr, rpId) << response;
+  EXPECT_EQ("a.com", *rpId);
+
+  ExpectEnrollSystemPromptResult(
+      SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted, 1);
+  ExpectAuthSystemPromptResult(
+      SecurePaymentConfirmationSystemPromptResult::kAccepted, 1);
+  ExpectEvent2Histogram({Event2::kInitiated, Event2::kShown, Event2::kCompleted,
+                         Event2::kPayClicked, Event2::kHadInitialFormOfPayment,
+                         Event2::kRequestMethodSecurePaymentConfirmation,
+                         Event2::kSelectedSecurePaymentConfirmation});
+}
+
+IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationAuthenticatorGetTest,
                        ConfirmPaymentInCrossOriginIframeWithPayeeName) {
   NavigateTo("a.com", "/secure_payment_confirmation.html");
   auto scoped_auth_env = ReplaceFidoDiscoveryFactory(/*should_succeed=*/true);
@@ -516,119 +586,6 @@
       SecurePaymentConfirmationSystemPromptResult::kAccepted, 4);
 }
 
-// TODO(crbug.com/1356224): Fold back into
-// SecurePaymentConfirmationAuthenticatorGetTest once 'rp' field is completely
-// removed.
-class SecurePaymentConfirmationParameterizedAuthenticatorGetTest
-    : public SecurePaymentConfirmationAuthenticatorGetTest,
-      public testing::WithParamInterface<bool> {
- public:
-  SecurePaymentConfirmationParameterizedAuthenticatorGetTest() {
-    if (IsRpFieldEnabled()) {
-      features_.InitAndDisableFeature(
-          ::features::kSecurePaymentConfirmationRemoveRpField);
-    } else {
-      features_.InitAndEnableFeature(
-          ::features::kSecurePaymentConfirmationRemoveRpField);
-    }
-  }
-
-  ~SecurePaymentConfirmationParameterizedAuthenticatorGetTest() override =
-      default;
-
-  bool IsRpFieldEnabled() { return GetParam(); }
-
- private:
-  base::test::ScopedFeatureList features_;
-};
-
-IN_PROC_BROWSER_TEST_P(
-    SecurePaymentConfirmationParameterizedAuthenticatorGetTest,
-    ConfirmPaymentInCrossOriginIframe) {
-  NavigateTo("a.com", "/secure_payment_confirmation.html");
-  auto scoped_auth_env = ReplaceFidoDiscoveryFactory(/*should_succeed=*/true);
-
-  PaymentCredentialInfo credential_info;
-  CreatePaymentCredential(&credential_info);
-
-  // Load a cross-origin iframe that can initiate SPC.
-  content::WebContents* tab = GetActiveWebContents();
-  GURL iframe_url = https_server()->GetURL(
-      "b.com", "/secure_payment_confirmation_iframe.html");
-  EXPECT_TRUE(content::NavigateIframeToURL(tab, "test", iframe_url));
-
-  test_controller()->SetHasAuthenticator(true);
-  confirm_payment_ = true;
-
-  // Trigger SPC and capture the response.
-  // EvalJs waits for JavaScript promise to resolve.
-  content::RenderFrameHost* iframe = content::FrameMatchingPredicate(
-      tab->GetPrimaryPage(),
-      base::BindRepeating(&content::FrameHasSourceUrl, iframe_url));
-  std::string response =
-      content::EvalJs(
-          iframe, content::JsReplace("requestPayment($1);", credential_info.id))
-          .ExtractString();
-
-  ASSERT_EQ(std::string::npos, response.find("Error"));
-  absl::optional<base::Value> value = base::JSONReader::Read(response);
-  ASSERT_TRUE(value.has_value());
-  ASSERT_TRUE(value->is_dict());
-  const base::Value::Dict& value_dict = value->GetDict();
-  const std::string* type = value_dict.FindString("type");
-  ASSERT_NE(nullptr, type) << response;
-  EXPECT_EQ("payment.get", *type);
-
-  const std::string* origin = value_dict.FindString("origin");
-  ASSERT_NE(nullptr, origin) << response;
-  EXPECT_EQ(https_server()->GetURL("b.com", "/"), GURL(*origin));
-
-  absl::optional<bool> cross_origin = value_dict.FindBool("crossOrigin");
-  ASSERT_TRUE(cross_origin.has_value()) << response;
-  EXPECT_TRUE(cross_origin.value());
-
-  const std::string* payee_name =
-      value_dict.FindStringByDottedPath("payment.payeeName");
-  ASSERT_EQ(nullptr, payee_name) << response;
-
-  const std::string* payee_origin =
-      value_dict.FindStringByDottedPath("payment.payeeOrigin");
-  ASSERT_NE(nullptr, payee_origin) << response;
-  EXPECT_EQ(GURL("https://example-payee-origin.test"), GURL(*payee_origin));
-
-  const std::string* top_origin =
-      value_dict.FindStringByDottedPath("payment.topOrigin");
-  ASSERT_NE(nullptr, top_origin) << response;
-  EXPECT_EQ(https_server()->GetURL("a.com", "/"), GURL(*top_origin));
-  const std::string* rpId = value_dict.FindStringByDottedPath("payment.rpId");
-  ASSERT_NE(nullptr, rpId) << response;
-  EXPECT_EQ("a.com", *rpId);
-
-  // TODO(crbug.com/1356224): Remove legacy 'rp' parameter.
-  if (IsRpFieldEnabled()) {
-    const std::string* rp = value_dict.FindStringByDottedPath("payment.rp");
-    ASSERT_NE(nullptr, rp) << response;
-    EXPECT_EQ("a.com", *rp);
-  }
-
-  ExpectEnrollSystemPromptResult(
-      SecurePaymentConfirmationEnrollSystemPromptResult::kAccepted, 1);
-  ExpectAuthSystemPromptResult(
-      SecurePaymentConfirmationSystemPromptResult::kAccepted, 1);
-  ExpectEvent2Histogram({Event2::kInitiated, Event2::kShown, Event2::kCompleted,
-                         Event2::kPayClicked, Event2::kHadInitialFormOfPayment,
-                         Event2::kRequestMethodSecurePaymentConfirmation,
-                         Event2::kSelectedSecurePaymentConfirmation});
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    /* no prefix */,
-    SecurePaymentConfirmationParameterizedAuthenticatorGetTest,
-    testing::Bool(),
-    [](const testing::TestParamInfo<bool>& info) {
-      return info.param ? "RpFieldIncluded" : "RpFieldRemoved";
-    });
-
 }  // namespace
 }  // namespace payments
 
diff --git a/chrome/browser/permissions/prediction_based_permission_ui_selector_unittest.cc b/chrome/browser/permissions/prediction_based_permission_ui_selector_unittest.cc
index 32366f79..6efafe1 100644
--- a/chrome/browser/permissions/prediction_based_permission_ui_selector_unittest.cc
+++ b/chrome/browser/permissions/prediction_based_permission_ui_selector_unittest.cc
@@ -249,6 +249,7 @@
           features::kPermissionPredictions,
           features::kPermissionGeolocationPredictions,
           permissions::features::kPermissionOnDeviceNotificationPredictions,
+          permissions::features::kPermissionOnDeviceGeolocationPredictions,
       },
       {
           features::kQuietNotificationPrompts,
@@ -268,6 +269,7 @@
           features::kPermissionPredictions,
           features::kPermissionGeolocationPredictions,
           permissions::features::kPermissionOnDeviceNotificationPredictions,
+          permissions::features::kPermissionOnDeviceGeolocationPredictions,
           features::kQuietNotificationPrompts,
       },
       {
@@ -287,6 +289,7 @@
           features::kPermissionPredictions,
           features::kPermissionGeolocationPredictions,
           permissions::features::kPermissionOnDeviceNotificationPredictions,
+          permissions::features::kPermissionOnDeviceGeolocationPredictions,
           features::kQuietNotificationPrompts,
           permissions::features::kPermissionQuietChip,
       },
@@ -295,7 +298,7 @@
             prediction_selector.GetPredictionTypeToUse(
                 permissions::RequestType::kNotifications));
   // On device only works for notification permission request.
-  EXPECT_EQ(PredictionSource::USE_SERVER_SIDE,
+  EXPECT_EQ(PredictionSource::USE_ANY,
             prediction_selector.GetPredictionTypeToUse(
                 permissions::RequestType::kGeolocation));
 
@@ -304,6 +307,7 @@
   feature_list_->InitWithFeatures(
       {
           permissions::features::kPermissionOnDeviceNotificationPredictions,
+          permissions::features::kPermissionOnDeviceGeolocationPredictions,
           features::kQuietNotificationPrompts,
           permissions::features::kPermissionQuietChip,
       },
@@ -314,7 +318,7 @@
   EXPECT_EQ(PredictionSource::USE_ONDEVICE,
             prediction_selector.GetPredictionTypeToUse(
                 permissions::RequestType::kNotifications));
-  EXPECT_EQ(PredictionSource::USE_NONE,
+  EXPECT_EQ(PredictionSource::USE_ONDEVICE,
             prediction_selector.GetPredictionTypeToUse(
                 permissions::RequestType::kGeolocation));
 
@@ -329,6 +333,7 @@
       },
       {
           permissions::features::kPermissionOnDeviceNotificationPredictions,
+          permissions::features::kPermissionOnDeviceGeolocationPredictions,
       });
   EXPECT_EQ(PredictionSource::USE_SERVER_SIDE,
             prediction_selector.GetPredictionTypeToUse(
diff --git a/chrome/browser/policy/BUILD.gn b/chrome/browser/policy/BUILD.gn
index 019f006f..46e9563 100644
--- a/chrome/browser/policy/BUILD.gn
+++ b/chrome/browser/policy/BUILD.gn
@@ -357,6 +357,7 @@
       "test/suggested_content_policy_browsertest.cc",
       "test/system_features_policy_browsertest.cc",
       "test/unified_desktop_enabled_browsertest.cc",
+      "test/user_avatar_customization_selectors_enabled_policy_browsertest.cc",
     ]
 
     deps += [
diff --git a/chrome/browser/policy/test/user_avatar_customization_selectors_enabled_policy_browsertest.cc b/chrome/browser/policy/test/user_avatar_customization_selectors_enabled_policy_browsertest.cc
new file mode 100644
index 0000000..3bf06006
--- /dev/null
+++ b/chrome/browser/policy/test/user_avatar_customization_selectors_enabled_policy_browsertest.cc
@@ -0,0 +1,157 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/path_service.h"
+#include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h"
+#include "chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h"
+#include "chrome/browser/ash/login/users/chrome_user_manager.h"
+#include "chrome/browser/ash/login/users/default_user_image/default_user_images.h"
+#include "chrome/browser/policy/policy_test_utils.h"
+#include "chrome/common/chrome_paths.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/policy_types.h"
+#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_service.h"
+#include "components/user_manager/user_manager.h"
+#include "content/public/test/browser_test.h"
+
+namespace policy {
+
+// Browser tests for UserAvatarCustomizationSelectorsEnabled policy. These tests
+// set the policy value and then attempt to set the user image (avatar) using
+// various sources such as a local image (simulating camera), local image file,
+// and profile image.
+class UserAvatarCustomizationSelectorsEnabledPolicyTest : public PolicyTest {
+ public:
+  void SetUpOnMainThread() override {
+    PolicyTest::SetUpOnMainThread();
+
+    // Fetch User, which can be used to check the currently set user image
+    user_ = user_manager::UserManager::Get()->GetActiveUser();
+    // Fetch UserImageManager, which can be used to save a new user image
+    user_image_manager_ = ash::ChromeUserManager::Get()->GetUserImageManager(
+        user_->GetAccountId());
+
+    ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
+  }
+
+ protected:
+  // Set boolean value of UserAvatarCustomizationSelectorsEnabled policy
+  void SetPolicy(bool value) {
+    PolicyMap policies;
+    policies.Set(key::kUserAvatarCustomizationSelectorsEnabled,
+                 POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+                 base::Value(value), nullptr);
+    provider_.UpdateChromePolicy(policies);
+  }
+
+  ash::UserImageManager* user_image_manager_;
+  const user_manager::User* user_;
+  base::FilePath test_data_dir_;
+};
+
+class UserImageChangedWaiter : public user_manager::UserManager::Observer {
+ public:
+  UserImageChangedWaiter() {
+    run_loop_ = std::make_unique<base::RunLoop>();
+    user_manager::UserManager::Get()->AddObserver(this);
+  }
+  ~UserImageChangedWaiter() override {
+    user_manager::UserManager::Get()->RemoveObserver(this);
+  }
+
+  // UserManager::Observer override
+  // Observes user image changes, which allows tests to wait for the image to
+  // change using Wait()
+  void OnUserImageChanged(const user_manager::User& _) override {
+    run_loop_->Quit();
+  }
+
+  void Wait() { run_loop_->Run(); }
+
+  void Reset() { run_loop_ = std::make_unique<base::RunLoop>(); }
+
+ private:
+  std::unique_ptr<base::RunLoop> run_loop_;
+};
+
+// Verifies that the `kUserAvatarCustomizationSelectorsEnabled` pref disables:
+//   1. Save custom local image
+//   2. Save custom local image file
+//   3. Save profile image
+IN_PROC_BROWSER_TEST_F(UserAvatarCustomizationSelectorsEnabledPolicyTest,
+                       Disabled) {
+  SetPolicy(false);
+
+  // Verify user starts with default image
+  EXPECT_TRUE(user_->HasDefaultImage());
+
+  // Attempt to save custom local image
+  const gfx::ImageSkia& image = ash::default_user_image::GetStubDefaultImage();
+  user_image_manager_->SaveUserImage(user_manager::UserImage::CreateAndEncode(
+      image, user_manager::UserImage::FORMAT_JPEG));
+  EXPECT_TRUE(user_->HasDefaultImage());
+
+  // Attempt to save custom local image from file
+  const base::FilePath custom_image_path =
+      test_data_dir_.Append(ash::test::kUserAvatarImage1RelativePath);
+  const gfx::ImageSkia custom_image =
+      ash::test::ImageLoader(custom_image_path).Load();
+  ASSERT_FALSE(custom_image.isNull());
+  user_image_manager_->SaveUserImageFromFile(custom_image_path);
+  EXPECT_TRUE(user_->HasDefaultImage());
+
+  // Attempt to save image from profile
+  user_image_manager_->SaveUserImageFromProfileImage();
+  EXPECT_TRUE(user_->HasDefaultImage());
+
+  // Save default image. This should not be affected by policy
+  int index = ash::default_user_image::GetRandomDefaultImageIndex();
+  UserImageChangedWaiter waiter;
+  user_image_manager_->SaveUserDefaultImageIndex(index);
+  waiter.Wait();
+  EXPECT_TRUE(user_->HasDefaultImage());
+  EXPECT_EQ(index, user_->image_index());
+}
+
+IN_PROC_BROWSER_TEST_F(UserAvatarCustomizationSelectorsEnabledPolicyTest,
+                       Enabled) {
+  SetPolicy(true);
+
+  // Save custom local image
+  const gfx::ImageSkia& image = ash::default_user_image::GetStubDefaultImage();
+  UserImageChangedWaiter waiter;
+  user_image_manager_->SaveUserImage(user_manager::UserImage::CreateAndEncode(
+      image, user_manager::UserImage::FORMAT_JPEG));
+  waiter.Wait();
+  EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, user_->image_index());
+  EXPECT_TRUE(ash::test::AreImagesEqual(image, user_->GetImage()));
+
+  // Save custom local image from file
+  const base::FilePath custom_image_path =
+      test_data_dir_.Append(ash::test::kUserAvatarImage1RelativePath);
+  const gfx::ImageSkia custom_image =
+      ash::test::ImageLoader(custom_image_path).Load();
+  ASSERT_FALSE(custom_image.isNull());
+  waiter.Reset();
+  user_image_manager_->SaveUserImageFromFile(custom_image_path);
+  waiter.Wait();
+  EXPECT_EQ(user_manager::User::USER_IMAGE_EXTERNAL, user_->image_index());
+  EXPECT_TRUE(ash::test::AreImagesEqual(custom_image, user_->GetImage()));
+
+  // Save profile image
+  waiter.Reset();
+  user_image_manager_->SaveUserImageFromProfileImage();
+  waiter.Wait();
+  EXPECT_EQ(user_manager::User::USER_IMAGE_PROFILE, user_->image_index());
+
+  // Save default image. This should not be affected by policy
+  int index = ash::default_user_image::GetRandomDefaultImageIndex();
+  waiter.Reset();
+  user_image_manager_->SaveUserDefaultImageIndex(index);
+  waiter.Wait();
+  EXPECT_TRUE(user_->HasDefaultImage());
+  EXPECT_EQ(index, user_->image_index());
+}
+}  // namespace policy
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 661e7625..7ef5f21 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "ash/constants/ash_constants.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "build/branding_buildflags.h"
@@ -827,6 +828,12 @@
 const char kEasyUnlockLocalStateUserPrefs[] = "easy_unlock.user_prefs";
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+// Deprecated 03/2023
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+const char kDarkLightModeNudgeLeftToShowCount[] =
+    "ash.dark_light_mode.educational_nudge";
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
 // Register local state used only for migration (clearing or moving to a new
 // key).
 void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) {
@@ -1120,6 +1127,12 @@
   // Deprecated 03/2023.
   registry->RegisterTimePref(
       kGoogleSearchDomainMixingMetricsEmitterLastMetricsTime, base::Time());
+
+  // Deprecated 03/2023.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  registry->RegisterIntegerPref(kDarkLightModeNudgeLeftToShowCount,
+                                ash::kDarkLightModeNudgeMaxShownCount);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 }  // namespace
@@ -2175,6 +2188,11 @@
   profile_prefs->ClearPref(
       kGoogleSearchDomainMixingMetricsEmitterLastMetricsTime);
 
+// Added 03/2023.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  profile_prefs->ClearPref(kDarkLightModeNudgeLeftToShowCount);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
   // Please don't delete the following line. It is used by PRESUBMIT.py.
   // END_MIGRATE_OBSOLETE_PROFILE_PREFS
 
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_preload_unified_browsertest.cc b/chrome/browser/preloading/prefetch/search_prefetch/search_preload_unified_browsertest.cc
index 1809c94..a0be23f 100644
--- a/chrome/browser/preloading/prefetch/search_prefetch/search_preload_unified_browsertest.cc
+++ b/chrome/browser/preloading/prefetch/search_prefetch/search_preload_unified_browsertest.cc
@@ -1641,10 +1641,9 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-// Tests prerender is cancelled after SearchPrefetchService cancels prefetch
-// requests.
+// Tests cancelling prerenders should not delete the prefetched responses.
 IN_PROC_BROWSER_TEST_F(SearchPreloadUnifiedFallbackBrowserTest,
-                       FetchPrerenderFetch) {
+                       PrefetchSucceedAfterPrerenderFailed) {
   base::HistogramTester histogram_tester;
   const GURL kInitialUrl = embedded_test_server()->GetURL("/empty.html");
   const GURL kNavigatedUrl = embedded_test_server()->GetURL("/title1.html");
@@ -1682,6 +1681,8 @@
   int host_id = prerender_helper().GetHostForUrl(expected_prerender_url);
   content::test::PrerenderHostObserver prerender_observer(
       *GetActiveWebContents(), host_id);
+  // Ensure kCompleted is recorded.
+  prerender_helper().WaitForPrerenderLoadCompletion(host_id);
   prerender_helper().CancelPrerenderedPage(host_id);
   prerender_observer.WaitForDestroyed();
 
@@ -1691,19 +1692,20 @@
           GetCanonicalSearchURL(expected_prerender_url));
   EXPECT_TRUE(prefetch_status.has_value());
 
-  // TODO: Use another metric to trigger whether prerender takes a prefetched
-  // response.
-
-  // Navigate away to flush the metrics.
   ASSERT_TRUE(
       content::NavigateToURL(GetActiveWebContents(), expected_prerender_url));
   histogram_tester.ExpectUniqueSample(
       "Omnibox.SearchPrefetch.PrefetchFinalStatus.SuggestionPrefetch",
       SearchPrefetchStatus::kPrefetchServedForRealNavigation, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender",
+      StreamingSearchPrefetchURLLoader::ResponseReader::
+          ResponseDataReaderStatus::kCompleted,
+      1);
 }
 
-// Tests prerender is cancelled after SearchPrefetchService cancels prefetch
-// requests.
+// Tests that prefetched response can be served to prerender client
+// successfully.
 IN_PROC_BROWSER_TEST_F(SearchPreloadUnifiedFallbackBrowserTest,
                        FetchPrerenderActivated) {
   base::HistogramTester histogram_tester;
@@ -1739,12 +1741,16 @@
   EXPECT_TRUE(prefetch_status.has_value());
   EXPECT_NE(prefetch_status.value(), SearchPrefetchStatus::kPrerendered);
 
-  // TODO: Use another metric to trigger whether prerender takes a prefetched
-  // response.
   content::test::PrerenderHostObserver prerender_observer(
       *GetActiveWebContents(), expected_prerender_url);
   NavigateToPrerenderedResult(expected_prerender_url);
   prerender_observer.WaitForActivation();
+  WaitForActivatedPageLoaded();
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender",
+      StreamingSearchPrefetchURLLoader::ResponseReader::
+          ResponseDataReaderStatus::kCompleted,
+      1);
 }
 
 // Tests that the SearchSuggestionService can trigger prerendering if it
@@ -1798,10 +1804,16 @@
                                                         expected_prerender_url);
   NavigateToPrerenderedResult(expected_prerender_url);
   prerender_observer.WaitForActivation();
+  WaitForActivatedPageLoaded();
 
   // No prerender requests went through network.
   EXPECT_EQ(1, prerender_helper().GetRequestCount(expected_prefetch_url));
   EXPECT_EQ(0, prerender_helper().GetRequestCount(expected_prerender_url));
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender",
+      StreamingSearchPrefetchURLLoader::ResponseReader::
+          ResponseDataReaderStatus::kCompleted,
+      1);
 }
 
 // Tests that once prefetch encountered error, prerender would be canceled as
@@ -1849,12 +1861,11 @@
   prerender_observer.WaitForDestroyed();
   WaitUntilStatusChangesTo(GetCanonicalSearchURL(expected_prefetch_url),
                            {SearchPrefetchStatus::kRequestFailed});
-  // TODO(crbug.com/1400881): We should have another metric to track the
-  // cancellation reason.
   histogram_tester.ExpectUniqueSample(
-      "Prerender.Experimental.PrerenderHostFinalStatus.Embedder_"
-      "DefaultSearchEngine",
-      /*SearchPrefetchStatus::kPrefetchServedForRealNavigation*/ 16, 1);
+      "Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender",
+      StreamingSearchPrefetchURLLoader::ResponseReader::
+          ResponseDataReaderStatus::kNetworkError,
+      1);
 }
 
 // Tests that if prerender is canceled by itself before the loader receives
@@ -1914,6 +1925,11 @@
   histogram_tester.ExpectUniqueSample(
       "Omnibox.SearchPrefetch.PrefetchFinalStatus.SuggestionPrefetch",
       SearchPrefetchStatus::kPrefetchServedForRealNavigation, 1);
+  histogram_tester.ExpectUniqueSample(
+      "Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender",
+      StreamingSearchPrefetchURLLoader::ResponseReader::
+          ResponseDataReaderStatus::kServingError,
+      1);
 }
 
 // Edge case: when the prerendering navigation is still reading from the cache,
@@ -1983,6 +1999,11 @@
   // Prerender should not retry the request.
   EXPECT_EQ(0, prerender_helper().GetRequestCount(expected_prerender_url));
   EXPECT_EQ(1, prerender_helper().GetRequestCount(expected_prefetch_url));
+  histogram_tester.ExpectUniqueSample(
+      "Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender",
+      StreamingSearchPrefetchURLLoader::ResponseReader::
+          ResponseDataReaderStatus::kCompleted,
+      1);
 }
 
 class NoCancelSearchPreloadUnifiedFallbackBrowserTest
@@ -2012,7 +2033,7 @@
 // prefetched result in another tab and activate the prefetched response
 // successfully.
 IN_PROC_BROWSER_TEST_F(NoCancelSearchPreloadUnifiedFallbackBrowserTest,
-                       ServingToPrerenderingUntilCompletion) {
+                       OpenPrefetchedResponseInBackgroundedTab) {
   base::HistogramTester histogram_tester;
   set_service_deferral_type(
       SearchPreloadTestResponseDeferralType::kDeferChunkedResponseBody);
@@ -2064,6 +2085,7 @@
                                     ui::PAGE_TRANSITION_FROM_ADDRESS_BAR),
           /*is_renderer_initiated=*/false));
   WaitUntilStatusChangesTo(GetCanonicalSearchURL(expected_prerender_url), {});
+
   // TODO(crbug.com/1423259): Ideally we should open the tab with the
   // prerendered result.
   prerender_observer.WaitForDestroyed();
@@ -2101,6 +2123,17 @@
   EXPECT_TRUE(base::Contains(prefetch_inner_html, "PREFETCH"));
   EXPECT_EQ(0, prerender_helper().GetRequestCount(expected_prerender_url));
   EXPECT_EQ(2, prerender_helper().GetRequestCount(expected_prefetch_url));
+
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender",
+      StreamingSearchPrefetchURLLoader::ResponseReader::
+          ResponseDataReaderStatus::kServingError,
+      1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender",
+      StreamingSearchPrefetchURLLoader::ResponseReader::
+          ResponseDataReaderStatus::kCompleted,
+      1);
 }
 
 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc b/chrome/browser/preloading/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
index c5ac5cad..29323f93 100644
--- a/chrome/browser/preloading/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
+++ b/chrome/browser/preloading/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/storage_partition.h"
 #include "mojo/public/c/system/data_pipe.h"
+#include "net/base/net_errors.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -71,9 +72,9 @@
     mojo::PendingRemote<network::mojom::URLLoaderClient> forwarding_client,
     base::OnceCallback<void(ResponseReader*)> forwarding_disconnection_callback,
     absl::optional<network::URLLoaderCompletionStatus> status,
-    StreamingSearchPrefetchURLLoader* loader)
+    base::WeakPtr<StreamingSearchPrefetchURLLoader> loader)
     : disconnection_callback_(std::move(forwarding_disconnection_callback)),
-      loader_(loader),
+      loader_(std::move(loader)),
       url_loader_completion_status_(status) {
   forwarding_receiver_.Bind(std::move(forward_receiver));
   forwarding_client_.Bind(std::move(forwarding_client));
@@ -84,12 +85,23 @@
                      base::Unretained(this)));
 }
 
-StreamingSearchPrefetchURLLoader::ResponseReader::~ResponseReader() = default;
+StreamingSearchPrefetchURLLoader::ResponseReader::~ResponseReader() {
+  // Always ensure we recorded something on destruction.
+  OnDestroyed();
+
+  // TODO(crbug.com/1400881): For now prerender is the only use case. After
+  // refactoring it should specify the client type.
+  base::UmaHistogramEnumeration(
+      "Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender", status_);
+}
 
 void StreamingSearchPrefetchURLLoader::ResponseReader::OnStatusCodeReady(
     const network::URLLoaderCompletionStatus& status) {
   DCHECK(!url_loader_completion_status_);
   url_loader_completion_status_ = status;
+  if (url_loader_completion_status_->error_code != net::OK) {
+    status_ = ResponseDataReaderStatus::kNetworkError;
+  }
   MaybeSendCompletionSignal();
 }
 
@@ -100,13 +112,13 @@
   MojoResult rv =
       CreateDataPipeForServingData(producer_handle_, consumer_handle);
   if (rv != MOJO_RESULT_OK) {
+    status_ = ResponseDataReaderStatus::kServingError;
     OnForwardingDisconnection();
     return;
   }
   handle_watcher_ = std::make_unique<mojo::SimpleWatcher>(
       FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL,
       base::SequencedTaskRunner::GetCurrentDefault());
-
   // It is safe to use `base::Unretained(this)` as `this` owns the watcher.
   handle_watcher_->Watch(
       producer_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
@@ -120,6 +132,10 @@
 }
 
 void StreamingSearchPrefetchURLLoader::ResponseReader::PushData() {
+  if (!loader_) {
+    // This will be deleted soon.
+    return;
+  }
   while (true) {
     base::StringPiece response_data =
         loader_->GetMoreDataFromCache(write_position_);
@@ -141,6 +157,8 @@
 
     if (result != MOJO_RESULT_OK) {
       OnForwardingDisconnection();
+      // This case is usually caused by the client stopping loading.
+      status_ = ResponseDataReaderStatus::kServingError;
       return;
     }
 
@@ -159,6 +177,7 @@
     return;
   }
   if (result != MOJO_RESULT_OK) {
+    status_ = ResponseDataReaderStatus::kServingError;
     OnForwardingDisconnection();
     return;
   }
@@ -171,6 +190,9 @@
     return;
   }
   if (producer_handle_) {
+    if (url_loader_completion_status_->error_code == net::OK) {
+      status_ = ResponseDataReaderStatus::kCompleted;
+    }
     forwarding_client_->OnComplete(*url_loader_completion_status_);
   }
   producer_handle_.reset();
@@ -178,8 +200,32 @@
 
 void StreamingSearchPrefetchURLLoader::ResponseReader::
     OnForwardingDisconnection() {
-  if (disconnection_callback_) {
-    std::move(disconnection_callback_).Run(this);
+  if (!disconnection_callback_) {
+    return;
+  }
+  // If we receive the disconnection signal before completing serving, there
+  // should be a serving error.
+  if (status_ == ResponseDataReaderStatus::kCreated) {
+    status_ = ResponseDataReaderStatus::kServingError;
+  }
+  std::move(disconnection_callback_).Run(this);
+}
+
+void StreamingSearchPrefetchURLLoader::ResponseReader::OnDestroyed() {
+  switch (status_) {
+    // Has completed serving.
+    case ResponseDataReaderStatus::kCompleted:
+    // For tracking failures.
+    case ResponseDataReaderStatus::kServingError:
+    case ResponseDataReaderStatus::kNetworkError:
+    case ResponseDataReaderStatus::kCanceledByLoader:
+      return;
+    // The `StreamingSearchPrefetchURLLoader` is destroyed, or it wants to
+    // create a new reader and serves to a new clients, so this instance is
+    // destroyed.
+    case ResponseDataReaderStatus::kCreated:
+      status_ = ResponseDataReaderStatus::kCanceledByLoader;
+      return;
   }
 }
 
@@ -299,6 +345,7 @@
     // serving.
     self_pointer_ = std::move(self_loader);
   }
+  LOG(ERROR) << self_loader.get();
   return self_loader;
 }
 
@@ -368,7 +415,7 @@
       base::BindOnce(
           &StreamingSearchPrefetchURLLoader::OnPrerenderForwardingDisconnect,
           weak_factory_.GetWeakPtr()),
-      status_, this);
+      status_, weak_factory_.GetWeakPtr());
   response_reader_for_prerender_->StartReadingResponseFromData(
       resource_response_);
   response_reader_for_prerender_->PushData();
@@ -658,6 +705,10 @@
     OnForwardingComplete();
     return;
   }
+  status_ = status;
+  if (response_reader_for_prerender_) {
+    response_reader_for_prerender_->OnStatusCodeReady(status);
+  }
 
   if (streaming_prefetch_request_) {
     DCHECK(!forwarding_client_);
@@ -669,11 +720,6 @@
       return;
     }
   }
-
-  status_ = status;
-  if (response_reader_for_prerender_) {
-    response_reader_for_prerender_->OnStatusCodeReady(status);
-  }
 }
 
 void StreamingSearchPrefetchURLLoader::RunEventQueue() {
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h b/chrome/browser/preloading/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
index ed5fe2d9..29cd38c 100644
--- a/chrome/browser/preloading/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
+++ b/chrome/browser/preloading/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
@@ -39,13 +39,32 @@
   // `StreamingSearchPrefetchURLLoader`'s data cache.
   class ResponseReader : public network::mojom::URLLoader {
    public:
+    // These values are persisted to logs. Entries should not be renumbered and
+    // numeric values should never be reused. Recorded as
+    // SearchPrefetchResponseDataReaderStatus in logs.
+    enum class ResponseDataReaderStatus {
+      kCreated = 0,
+      // This reader failed to push data to its clients. This is usually caused
+      // by the clients refused to receive data after destruction.
+      kServingError = 1,
+      // The loader receives an error from the network and terminates this
+      // reader.
+      kNetworkError = 2,
+      // For a success serving case.
+      kCompleted = 3,
+      // Its owner deletes this instance before this instance encounters any
+      // issues or completes serving.
+      kCanceledByLoader = 4,
+      kMaxValue = kCanceledByLoader,
+    };
+
     ResponseReader(
         mojo::PendingReceiver<network::mojom::URLLoader> forward_receiver,
         mojo::PendingRemote<network::mojom::URLLoaderClient> forwarding_client,
         base::OnceCallback<void(ResponseReader*)>
             forwarding_disconnection_callback,
         absl::optional<network::URLLoaderCompletionStatus>,
-        StreamingSearchPrefetchURLLoader* loader);
+        base::WeakPtr<StreamingSearchPrefetchURLLoader> loader);
     ~ResponseReader() override;
 
     // Not copyable nor movable.
@@ -81,6 +100,7 @@
     // Called by `StreamingSearchPrefetchURLLoader` to inform it of the
     // received response.
     void OnStatusCodeReady(const network::URLLoaderCompletionStatus& status);
+    void OnDestroyed();
 
    private:
     // Checks if all data have be pushed to its consumer and the corresponding
@@ -99,6 +119,9 @@
     //            write_position_         end of response body.
     int write_position_ = 0;
 
+    // Tracking the current status.
+    ResponseDataReaderStatus status_ = ResponseDataReaderStatus::kCreated;
+
     // Data pipe for pushing the received response to the client.
     mojo::ScopedDataPipeProducerHandle producer_handle_;
     std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
@@ -111,11 +134,12 @@
     // loader to delete itself.
     base::OnceCallback<void(ResponseReader*)> disconnection_callback_;
 
-    // 'loader_' owns this, and guarantees that `loader_` won't be deleted
-    // before deleting `this`, so it is safe to keep a ref.
+    // 'loader_' owns `this`. Note that `this` would be deleted asynchronously
+    // and `loader_` can be deleted synchronously, their destruction order is
+    // not guaranteed so here is a weakptr.
     // TODO(crbug.com/1400881): This breaks the hierarchy. Will be replaced soon
     // after refactoring.
-    raw_ptr<StreamingSearchPrefetchURLLoader> loader_;
+    base::WeakPtr<StreamingSearchPrefetchURLLoader> loader_;
 
     // Records the completion status for the corresponding network loader.
     absl::optional<network::URLLoaderCompletionStatus>
@@ -284,7 +308,7 @@
   // the navigation stack.
   raw_ptr<SearchPrefetchRequest> streaming_prefetch_request_;
 
-  // Whether we are serving from |bdoy_content_|.
+  // Whether we are serving from |body_content_|.
   bool serving_from_data_ = false;
 
   // The status returned from |network_url_loader_|.
diff --git a/chrome/browser/profiles/delete_profile_helper.cc b/chrome/browser/profiles/delete_profile_helper.cc
index ae4096aa..ce481ef 100644
--- a/chrome/browser/profiles/delete_profile_helper.cc
+++ b/chrome/browser/profiles/delete_profile_helper.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/profiles/delete_profile_helper.h"
 
-#include <memory>
-
 #include "base/check.h"
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
@@ -20,7 +18,6 @@
 #include "chrome/browser/download/download_core_service.h"
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
-#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
 #include "chrome/browser/profiles/nuke_profile_directory_utils.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
@@ -129,8 +126,7 @@
 }
 
 void DeleteProfileHelper::ScheduleEphemeralProfileForDeletion(
-    const base::FilePath& profile_dir,
-    std::unique_ptr<ScopedProfileKeepAlive> keep_alive) {
+    const base::FilePath& profile_dir) {
   DCHECK(IsRegisteredAsEphemeral(
       &profile_manager_->GetProfileAttributesStorage(), profile_dir));
   DCHECK_EQ(0u, chrome::GetBrowserCount(
@@ -147,8 +143,7 @@
   DCHECK(!new_active_profile_dir->empty());
   RemoveFromLastActiveProfilesPrefList(profile_dir);
 
-  FinishDeletingProfile(profile_dir, new_active_profile_dir.value(),
-                        std::move(keep_alive));
+  FinishDeletingProfile(profile_dir, new_active_profile_dir.value());
 }
 
 void DeleteProfileHelper::CleanUpEphemeralProfiles() {
@@ -245,12 +240,7 @@
       profile_manager_->GetProfileByPath(last_used_profile_path);
   if (last_used_profile_path != profile_dir &&
       last_used_profile_path != guest_profile_path && last_used_profile) {
-    Profile* profile = profile_manager_->GetProfileByPath(profile_dir);
-    FinishDeletingProfile(
-        profile_dir, last_used_profile_path,
-        profile ? std::make_unique<ScopedProfileKeepAlive>(
-                      profile, ProfileKeepAliveOrigin::kProfileDeletionProcess)
-                : nullptr);
+    FinishDeletingProfile(profile_dir, last_used_profile_path);
     return;
   }
 
@@ -302,8 +292,7 @@
 
 void DeleteProfileHelper::FinishDeletingProfile(
     const base::FilePath& profile_dir,
-    const base::FilePath& new_active_profile_dir,
-    std::unique_ptr<ScopedProfileKeepAlive> keep_alive) {
+    const base::FilePath& new_active_profile_dir) {
   // Update the last used profile pref before closing browser windows. This
   // way the correct last used profile is set for any notification observers.
   profiles::SetLastUsedProfile(new_active_profile_dir.BaseName());
@@ -313,8 +302,7 @@
   profile_manager_->LoadProfileByPath(
       profile_dir, false,
       base::BindOnce(&DeleteProfileHelper::OnLoadProfileForProfileDeletion,
-                     base::Unretained(this), profile_dir,
-                     std::move(keep_alive)));
+                     base::Unretained(this), profile_dir));
   if (!IsProfileDirectoryMarkedForDeletion(profile_dir)) {
     // Prevents CreateProfileAsync from re-creating the profile.
     MarkProfileDirectoryForDeletion(profile_dir);
@@ -323,7 +311,6 @@
 
 void DeleteProfileHelper::OnLoadProfileForProfileDeletion(
     const base::FilePath& profile_dir,
-    std::unique_ptr<ScopedProfileKeepAlive> keep_alive,
     Profile* profile) {
   ProfileAttributesStorage& storage =
       profile_manager_->GetProfileAttributesStorage();
@@ -405,13 +392,6 @@
     return;
   }
 
-  Profile* profile_to_delete =
-      profile_manager_->GetProfileByPath(profile_to_delete_path);
-  FinishDeletingProfile(
-      profile_to_delete_path, new_active_profile_path,
-      profile_to_delete ? std::make_unique<ScopedProfileKeepAlive>(
-                              profile_to_delete,
-                              ProfileKeepAliveOrigin::kProfileDeletionProcess)
-                        : nullptr);
+  FinishDeletingProfile(profile_to_delete_path, new_active_profile_path);
   std::move(callback).Run(loaded_profile);
 }
diff --git a/chrome/browser/profiles/delete_profile_helper.h b/chrome/browser/profiles/delete_profile_helper.h
index e529c24f..d2b5da4 100644
--- a/chrome/browser/profiles/delete_profile_helper.h
+++ b/chrome/browser/profiles/delete_profile_helper.h
@@ -7,7 +7,6 @@
 
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ref.h"
-#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
 #include "chrome/browser/profiles/profile_metrics.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -52,9 +51,7 @@
   // Schedules the ephemeral profile at the given path to be deleted. New
   // profiles will not be created. If the profile is not loaded, this may
   // trigger a reload of the profile so that user data is cleaned up.
-  void ScheduleEphemeralProfileForDeletion(
-      const base::FilePath& profile_dir,
-      std::unique_ptr<ScopedProfileKeepAlive> keep_alive);
+  void ScheduleEphemeralProfileForDeletion(const base::FilePath& profile_dir);
 
   // Checks if any profiles are left behind (e.g. because of a browser
   // crash) and schedule them for deletion. Unlike the "Schedule" methods above,
@@ -76,14 +73,10 @@
 
   // Schedules the profile at the given path to be deleted on shutdown,
   // and marks the new profile as active.
-  void FinishDeletingProfile(
-      const base::FilePath& profile_dir,
-      const base::FilePath& new_active_profile_dir,
-      std::unique_ptr<ScopedProfileKeepAlive> keep_alive);
-  void OnLoadProfileForProfileDeletion(
-      const base::FilePath& profile_dir,
-      std::unique_ptr<ScopedProfileKeepAlive> keep_alive,
-      Profile* profile);
+  void FinishDeletingProfile(const base::FilePath& profile_dir,
+                             const base::FilePath& new_active_profile_dir);
+  void OnLoadProfileForProfileDeletion(const base::FilePath& profile_dir,
+                                       Profile* profile);
 
   // If the `loaded_profile` has been loaded successfully and isn't already
   // scheduled for deletion, then finishes adding `profile_to_delete_dir` to the
diff --git a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc
index ff5d412a..79634dd 100644
--- a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc
+++ b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc
@@ -69,8 +69,6 @@
       return out << "kProfileCreationSamlFlow";
     case ProfileKeepAliveOrigin::kDriveFsNativeMessageHostLacros:
       return out << "kDriveFsNativeMessageHostLacros";
-    case ProfileKeepAliveOrigin::kProfileDeletionProcess:
-      return out << "kProfileDeletionProcess";
   }
   NOTREACHED();
   return out << static_cast<int>(origin);
diff --git a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h
index b9de360..378d062f 100644
--- a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h
+++ b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h
@@ -86,9 +86,6 @@
   kExtensionUpdater = 18,
 
   // This profile is being created (and is used to render GAIA sign-in flow).
-  // The profile creation flow either opens a browser window before
-  // kProfileCreationFlow keep alive is released or gets aborted without opening
-  // a browser window and in that case the profile should be removed.
   kProfileCreationFlow = 19,
 
   // The user just closed a notification. This might cause writing to the
@@ -138,13 +135,7 @@
   // This keeps the profile alive while the connection is active.
   kDriveFsNativeMessageHostLacros = 31,
 
-  // Used during the deletion process for the respective profile. Avoids the
-  // profile from being randomly unloaded. Useful to keep an ephemeral profile
-  // alive until their deletion is completed, after releasing its last keep
-  // alive.
-  kProfileDeletionProcess = 32,
-
-  kMaxValue = kProfileDeletionProcess,
+  kMaxValue = kDriveFsNativeMessageHostLacros,
 };
 
 std::ostream& operator<<(std::ostream& out,
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc
index 4d8fae2..2be5b51 100644
--- a/chrome/browser/profiles/profile_downloader.cc
+++ b/chrome/browser/profiles/profile_downloader.cc
@@ -192,10 +192,13 @@
         policy {
           cookies_allowed: NO
           setting: "This feature cannot be disabled by settings."
-          policy_exception_justification:
-            "Not implemented, considered not useful as no content is being "
-            "uploaded or saved; this request merely downloads the user's "
-            "Google account image."
+          chrome_policy {
+            subProto1 {
+              UserAvatarCustomizationSelectorsEnabled {
+                UserAvatarCustomizationSelectorsEnabled: false
+              }
+            }
+          }
         })");
 
   VLOG(1) << "Loading profile image from " << image_url_to_fetch;
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 13171da..dd1bb05 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -1288,7 +1288,6 @@
           << "). keep_alives=" << info->keep_alives;
 
   if (origin == ProfileKeepAliveOrigin::kBrowserWindow ||
-      origin == ProfileKeepAliveOrigin::kProfileCreationFlow ||
       (origin == ProfileKeepAliveOrigin::kProfilePickerView &&
        base::FeatureList::IsEnabled(features::kDestroySystemProfiles))) {
     ClearFirstBrowserWindowKeepAlive(profile);
@@ -1302,8 +1301,7 @@
   CHECK(profile);
   CHECK(!profile->IsOffTheRecord());
 
-  const base::FilePath profile_path = profile->GetPath();
-  ProfileInfo* info = GetProfileInfoByPath(profile_path);
+  ProfileInfo* info = GetProfileInfoByPath(profile->GetPath());
   if (!info) {
     // Can be null in unit tests, when the Profile was not created via
     // ProfileManager.
@@ -1316,22 +1314,6 @@
   }
 
   DCHECK(base::Contains(info->keep_alives, origin));
-
-#if !BUILDFLAG(IS_ANDROID)
-  // When removing the last keep alive of an ephemeral profile, schedule the
-  // profile for deletion if it is not yet marked.
-  bool ephemeral =
-      IsRegisteredAsEphemeral(&GetProfileAttributesStorage(), profile_path);
-  bool marked_for_deletion = IsProfileDirectoryMarkedForDeletion(profile_path);
-  if (ephemeral && !marked_for_deletion &&
-      GetTotalRefCount(info->keep_alives) == 1) {
-    delete_profile_helper_->ScheduleEphemeralProfileForDeletion(
-        profile_path,
-        std::make_unique<ScopedProfileKeepAlive>(
-            profile, ProfileKeepAliveOrigin::kProfileDeletionProcess));
-  }
-#endif
-
   info->keep_alives[origin]--;
   DCHECK_LE(0, info->keep_alives[origin]);
 
@@ -2089,8 +2071,16 @@
   }
 
   base::FilePath path = profile->GetPath();
+  ProfileInfo* info = GetProfileInfoByPath(path);
   if (IsProfileDirectoryMarkedForDeletion(path)) {
     // Do nothing if the profile is already being deleted.
+  } else if (IsRegisteredAsEphemeral(&GetProfileAttributesStorage(), path) &&
+             info->keep_alives[ProfileKeepAliveOrigin::kProfileCreationFlow] ==
+                 0) {
+    // Delete if the profile is an ephemeral profile and it is not in the
+    // profile creation flow.
+    // TODO(crbug.com/1369535): Delete the profile when there is no keep alive.
+    delete_profile_helper_->ScheduleEphemeralProfileForDeletion(path);
   } else if (!profile->IsOffTheRecord()) {
     auto* browsing_data_lifetime_manager =
         ChromeBrowsingDataLifetimeManagerFactory::GetForProfile(
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc
index 77ce3cfa..b1dcd0d3 100644
--- a/chrome/browser/profiles/profiles_state.cc
+++ b/chrome/browser/profiles/profiles_state.cc
@@ -39,6 +39,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/constants/ash_switches.h"
+#include "chrome/browser/ash/login/demo_mode/demo_session.h"
 #include "chromeos/ash/components/login/login_state/login_state.h"
 #else
 #include <algorithm>
@@ -301,6 +302,14 @@
 #endif
 }
 
+bool IsDemoSession() {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  return ash::DemoSession::IsDeviceInDemoMode();
+#else
+  return false;
+#endif
+}
+
 bool IsChromeAppKioskSession() {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   return user_manager::UserManager::Get()->IsLoggedInAsKioskApp();
diff --git a/chrome/browser/profiles/profiles_state.h b/chrome/browser/profiles/profiles_state.h
index 164b858..b487c9e 100644
--- a/chrome/browser/profiles/profiles_state.h
+++ b/chrome/browser/profiles/profiles_state.h
@@ -114,6 +114,9 @@
 // Returns whether a kiosk session is being run currently.
 bool IsKioskSession();
 
+// Returns true if the current session is a Demo session.
+bool IsDemoSession();
+
 // Returns true if the current session is a Chrome App Kiosk session.
 bool IsChromeAppKioskSession();
 
diff --git a/chrome/browser/recent_tabs/BUILD.gn b/chrome/browser/recent_tabs/BUILD.gn
index 5ea2ff0..68d349c4 100644
--- a/chrome/browser/recent_tabs/BUILD.gn
+++ b/chrome/browser/recent_tabs/BUILD.gn
@@ -17,6 +17,7 @@
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/tab:java",
     "//content/public/android:content_java",
+    "//third_party/androidx:androidx_annotation_annotation_java",
     "//url:gurl_java",
   ]
 
@@ -28,6 +29,7 @@
 
   deps = [
     ":java",
+    "//chrome/browser/profiles/android:java",
     "//chrome/browser/recent_tabs/internal:java",
   ]
 }
diff --git a/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/ForeignSessionHelper.java b/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/ForeignSessionHelper.java
index be58f08..28dfe485 100644
--- a/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/ForeignSessionHelper.java
+++ b/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/ForeignSessionHelper.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.recent_tabs;
 
+import androidx.annotation.VisibleForTesting;
+
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -44,7 +46,8 @@
         public final long modifiedTime;
         public final List<ForeignSessionWindow> windows = new ArrayList<ForeignSessionWindow>();
 
-        protected ForeignSession(String tag, String name, long modifiedTime) {
+        @VisibleForTesting
+        public ForeignSession(String tag, String name, long modifiedTime) {
             this.tag = tag;
             this.name = name;
             this.modifiedTime = modifiedTime;
diff --git a/chrome/browser/recent_tabs/internal/BUILD.gn b/chrome/browser/recent_tabs/internal/BUILD.gn
index 3a52c7d..280636c 100644
--- a/chrome/browser/recent_tabs/internal/BUILD.gn
+++ b/chrome/browser/recent_tabs/internal/BUILD.gn
@@ -18,6 +18,8 @@
     "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperImpl.java",
     "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediator.java",
     "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsProperties.java",
+    "android/java/src/org/chromium/chrome/browser/recent_tabs/ui/ForeignSessionItemProperties.java",
+    "android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsDetailScreenCoordinator.java",
     "android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsPromoScreenCoordinator.java",
   ]
 
@@ -38,12 +40,15 @@
   testonly = true
 
   sources = [
+    "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java",
     "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperUnitTest.java",
     "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java",
+    "android/java/src/org/chromium/chrome/browser/recent_tabs/ui/ForeignSessionItemPropertiesUnitTest.java",
   ]
 
   deps = [
     ":java",
+    "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
     "//chrome/browser/feature_engagement:java",
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java
index c8d11ce..9b996ef 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java
@@ -4,22 +4,27 @@
 
 package org.chromium.chrome.browser.recent_tabs;
 
-import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.browser.profiles.Profile;
 
 /**
  * A factory interface for building a RestoreTabsController instance.
  */
 public class RestoreTabsControllerFactory {
-    private static RestoreTabsControllerImpl sInstance;
+    /**
+     * A listener to indicate the lifecycle status of the RestoreTabs feature.
+     */
+    public interface ControllerListener {
+        /**
+         * Action to perform when the restore tabs promo is done showing.
+         */
+        public void onDismissed();
+    }
 
     /**
-     * @return The singleton instance of RestoreTabsControllerImpl.
+     * @return An instance of RestoreTabsControllerImpl.
      */
-    public static RestoreTabsControllerImpl getInstance() {
-        ThreadUtils.assertOnUiThread();
-        if (sInstance == null) {
-            sInstance = new RestoreTabsControllerImpl();
-        }
-        return sInstance;
+    public static RestoreTabsControllerImpl createInstance(
+            Profile profile, RestoreTabsControllerFactory.ControllerListener listener) {
+        return new RestoreTabsControllerImpl(profile, listener);
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerImpl.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerImpl.java
index edc89d74..c760c77 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerImpl.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerImpl.java
@@ -13,17 +13,23 @@
     private RestoreTabsFeatureHelper mHelper;
     private RestoreTabsCoordinator mRestoreTabsCoordinator;
 
-    public RestoreTabsControllerImpl() {
+    public RestoreTabsControllerImpl(
+            Profile profile, RestoreTabsControllerFactory.ControllerListener listener) {
         mHelper = new RestoreTabsFeatureHelperImpl();
-        mRestoreTabsCoordinator = new RestoreTabsCoordinator();
-        mRestoreTabsCoordinator.initialize();
+        mRestoreTabsCoordinator = new RestoreTabsCoordinator(profile, listener);
+    }
+
+    public void destroy() {
+        mRestoreTabsCoordinator.destroy();
+        mRestoreTabsCoordinator = null;
+        mHelper = null;
     }
 
     public RestoreTabsFeatureHelper getFeatureHelper() {
         return mHelper;
     }
 
-    public void showBottomSheet(Profile profile) {
-        mRestoreTabsCoordinator.showOptions(profile);
+    public void showBottomSheet() {
+        mRestoreTabsCoordinator.showOptions();
     }
 }
\ No newline at end of file
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinator.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinator.java
index 1e236db..85b0452 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinator.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinator.java
@@ -5,27 +5,36 @@
 package org.chromium.chrome.browser.recent_tabs;
 
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSession;
 import org.chromium.ui.modelutil.PropertyModel;
 
-import java.util.List;
-
 /**
  * Coordinator to manage the Restore Tabs on FRE feature.
  */
 public class RestoreTabsCoordinator {
-    private RestoreTabsMediator mMediator = new RestoreTabsMediator();
+    private ForeignSessionHelper mForeignSessionHelper;
+    private RestoreTabsMediator mMediator;
     private PropertyModel mModel = RestoreTabsProperties.createDefaultModel();
 
-    public void initialize() {
-        mMediator.initialize(mModel);
+    public RestoreTabsCoordinator(
+            Profile profile, RestoreTabsControllerFactory.ControllerListener listener) {
+        this(new ForeignSessionHelper(profile), new RestoreTabsMediator(), listener);
     }
 
-    public void showOptions(Profile profile) {
-        ForeignSessionHelper foreignSessionHelper = new ForeignSessionHelper(profile);
-        List<ForeignSession> sessions = foreignSessionHelper.getForeignSessions();
-        foreignSessionHelper.destroy();
+    protected RestoreTabsCoordinator(ForeignSessionHelper helper, RestoreTabsMediator mediator,
+            RestoreTabsControllerFactory.ControllerListener listener) {
+        mForeignSessionHelper = helper;
+        mMediator = mediator;
+        mMediator.initialize(mModel, listener);
+    }
 
-        mMediator.showOptions(sessions);
+    public void destroy() {
+        mForeignSessionHelper.destroy();
+        mForeignSessionHelper = null;
+        mMediator.destroy();
+        mMediator = null;
+    }
+
+    public void showOptions() {
+        mMediator.showOptions(mForeignSessionHelper.getForeignSessions());
     }
 }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java
new file mode 100644
index 0000000..09ce585
--- /dev/null
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java
@@ -0,0 +1,59 @@
+// Copyright 2023 The Chromium Authors
+// 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.recent_tabs;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSession;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for RestoreTabsCoordinator.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class RestoreTabsCoordinatorUnitTest {
+    @Mock
+    private RestoreTabsMediator mMediator;
+    @Mock
+    private ForeignSessionHelper mForeignSessionHelper;
+
+    private RestoreTabsCoordinator mCoordinator;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mCoordinator = new RestoreTabsCoordinator(mForeignSessionHelper, mMediator,
+                new RestoreTabsControllerFactory.ControllerListener() {
+                    @Override
+                    public void onDismissed() {
+                        mCoordinator.destroy();
+                    }
+                });
+    }
+
+    @Test
+    public void testRestoreTabsCoordinator_showOptions() {
+        ForeignSession session = new ForeignSession("tag", "John's iPhone 6", 32L);
+        List<ForeignSession> testSessions = new ArrayList<>();
+        testSessions.add(session);
+
+        when(mForeignSessionHelper.getForeignSessions()).thenReturn(testSessions);
+        mCoordinator.showOptions();
+        verify(mMediator, times(1)).showOptions(testSessions);
+    }
+}
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperUnitTest.java
index 1b0ea5c..3d73f413 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsFeatureHelperUnitTest.java
@@ -11,6 +11,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -18,6 +19,7 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.feature_engagement.EventConstants;
@@ -32,19 +34,26 @@
     private RestoreTabsControllerImpl mController;
     private RestoreTabsFeatureHelper mHelper;
 
-    @Mock
-    private Profile mProfile;
+    @Rule
+    public JniMocker jniMocker = new JniMocker();
 
     @Mock
+    ForeignSessionHelper.Natives mForeignSessionHelperJniMock;
+    @Mock
+    private Profile mProfile;
+    @Mock
     private Tracker mTracker;
+    @Mock
+    private RestoreTabsControllerFactory.ControllerListener mListener;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         Profile.setLastUsedProfileForTesting(mProfile);
         TrackerFactory.setTrackerForTests(mTracker);
+        jniMocker.mock(ForeignSessionHelperJni.TEST_HOOKS, mForeignSessionHelperJniMock);
 
-        mController = RestoreTabsControllerFactory.getInstance();
+        mController = RestoreTabsControllerFactory.createInstance(mProfile, mListener);
         mHelper = mController.getFeatureHelper();
     }
 
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediator.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediator.java
index 3481590b..bfe4056f 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediator.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediator.java
@@ -5,7 +5,12 @@
 package org.chromium.chrome.browser.recent_tabs;
 
 import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSession;
+import org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.DetailItemType;
+import org.chromium.chrome.browser.recent_tabs.ui.ForeignSessionItemProperties;
+import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsDetailScreenCoordinator;
 import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsPromoScreenCoordinator;
+import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
+import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
 import org.chromium.ui.modelutil.PropertyModel;
 
 import java.util.List;
@@ -14,11 +19,20 @@
  * Contains the logic to set the state of the model and react to events like clicks.
  */
 public class RestoreTabsMediator {
+    private RestoreTabsControllerFactory.ControllerListener mListener;
     private PropertyModel mModel;
 
-    public void initialize(PropertyModel model) {
+    public void initialize(
+            PropertyModel model, RestoreTabsControllerFactory.ControllerListener listener) {
+        mListener = listener;
         mModel = model;
         mModel.set(RestoreTabsProperties.HOME_SCREEN_DELEGATE, createHomeScreenDelegate());
+        mModel.set(RestoreTabsProperties.DETAIL_SCREEN_BACK_CLICK_HANDLER,
+                () -> { setCurrentScreen(RestoreTabsProperties.ScreenType.HOME_SCREEN); });
+    }
+
+    public void destroy() {
+        mModel.set(RestoreTabsProperties.VISIBLE, false);
     }
 
     /** Returns an implementation the RestoreTabsPromoScreen.Delegate interface. */
@@ -47,18 +61,62 @@
         mModel.set(RestoreTabsProperties.VISIBLE, true);
     }
 
+    /** Dismiss the bottom sheet */
+    public void dismiss() {
+        mModel.set(RestoreTabsProperties.VISIBLE, false);
+
+        if (mListener != null) {
+            mListener.onDismissed();
+        }
+    }
+
+    /**
+     * Sets the device items and creates the corresponding models for the
+     * device item entries on the device profiles page.
+     * If there is a selected device profile prior to calling this method, the device
+     * with the same tag will remain selected. If no prior selection was made or this
+     * tag no longer exists, the first device is selected.
+     * @param sessions The list of ForeignSession to set as device profiles.
+     */
     public void setDeviceListItems(List<ForeignSession> sessions) {
         assert sessions != null && sessions.size() != 0;
 
         ForeignSession previousSelection = mModel.get(RestoreTabsProperties.SELECTED_DEVICE);
         ForeignSession newSelection = sessions.get(0);
 
+        // Populate all model entries.
+        ModelList sessionItems = mModel.get(RestoreTabsProperties.DEVICE_MODEL_LIST);
+        sessionItems.clear();
+        for (ForeignSession session : sessions) {
+            if (previousSelection != null && session.tag.equals(previousSelection.tag)) {
+                newSelection = session;
+            }
+            PropertyModel model = ForeignSessionItemProperties.create(
+                    /*session=*/session, /*isSelected=*/false, /*onClickListener=*/() -> {
+                        setSelectedDeviceItem(session);
+                        setCurrentScreen(RestoreTabsProperties.ScreenType.HOME_SCREEN);
+                    });
+            sessionItems.add(new ListItem(DetailItemType.DEVICE, model));
+        }
+
         setSelectedDeviceItem(newSelection);
     }
 
+    /**
+     * Sets the selected device profile and updates the IS_SELECTED entry in the models
+     * of the device item entries on the device profiles page.
+     * @param selectedSession The device that is to be selected.
+     */
     public void setSelectedDeviceItem(ForeignSession selectedSession) {
         assert selectedSession != null;
         mModel.set(RestoreTabsProperties.SELECTED_DEVICE, selectedSession);
+
+        ModelList allItems = mModel.get(RestoreTabsProperties.DEVICE_MODEL_LIST);
+        for (ListItem item : allItems) {
+            boolean isSelected = selectedSession.equals(
+                    item.model.get(ForeignSessionItemProperties.SESSION_PROFILE));
+            item.model.set(ForeignSessionItemProperties.IS_SELECTED, isSelected);
+        }
     }
 
     /**
@@ -66,5 +124,35 @@
      * @param screenType A {@link RestoreTabsProperties.ScreenType} that defines the screen to be
      *         shown.
      */
-    public void setCurrentScreen(int screenType) {}
+    public void setCurrentScreen(int screenType) {
+        if (screenType == RestoreTabsProperties.ScreenType.DEVICE_SCREEN) {
+            mModel.set(RestoreTabsProperties.DETAIL_SCREEN_MODEL_LIST,
+                    mModel.get(RestoreTabsProperties.DEVICE_MODEL_LIST));
+            mModel.set(RestoreTabsProperties.REVIEW_TABS_SCREEN_DELEGATE, null);
+        } else if (screenType == RestoreTabsProperties.ScreenType.REVIEW_TABS_SCREEN) {
+            mModel.set(RestoreTabsProperties.DETAIL_SCREEN_MODEL_LIST,
+                    mModel.get(RestoreTabsProperties.REVIEW_TABS_MODEL_LIST));
+            mModel.set(RestoreTabsProperties.REVIEW_TABS_SCREEN_DELEGATE,
+                    createReviewTabsScreenDelegate());
+        } else {
+            mModel.set(RestoreTabsProperties.DETAIL_SCREEN_MODEL_LIST, null);
+        }
+
+        mModel.set(RestoreTabsProperties.CURRENT_SCREEN, screenType);
+    }
+
+    /** Returns an implementation of the RestoreTabsDetailScreen.Delegate interface. */
+    private RestoreTabsDetailScreenCoordinator.Delegate createReviewTabsScreenDelegate() {
+        return new RestoreTabsDetailScreenCoordinator.Delegate() {
+            // If all tabs are selected this will present a deselect all option, otherwise it will
+            // present a select all option.
+            @Override
+            public void onChangeSelectionStateForAllTabs() {}
+
+            @Override
+            public void onSelectedTabsChosen() {
+                mModel.set(RestoreTabsProperties.VISIBLE, false);
+            };
+        };
+    }
 }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java
index 675a36e5..cf5d0f6 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java
@@ -7,8 +7,15 @@
 import static org.hamcrest.Matchers.instanceOf;
 
 import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.CURRENT_SCREEN;
+import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.DETAIL_SCREEN_BACK_CLICK_HANDLER;
+import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.DETAIL_SCREEN_MODEL_LIST;
+import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.DEVICE_MODEL_LIST;
 import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.HOME_SCREEN_DELEGATE;
+import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.REVIEW_TABS_MODEL_LIST;
+import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.REVIEW_TABS_SCREEN_DELEGATE;
 import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.SELECTED_DEVICE;
+import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.ScreenType.DEVICE_SCREEN;
+import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.ScreenType.REVIEW_TABS_SCREEN;
 import static org.chromium.chrome.browser.recent_tabs.RestoreTabsProperties.VISIBLE;
 
 import org.junit.After;
@@ -20,6 +27,7 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSession;
+import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsDetailScreenCoordinator;
 import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsPromoScreenCoordinator;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -35,7 +43,12 @@
 
     @Before
     public void setUp() {
-        mMediator.initialize(mModel);
+        mMediator.initialize(mModel, new RestoreTabsControllerFactory.ControllerListener() {
+            @Override
+            public void onDismissed() {
+                mMediator.destroy();
+            }
+        });
     }
 
     @After
@@ -44,12 +57,33 @@
     }
 
     @Test
-    public void testRestoreTabsMediator_createsValidDefaultModel() {
+    public void testRestoreTabsMediator_initCreatesValidDefaultModel() {
+        Assert.assertEquals(mModel.get(VISIBLE), false);
+        Assert.assertNotNull(mModel.get(HOME_SCREEN_DELEGATE));
+        Assert.assertThat(mModel.get(HOME_SCREEN_DELEGATE),
+                instanceOf(RestoreTabsPromoScreenCoordinator.Delegate.class));
+        Assert.assertNotNull(mModel.get(DETAIL_SCREEN_BACK_CLICK_HANDLER));
+        Assert.assertEquals(
+                mModel.get(CURRENT_SCREEN), RestoreTabsProperties.ScreenType.HOME_SCREEN);
+    }
+
+    @Test
+    public void testRestoreTabsMediator_onDismissed() {
         ForeignSession session = new ForeignSession("tag", "John's iPhone 6", 32L);
         List<ForeignSession> testSessions = new ArrayList<>();
         testSessions.add(session);
 
+        mMediator.showOptions(testSessions);
+        Assert.assertEquals(mModel.get(VISIBLE), true);
+        mMediator.dismiss();
         Assert.assertEquals(mModel.get(VISIBLE), false);
+    }
+
+    @Test
+    public void testRestoreTabsMediator_showOptionsUpdatesModel() {
+        ForeignSession session = new ForeignSession("tag", "John's iPhone 6", 32L);
+        List<ForeignSession> testSessions = new ArrayList<>();
+        testSessions.add(session);
 
         mMediator.showOptions(testSessions);
 
@@ -57,9 +91,63 @@
         Assert.assertEquals(
                 mModel.get(CURRENT_SCREEN), RestoreTabsProperties.ScreenType.HOME_SCREEN);
         Assert.assertEquals(mModel.get(SELECTED_DEVICE), testSessions.get(0));
+    }
 
-        Assert.assertNotNull(mModel.get(HOME_SCREEN_DELEGATE));
-        Assert.assertThat(mModel.get(HOME_SCREEN_DELEGATE),
-                instanceOf(RestoreTabsPromoScreenCoordinator.Delegate.class));
+    @Test
+    public void testRestoreTabsMediator_setDeviceListItemsNoSelection() {
+        ForeignSession session1 = new ForeignSession("tag1", "John's iPhone 6", 32L);
+        ForeignSession session2 = new ForeignSession("tag2", "John's iPhone 7", 33L);
+        List<ForeignSession> testSessions = new ArrayList<>();
+        testSessions.add(session1);
+        testSessions.add(session2);
+
+        mMediator.setDeviceListItems(testSessions);
+
+        Assert.assertEquals(mModel.get(SELECTED_DEVICE), testSessions.get(0));
+    }
+
+    @Test
+    public void testRestoreTabsMediator_setDeviceListItemsSelection() {
+        ForeignSession session1 = new ForeignSession("tag1", "John's iPhone 6", 32L);
+        ForeignSession session2 = new ForeignSession("tag2", "John's iPhone 7", 33L);
+        List<ForeignSession> testSessions = new ArrayList<>();
+        testSessions.add(session1);
+        testSessions.add(session2);
+
+        mModel.set(SELECTED_DEVICE, session2);
+
+        mMediator.setDeviceListItems(testSessions);
+
+        Assert.assertEquals(mModel.get(SELECTED_DEVICE), testSessions.get(1));
+    }
+
+    @Test
+    public void testRestoreTabsMediator_setSelectedDeviceItem() {
+        ForeignSession session = new ForeignSession("tag", "John's iPhone 6", 32L);
+        mMediator.setSelectedDeviceItem(session);
+
+        Assert.assertEquals(mModel.get(SELECTED_DEVICE), session);
+    }
+
+    @Test
+    public void testRestoreTabsMediator_setCurrentScreenDevices() {
+        mMediator.setCurrentScreen(DEVICE_SCREEN);
+
+        Assert.assertEquals(mModel.get(DETAIL_SCREEN_MODEL_LIST), mModel.get(DEVICE_MODEL_LIST));
+        Assert.assertEquals(
+                mModel.get(CURRENT_SCREEN), RestoreTabsProperties.ScreenType.DEVICE_SCREEN);
+    }
+
+    @Test
+    public void testRestoreTabsMediator_setCurrentScreenReviewTabs() {
+        mMediator.setCurrentScreen(REVIEW_TABS_SCREEN);
+
+        Assert.assertEquals(
+                mModel.get(DETAIL_SCREEN_MODEL_LIST), mModel.get(REVIEW_TABS_MODEL_LIST));
+        Assert.assertNotNull(mModel.get(REVIEW_TABS_SCREEN_DELEGATE));
+        Assert.assertThat(mModel.get(REVIEW_TABS_SCREEN_DELEGATE),
+                instanceOf(RestoreTabsDetailScreenCoordinator.Delegate.class));
+        Assert.assertEquals(
+                mModel.get(CURRENT_SCREEN), RestoreTabsProperties.ScreenType.REVIEW_TABS_SCREEN);
     }
 }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsProperties.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsProperties.java
index ada2b37..f1709ff 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsProperties.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsProperties.java
@@ -7,9 +7,12 @@
 import androidx.annotation.IntDef;
 
 import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSession;
+import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsDetailScreenCoordinator;
 import org.chromium.chrome.browser.recent_tabs.ui.RestoreTabsPromoScreenCoordinator;
+import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
@@ -32,6 +35,19 @@
         int REVIEW_TABS_SCREEN = 2;
     }
 
+    /**
+     * The different item types in the RecyclerView on the detail bottom sheet.
+     */
+    @IntDef({DetailItemType.DEVICE, DetailItemType.TAB})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DetailItemType {
+        /** A device entry. */
+        int DEVICE = 1;
+
+        /** A tab entry. */
+        int TAB = 2;
+    }
+
     /** Property that indicates the bottom sheet visibility. */
     public static final WritableBooleanPropertyKey VISIBLE = new WritableBooleanPropertyKey();
 
@@ -42,18 +58,48 @@
     public static final WritableObjectPropertyKey<ForeignSession> SELECTED_DEVICE =
             new WritableObjectPropertyKey<>();
 
+    /** The models corresponding to all user synced devices. */
+    public static final ReadableObjectPropertyKey<ModelList> DEVICE_MODEL_LIST =
+            new ReadableObjectPropertyKey();
+
+    /** The models corresponding to all synced tabs from the selected device. */
+    public static final ReadableObjectPropertyKey<ModelList> REVIEW_TABS_MODEL_LIST =
+            new ReadableObjectPropertyKey();
+
     /** The delegate that handles actions on the home screen. */
     public static final WritableObjectPropertyKey<RestoreTabsPromoScreenCoordinator.Delegate>
             HOME_SCREEN_DELEGATE = new WritableObjectPropertyKey<>();
 
+    /** The string id of the title shown on the detail screen. */
+    public static final WritableIntPropertyKey DETAIL_SCREEN_TITLE = new WritableIntPropertyKey();
+
+    /** The handler for the back icon on the detail screens (device select, review tabs). */
+    public static final WritableObjectPropertyKey<Runnable> DETAIL_SCREEN_BACK_CLICK_HANDLER =
+            new WritableObjectPropertyKey<>();
+
+    /** The delegate that handles actions on the review tabs screen. */
+    public static final WritableObjectPropertyKey<RestoreTabsDetailScreenCoordinator.Delegate>
+            REVIEW_TABS_SCREEN_DELEGATE = new WritableObjectPropertyKey<>();
+
+    /**
+     * The models that are displayed on the detail screen. This will either point to
+     * DEVICE_MODEL_LIST or REVIEW_TABS_MODEL_LIST.
+     */
+    public static final WritableObjectPropertyKey<ModelList> DETAIL_SCREEN_MODEL_LIST =
+            new WritableObjectPropertyKey<>();
+
     public static PropertyModel createDefaultModel() {
         return new PropertyModel.Builder(ALL_KEYS)
                 .with(VISIBLE, false)
                 .with(CURRENT_SCREEN, ScreenType.HOME_SCREEN)
+                .with(DEVICE_MODEL_LIST, new ModelList())
+                .with(REVIEW_TABS_MODEL_LIST, new ModelList())
                 .build();
     }
 
     /** All keys used for the restore tabs promo bottom sheet. */
-    static final PropertyKey[] ALL_KEYS =
-            new PropertyKey[] {VISIBLE, CURRENT_SCREEN, SELECTED_DEVICE, HOME_SCREEN_DELEGATE};
+    static final PropertyKey[] ALL_KEYS = new PropertyKey[] {VISIBLE, CURRENT_SCREEN,
+            SELECTED_DEVICE, DEVICE_MODEL_LIST, REVIEW_TABS_MODEL_LIST, HOME_SCREEN_DELEGATE,
+            DETAIL_SCREEN_TITLE, DETAIL_SCREEN_BACK_CLICK_HANDLER, REVIEW_TABS_SCREEN_DELEGATE,
+            DETAIL_SCREEN_MODEL_LIST};
 }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/ForeignSessionItemProperties.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/ForeignSessionItemProperties.java
new file mode 100644
index 0000000..8c1c96f
--- /dev/null
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/ForeignSessionItemProperties.java
@@ -0,0 +1,44 @@
+// Copyright 2023 The Chromium Authors
+// 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.recent_tabs.ui;
+
+import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSession;
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey;
+import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
+
+/**
+ * Model for a ForeignSession entry in the device detail screen sheet.
+ */
+public class ForeignSessionItemProperties {
+    /** The device represented by this entry. */
+    public static final ReadableObjectPropertyKey<ForeignSession> SESSION_PROFILE =
+            new ReadableObjectPropertyKey<>();
+
+    /**
+     * An indicator of whether this device is the currently selected one. This key is kept
+     * in sync by the RestoreTabsMediator.
+     */
+    public static final WritableBooleanPropertyKey IS_SELECTED = new WritableBooleanPropertyKey();
+
+    /**
+     * The function to run when this session item is selected by the user.
+     */
+    public static final ReadableObjectPropertyKey<Runnable> ON_CLICK_LISTENER =
+            new ReadableObjectPropertyKey<>();
+
+    /** Creates a model for a ForeignSession device. */
+    public static PropertyModel create(
+            ForeignSession session, boolean isSelected, Runnable onClickListener) {
+        return new PropertyModel.Builder(ALL_KEYS)
+                .with(SESSION_PROFILE, session)
+                .with(IS_SELECTED, isSelected)
+                .with(ON_CLICK_LISTENER, onClickListener)
+                .build();
+    }
+
+    public static final PropertyKey[] ALL_KEYS = {SESSION_PROFILE, IS_SELECTED, ON_CLICK_LISTENER};
+}
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/ForeignSessionItemPropertiesUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/ForeignSessionItemPropertiesUnitTest.java
new file mode 100644
index 0000000..4eca7294
--- /dev/null
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/ForeignSessionItemPropertiesUnitTest.java
@@ -0,0 +1,53 @@
+// Copyright 2023 The Chromium Authors
+// 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.recent_tabs.ui;
+
+import static org.chromium.chrome.browser.recent_tabs.ui.ForeignSessionItemProperties.IS_SELECTED;
+import static org.chromium.chrome.browser.recent_tabs.ui.ForeignSessionItemProperties.ON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.recent_tabs.ui.ForeignSessionItemProperties.SESSION_PROFILE;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.recent_tabs.ForeignSessionHelper.ForeignSession;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/** Tests for the ForeignSessionItem model. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class ForeignSessionItemPropertiesUnitTest {
+    private ForeignSession mSession;
+    private PropertyModel mModel;
+
+    @Before
+    public void setUp() {
+        mSession = new ForeignSession("tag", "John's iPhone 6", 32L);
+        mModel = ForeignSessionItemProperties.create(
+                /*device=*/mSession, /*isSelected=*/false, /*onClickListener=*/() -> {});
+    }
+
+    @After
+    public void tearDown() {
+        mModel = null;
+    }
+
+    @Test
+    public void testForeignSessionItemProperties_initCreatesValidDefaultModel() {
+        Assert.assertEquals(mModel.get(SESSION_PROFILE), mSession);
+        Assert.assertEquals(mModel.get(IS_SELECTED), false);
+        Assert.assertNotNull(mModel.get(ON_CLICK_LISTENER));
+    }
+
+    @Test
+    public void testForeignSessionItemProperties_setSelectedDeviceItem() {
+        mModel.set(IS_SELECTED, true);
+        Assert.assertEquals(mModel.get(IS_SELECTED), true);
+    }
+}
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsDetailScreenCoordinator.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsDetailScreenCoordinator.java
new file mode 100644
index 0000000..a62a73f4
--- /dev/null
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsDetailScreenCoordinator.java
@@ -0,0 +1,18 @@
+// Copyright 2023 The Chromium Authors
+// 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.recent_tabs.ui;
+
+/**
+ * Coordinator for the detail screens (device select, review tabs) of the Restore Tabs on FRE promo.
+ */
+public class RestoreTabsDetailScreenCoordinator {
+    /** The delegate of the class. */
+    public interface Delegate {
+        /** The user clicked on the select/deselect all tabs item. */
+        void onChangeSelectionStateForAllTabs();
+        /** The user clicked on restoring all selected tabs. */
+        void onSelectedTabsChosen();
+    }
+}
diff --git a/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.ts b/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.ts
index b832f85..13e7e8f 100644
--- a/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.ts
+++ b/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.ts
@@ -20,7 +20,7 @@
    * The local file tasks that the user could use to open the file. There are
    * separate buttons for the Drive and Office PWA apps.
    */
-  tasks: DialogTask[] = [];
+  localTasks: DialogTask[] = [];
   /**
    * References to the HTMLElement used to display the tasks that the user can
    * select.
@@ -61,9 +61,9 @@
     try {
       const dialogArgs = await this.proxy.handler.getDialogArgs();
       assert(dialogArgs.args);
-      assert(dialogArgs.args.tasks);
+      assert(dialogArgs.args.localTasks);
       // Adjust the dialog's size if there are no local tasks to display.
-      if (dialogArgs.args.tasks.length == 0) {
+      if (dialogArgs.args.localTasks.length == 0) {
         this.style.height = '311px';
       }
 
@@ -89,7 +89,7 @@
       officeCard.id = 'onedrive';
       this.addCloudProviderCard(officeCard);
 
-      const localTasks = dialogArgs.args.tasks;
+      const localTasks = dialogArgs.args.localTasks;
       if (localTasks.length == 0) {
         return;
       }
@@ -106,15 +106,14 @@
         localHandlerCard.setParameters(task.position, task.title);
         localHandlerCard.setIconUrl(task.iconUrl);
         localHandlerCard.id = this.toStringId(task.position);
-        if (i == dialogArgs.args.tasks.length - 1) {
+        if (i == dialogArgs.args.localTasks.length - 1) {
           // Round bottom for last card.
           localHandlerCard.$('#container')!.classList.add('round-bottom');
         }
         this.addLocalHandlerCard(localHandlerCard);
 
-        // Set `this.tasks` at end of `initDynamicContent` as an indication of
-        // completion.
-        this.tasks = dialogArgs.args.tasks;
+        // Set local tasks to indicate completion (used in tests).
+        this.localTasks = dialogArgs.args.localTasks;
       }
     } catch (e) {
       // TODO(b:243095484) Define expected behavior.
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js
index 270b3b2..28bdf47 100644
--- a/chrome/browser/resources/chromeos/login/oobe.js
+++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -124,43 +124,40 @@
 /**
  * ----------- OOBE Execution Begins -----------
  */
-(function() {
-// Ensure that there is a global error listener when OOBE starts.
-// This error listener is added in the main HTML document.
-assert(window.OobeErrorStore, 'OobeErrorStore not present on global object!');
+function startOobe() {
+  // Ensure that there is a global error listener when OOBE starts.
+  // This error listener is added in the main HTML document.
+  assert(window.OobeErrorStore, 'OobeErrorStore not present on global object!');
 
-// Update localized strings at the document level.
-Oobe.updateDocumentLocalizedStrings();
+  // Update localized strings at the document level.
+  Oobe.updateDocumentLocalizedStrings();
 
-prepareGlobalValues(window);
+  prepareGlobalValues(window);
 
-// Add common screens to the document.
-addScreensToMainContainer(commonScreensList);
-traceExecution(TraceEvent.COMMON_SCREENS_ADDED);
+  // Add common screens to the document.
+  addScreensToMainContainer(commonScreensList);
+  traceExecution(TraceEvent.COMMON_SCREENS_ADDED);
 
-// Add OOBE or LOGIN screens to the document.
-const isOobeFlow = loadTimeData.getBoolean('isOobeFlow');
-if (isOobeFlow) {
-  addScreensToMainContainer(oobeScreensList);
-  traceExecution(TraceEvent.OOBE_SCREENS_ADDED);
-} else {
-  addScreensToMainContainer(loginScreensList);
-  traceExecution(TraceEvent.LOGIN_SCREENS_ADDED);
+  // Add OOBE or LOGIN screens to the document.
+  const isOobeFlow = loadTimeData.getBoolean('isOobeFlow');
+  addScreensToMainContainer(isOobeFlow ? oobeScreensList : loginScreensList);
+  traceExecution(TraceEvent.REMAINING_SCREENS_ADDED);
+
+  // The default is to have the class 'oobe-display' in <body> for the OOBE
+  // flow. For the 'Add Person' flow, we remove it.
+  if (!isOobeFlow) {
+    document.body.classList.remove('oobe-display');
+  } else {
+    assert(
+        document.body.classList.contains('oobe-display'),
+        'The body of the document must contain oobe-display as a class for the OOBE flow!');
+  }
+
+  if (document.readyState === 'loading') {
+    document.addEventListener('DOMContentLoaded', initializeOobe);
+  } else {
+    initializeOobe();
+  }
 }
 
-// The default is to have the class 'oobe-display' in <body> for the OOBE
-// flow. For the 'Add Person' flow, we remove it.
-if (!isOobeFlow) {
-  document.body.classList.remove('oobe-display');
-} else {
-  assert(
-      document.body.classList.contains('oobe-display'),
-      'The body of the document must contain oobe-display as a class for the OOBE flow!');
-}
-
-if (document.readyState === 'loading') {
-  document.addEventListener('DOMContentLoaded', initializeOobe);
-} else {
-  initializeOobe();
-}
-})();
+startOobe();
diff --git a/chrome/browser/resources/chromeos/login/oobe_trace.js b/chrome/browser/resources/chromeos/login/oobe_trace.js
index 988abcfb..aa6f113 100644
--- a/chrome/browser/resources/chromeos/login/oobe_trace.js
+++ b/chrome/browser/resources/chromeos/login/oobe_trace.js
@@ -18,13 +18,15 @@
  */
 
 import {assert} from '//resources/ash/common/assert.js';
+
+import {loadTimeData} from './i18n_setup.js';
+
 assert(window.oobeInitializationBeginTimestamp);
 
 export const TraceEvent = {
   FIRST_LINE_AFTER_IMPORTS: 'FIRST_LINE_AFTER_IMPORTS',
   COMMON_SCREENS_ADDED: 'COMMON_SCREENS_ADDED',
-  OOBE_SCREENS_ADDED: 'OOBE_SCREENS_ADDED',
-  LOGIN_SCREENS_ADDED: 'LOGIN_SCREENS_ADDED',
+  REMAINING_SCREENS_ADDED: 'REMAINING_SCREENS_ADDED',
   DOM_CONTENT_LOADED: 'DOM_CONTENT_LOADED',
   OOBE_INITIALIZED: 'OOBE_INITIALIZED',
   FIRST_SCREEN_SHOWN: 'FIRST_SCREEN_SHOWN',
@@ -37,14 +39,12 @@
 const eventLogs = [];
 window.oobeTraceLogs = eventLogs;
 
-
-function createEventEntry(traceEvent) {
-  assert(traceEvent in TraceEvent);
-  const currentTimestamp = new Date();
-  const delta = currentTimestamp - window.oobeInitializationBeginTimestamp;
-  const eventEntry = {};
-  eventEntry[traceEvent] = delta;
-  return eventEntry;
+class EventEntry {
+  constructor(traceEventName) {
+    assert(traceEventName in TraceEvent);
+    this.name = traceEventName;
+    this.delta = new Date() - window.oobeInitializationBeginTimestamp;
+  }
 }
 
 let firstScreenShownEventLogged = false;
@@ -52,8 +52,7 @@
 let firstOobeLottieEventLogged = false;
 
 export function traceExecution(traceEvent) {
-  const eventEntry = createEventEntry(traceEvent);
-  eventLogs.push(eventEntry);
+  eventLogs.push(new EventEntry(traceEvent));
 }
 
 export function traceFirstScreenShown() {
@@ -90,13 +89,44 @@
 let scheduledLastOobeLottieTrace = null;
 function maybeTraceLastOobeLottieInitialization() {
   // Amount of time to wait until logging the last OOBE Lottie Initialization.
-  const LAST_OOBE_LOTTIE_TIMEOUT_MSECS = 5 * 1000;
+  const LAST_OOBE_LOTTIE_TIMEOUT_MSECS = 3 * 1000;
 
   if (scheduledLastOobeLottieTrace) {
     clearTimeout(scheduledLastOobeLottieTrace);
   }
 
-  const entry = createEventEntry(TraceEvent.LAST_OOBE_LOTTIE_INITIALIZED);
-  scheduledLastOobeLottieTrace =
-    setTimeout(() => eventLogs.push(entry), LAST_OOBE_LOTTIE_TIMEOUT_MSECS);
+  const entry = new EventEntry(TraceEvent.LAST_OOBE_LOTTIE_INITIALIZED);
+  scheduledLastOobeLottieTrace = setTimeout(() => {
+    eventLogs.push(entry);
+    maybePrintTraces();
+  }, LAST_OOBE_LOTTIE_TIMEOUT_MSECS);
+}
+
+// Maybe output the timings to the console to be parsed when the command line
+// switch 'oobe-print-frontend-timings' is present. More details can be found in
+// go/oobe-frontend-trace-timings
+function maybePrintTraces() {
+  if (!loadTimeData.getBoolean('printFrontendTimings')) {
+    return;
+  }
+
+  const EventPrintOrder = [
+    TraceEvent.FIRST_LINE_AFTER_IMPORTS,
+    TraceEvent.COMMON_SCREENS_ADDED,
+    TraceEvent.REMAINING_SCREENS_ADDED,
+    TraceEvent.DOM_CONTENT_LOADED,
+    TraceEvent.OOBE_INITIALIZED,
+    TraceEvent.FIRST_SCREEN_SHOWN,
+    TraceEvent.FIRST_OOBE_LOTTIE_INITIALIZED,
+    TraceEvent.LAST_OOBE_LOTTIE_INITIALIZED,
+    TraceEvent.WELCOME_ANIMATION_PLAYING,
+  ];
+
+  let output = 'OOBE_TRACE_BEGIN_';
+  for (const eventName of EventPrintOrder) {
+    const matchingEvent = eventLogs.find(e => e.name === eventName);
+    output += matchingEvent ? matchingEvent.delta + ';' : 'NaN;';
+  }
+  output += '_OOBE_TRACE_END';
+  console.error(output);
 }
diff --git a/chrome/browser/resources/intro/intro.html b/chrome/browser/resources/intro/intro.html
index ff5853c1..032ba45 100644
--- a/chrome/browser/resources/intro/intro.html
+++ b/chrome/browser/resources/intro/intro.html
@@ -1,5 +1,6 @@
 <!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<html dir="$i18n{textdirection}" lang="$i18n{language}"
+    $i18n{chromeRefresh2023Attribute}>
   <head>
     <meta charset="utf-8">
     <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
diff --git a/chrome/browser/resources/password_manager/dialogs/add_password_dialog.html b/chrome/browser/resources/password_manager/dialogs/add_password_dialog.html
index 38ee1f71..f97170c 100644
--- a/chrome/browser/resources/password_manager/dialogs/add_password_dialog.html
+++ b/chrome/browser/resources/password_manager/dialogs/add_password_dialog.html
@@ -86,8 +86,9 @@
       $i18n{viewExistingPassword}
     </a>
     <cr-input id="passwordInput" label="$i18n{passwordLabel}"
-         type="[[getPasswordInputType(isPasswordVisible)]]"
-         value="{{password_}}" required>
+        type="[[getPasswordInputType(isPasswordVisible)]]"
+        value="{{password_}}" invalid="[[isPasswordInvalid_]]"
+        on-blur="onPasswordInput_" on-input="onPasswordInput_" required>
       <cr-icon-button id="showPasswordButton" slot="inline-suffix"
           class$="[[getShowHideButtonIconClass(isPasswordVisible)]]"
           title="[[getShowHideButtonLabel(isPasswordVisible)]]"
diff --git a/chrome/browser/resources/password_manager/dialogs/add_password_dialog.ts b/chrome/browser/resources/password_manager/dialogs/add_password_dialog.ts
index 82d2d87..658dfd42 100644
--- a/chrome/browser/resources/password_manager/dialogs/add_password_dialog.ts
+++ b/chrome/browser/resources/password_manager/dialogs/add_password_dialog.ts
@@ -83,15 +83,25 @@
 
   static get properties() {
     return {
-      website_: String,
-      username_: String,
+      website_: {
+        type: String,
+        value: '',
+      },
+
+      username_: {
+        type: String,
+        value: '',
+      },
 
       password_: {
         type: String,
         value: '',
       },
 
-      note_: String,
+      note_: {
+        type: String,
+        value: '',
+      },
 
       urlCollection_: Object,
 
@@ -111,6 +121,11 @@
             'usernamesBySignonRealm_)',
       },
 
+      isPasswordInvalid_: {
+        type: Boolean,
+        value: false,
+      },
+
       canAddPassword_: {
         type: Boolean,
         computed: 'computeCanAddPassword_(websiteErrorMessage_, username_, ' +
@@ -144,6 +159,7 @@
   private usernamesBySignonRealm_: Map<string, Set<string>>;
   private websiteErrorMessage_: string|null;
   private usernameErrorMessage_: string|null;
+  private isPasswordInvalid_: boolean;
   private urlCollection_: chrome.passwordsPrivate.UrlCollection|null;
   private readonly storeOptionAccountValue_: string;
   private readonly storeOptionDeviceValue_: string;
@@ -201,7 +217,9 @@
   }
 
   private onWebsiteInputBlur_() {
-    if (!this.websiteErrorMessage_ && !this.website_.includes('.')) {
+    if (this.website_.length === 0) {
+      this.websiteErrorMessage_ = this.i18n('notValidWebsite');
+    } else if (!this.websiteErrorMessage_ && !this.website_.includes('.')) {
       this.websiteErrorMessage_ =
           this.i18n('missingTLD', `${this.website_}.com`);
     }
@@ -227,6 +245,10 @@
     return !!this.usernameErrorMessage_;
   }
 
+  private onPasswordInput_() {
+    this.isPasswordInvalid_ = this.password_.length === 0;
+  }
+
   private isNoteInputInvalid_(): boolean {
     return this.note_.length >= PASSWORD_NOTE_MAX_CHARACTER_COUNT;
   }
@@ -248,7 +270,7 @@
   }
 
   private computeCanAddPassword_(): boolean {
-    if (this.isWebsiteInputInvalid_()) {
+    if (this.isWebsiteInputInvalid_() || this.website_.length === 0) {
       return false;
     }
     if (this.doesUsernameExistAlready_()) {
diff --git a/chrome/browser/resources/password_manager/password_details_card.html b/chrome/browser/resources/password_manager/password_details_card.html
index df77e3e9..32022503 100644
--- a/chrome/browser/resources/password_manager/password_details_card.html
+++ b/chrome/browser/resources/password_manager/password_details_card.html
@@ -94,8 +94,9 @@
         </cr-input>
       </div>
       <div class="column-container">
-        <!-- TODO(crbug.com/1350947): Support displaying apps. -->
-        <div class="cr-form-field-label">$i18n{sitesLabel}</div>
+        <div id="domainLabel" class="cr-form-field-label">
+          [[getDomainLabel_(password)]]
+        </div>
         <template id="links" is="dom-repeat"
             items="[[password.affiliatedDomains]]">
           <div class="elide-left">
diff --git a/chrome/browser/resources/password_manager/password_details_card.ts b/chrome/browser/resources/password_manager/password_details_card.ts
index 29b2335..82e4e6b 100644
--- a/chrome/browser/resources/password_manager/password_details_card.ts
+++ b/chrome/browser/resources/password_manager/password_details_card.ts
@@ -37,6 +37,7 @@
     copyPasswordButton: CrIconButtonElement,
     copyUsernameButton: CrIconButtonElement,
     deleteButton: CrButtonElement,
+    domainLabel: HTMLElement,
     editButton: CrButtonElement,
     noteValue: HTMLElement,
     passwordValue: CrInputElement,
@@ -175,6 +176,17 @@
   private extendAuthValidity_() {
     PasswordManagerImpl.getInstance().extendAuthValidity();
   }
+
+  private getDomainLabel_(): string {
+    const hasApps = this.password.affiliatedDomains?.some(
+        domain => domain.signonRealm.startsWith('android://'));
+    const hasSites = this.password.affiliatedDomains?.some(
+        domain => !domain.signonRealm.startsWith('android://'));
+    if (hasApps && hasSites) {
+      return this.i18n('sitesAndAppsLabel');
+    }
+    return hasApps ? this.i18n('appsLabel') : this.i18n('sitesLabel');
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn
index cf90c2f..cb228ef 100644
--- a/chrome/browser/resources/pdf/BUILD.gn
+++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -99,6 +99,8 @@
 
   icons_html_files = [ "elements/icons.html" ]
 
+  html_to_wrapper_scheme = "chrome"
+
   # TypeScript Compiler parameters
   ts_composite = true
   ts_definitions = [
diff --git a/chrome/browser/resources/pdf/open_pdf_params_parser.ts b/chrome/browser/resources/pdf/open_pdf_params_parser.ts
index 95d6213a9..555e454 100644
--- a/chrome/browser/resources/pdf/open_pdf_params_parser.ts
+++ b/chrome/browser/resources/pdf/open_pdf_params_parser.ts
@@ -84,11 +84,12 @@
   /**
    * Parse view parameter of open PDF parameters. The PDF should be opened at
    * the specified fitting type mode and position.
+   * @param paramValue Params to parse.
    * @return Map with view parameters (view and viewPosition).
    */
-  private parseViewParam_(paramValue: string): OpenPdfParams {
+  private async parseViewParam_(paramValue: string): Promise<OpenPdfParams> {
     const viewModeComponents = paramValue.toLowerCase().split(',');
-    if (viewModeComponents.length < 1) {
+    if (viewModeComponents.length === 0) {
       return {};
     }
 
@@ -106,7 +107,7 @@
       acceptsPositionParam = true;
     }
 
-    if (!acceptsPositionParam || viewModeComponents.length < 2) {
+    if (!acceptsPositionParam || viewModeComponents.length === 1) {
       return params;
     }
 
@@ -120,9 +121,11 @@
 
   /**
    * Parse view parameters which come from nameddest.
+   * @param paramValue Params to parse.
    * @return Map with view parameters.
    */
-  private parseNameddestViewParam_(paramValue: string): OpenPdfParams {
+  private async parseNameddestViewParam_(paramValue: string):
+      Promise<OpenPdfParams> {
     const viewModeComponents = paramValue.toLowerCase().split(',');
     const viewMode = viewModeComponents[0];
     const params: OpenPdfParams = {};
@@ -250,7 +253,7 @@
     }
 
     if (urlParams.has('view')) {
-      Object.assign(params, this.parseViewParam_(urlParams.get('view')!));
+      Object.assign(params, await this.parseViewParam_(urlParams.get('view')!));
     }
 
     if (urlParams.has('zoom')) {
@@ -267,12 +270,11 @@
 
       if (data.namedDestinationView) {
         Object.assign(
-            params, this.parseNameddestViewParam_(data.namedDestinationView));
+            params,
+            await this.parseNameddestViewParam_(data.namedDestinationView));
       }
-
       return params;
     }
-
-    return Promise.resolve(params);
+    return params;
   }
 }
diff --git a/chrome/browser/resources/settings/chromeos/lazy_load.ts b/chrome/browser/resources/settings/chromeos/lazy_load.ts
index f427534..46013ee9 100644
--- a/chrome/browser/resources/settings/chromeos/lazy_load.ts
+++ b/chrome/browser/resources/settings/chromeos/lazy_load.ts
@@ -70,6 +70,7 @@
 import './os_a11y_page/switch_access_subpage.js';
 import './os_a11y_page/tts_subpage.js';
 import './os_files_page/google_drive_subpage.js';
+import './os_files_page/google_drive_disconnect_drive_dialog.js';
 import './os_files_page/office_page.js';
 import './os_languages_page/input_method_options_page.js';
 import './os_languages_page/input_page.js';
@@ -108,6 +109,7 @@
 export {SettingsAudioAndCaptionsPageElement} from './os_a11y_page/audio_and_captions_page.js';
 export {SettingsTextToSpeechPageElement} from './os_a11y_page/text_to_speech_page.js';
 export {SettingsTtsSubpageElement} from './os_a11y_page/tts_subpage.js';
+export {SettingsGoogleDriveSubpageElement} from './os_files_page/google_drive_subpage.js';
 export {SettingsOfficePageElement} from './os_files_page/office_page.js';
 export {LanguagesBrowserProxyImpl} from './os_languages_page/languages_browser_proxy.js';
 export {InputsShortcutReminderState, LanguagesMetricsProxyImpl, LanguagesPageInteraction} from './os_languages_page/languages_metrics_proxy.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.ts b/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.ts
index 03b239d..652ebfad 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.ts
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.ts
@@ -43,9 +43,15 @@
   size?: string;
 }
 
+/**
+ * Information related to device end of life. These values will always be
+ * populated by the C++ handler.
+ */
 interface EndOfLifeInfo {
-  hasEndOfLife?: boolean;
-  aboutPageEndOfLifeMessage?: string;
+  hasEndOfLife: boolean;
+  aboutPageEndOfLifeMessage: string;
+  shouldShowEndOfLifeIncentive: boolean;
+  shouldShowOfferText: boolean;
 }
 
 export interface TpmFirmwareUpdateStatusChangedEvent {
@@ -203,6 +209,11 @@
   getEndOfLifeInfo(): Promise<EndOfLifeInfo>;
 
   /**
+   * Called when the end of life incentive button is clicked.
+   */
+  endOfLifeIncentiveButtonClicked(): void;
+
+  /**
    * Request TPM firmware update status from the browser. It results in one or
    * more 'tpm-firmware-update-status-changed' WebUI events.
    */
@@ -305,6 +316,10 @@
     return sendWithPromise('getEndOfLifeInfo');
   }
 
+  endOfLifeIncentiveButtonClicked(): void {
+    chrome.send('openEndOfLifeIncentive');
+  }
+
   checkInternetConnection(): Promise<boolean> {
     return sendWithPromise('checkInternetConnection');
   }
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/eol_offer_section.html b/chrome/browser/resources/settings/chromeos/os_about_page/eol_offer_section.html
new file mode 100644
index 0000000..2eb5cbb
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/eol_offer_section.html
@@ -0,0 +1,49 @@
+<style>
+  :host {
+    background-color: var(--cr-card-background-color);
+    border-radius: 8px;
+    box-shadow: var(--cr-card-shadow);
+    display: flex;
+    padding: 16px;
+  }
+
+  .image-container {
+    background-color: var(--cros-illustration-color-1-shade-2);
+    border-radius: 50%;
+    display: inline-block;
+    height: 40px;
+    margin-inline-end: 16px;
+    width: 40px;
+  }
+
+  .inner-image {
+    --iron-icon-fill-color: var(--cros-icon-color-prominent);
+    padding: 8px;
+  }
+
+  .side-content {
+    flex: 1;
+  }
+
+  .eol-offer-title {
+    font-weight: 500;
+    margin-bottom: 8px;
+  }
+
+  .eol-offer-text {
+    margin-bottom: 8px;
+  }
+</style>
+<div class="image-container">
+  <iron-icon class="inner-image" icon="os-settings:end-of-life-offer">
+  </iron-icon>
+</div>
+<div class="side-content">
+  <div class="eol-offer-title">[[getEolTitleText_(shouldShowOfferText)]]</div>
+  <div class="eol-offer-text">[[getEolMessageText_(shouldShowOfferText)]]</div>
+  <cr-button id="eolIncentiveButton"
+      class="action-button"
+      on-click="onIncentiveButtonClick_">
+    [[getEolButtonText_(shouldShowOfferText)]]
+  </cr-button>
+</div>
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/eol_offer_section.ts b/chrome/browser/resources/settings/chromeos/os_about_page/eol_offer_section.ts
new file mode 100644
index 0000000..84db61c
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/eol_offer_section.ts
@@ -0,0 +1,68 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview 'eol-offer-section' contains information and a link for an
+ * offer related to the device's end of life.
+ */
+
+import '../os_settings_icons.html.js';
+import 'chrome://resources/cr_elements/cr_button/cr_button.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
+
+import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {AboutPageBrowserProxyImpl} from './about_page_browser_proxy.js';
+import {getTemplate} from './eol_offer_section.html.js';
+
+class EolOfferSection extends PolymerElement {
+  static get is() {
+    return 'eol-offer-section' as const;
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      shouldShowOfferText: {
+        type: Boolean,
+        value: false,
+      },
+    };
+  }
+
+  shouldShowOfferText: boolean;
+
+  private onIncentiveButtonClick_() {
+    AboutPageBrowserProxyImpl.getInstance().endOfLifeIncentiveButtonClicked();
+  }
+
+  private getEolTitleText_(): string {
+    return loadTimeData.getString(
+        this.shouldShowOfferText ? 'eolIncentiveOfferTitle' :
+                                   'eolIncentiveNoOfferTitle');
+  }
+
+  private getEolMessageText_(): string {
+    return loadTimeData.getString(
+        this.shouldShowOfferText ? 'eolIncentiveOfferMessage' :
+                                   'eolIncentiveNoOfferMessage');
+  }
+
+  private getEolButtonText_(): string {
+    return loadTimeData.getString(
+        this.shouldShowOfferText ? 'eolIncentiveButtonOfferText' : 'learnMore');
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    [EolOfferSection.is]: EolOfferSection;
+  }
+}
+
+customElements.define(EolOfferSection.is, EolOfferSection);
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
index c6d766f..3c37f85 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
@@ -71,6 +71,10 @@
     min-height: unset;
     padding-bottom: 10px;
   }
+
+  eol-offer-section {
+    margin: 6px 3px 16px 3px;
+  }
 </style>
 <iron-media-query query="(prefers-color-scheme: dark)"
     query-matches="{{isDarkModeActive_}}">
@@ -114,6 +118,11 @@
               $i18n{learnMore}
             </a>
           </div>
+          <template is="dom-if" if="[[showEolIncentive_]]">
+            <eol-offer-section id="endOfLifeOfferContainer"
+                should-show-offer-text="[[shouldShowOfferText_]]">
+            </eol-offer-section>
+          </template>
           <localized-link
               id="endOfLifeMessageContainer" hidden="[[!hasEndOfLife_]]"
               localized-string="$i18n{endOfLifeMessage}">
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
index 886998e..22e3882a 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
@@ -23,6 +23,7 @@
 import '../../settings_shared.css.js';
 import '../os_settings_icons.html.js';
 import '../os_reset_page/os_powerwash_dialog.js';
+import './eol_offer_section.js';
 import './update_warning_dialog.js';
 
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
@@ -131,6 +132,16 @@
         value: false,
       },
 
+      showEolIncentive_: {
+        type: Boolean,
+        value: false,
+      },
+
+      shouldShowOfferText_: {
+        type: Boolean,
+        value: false,
+      },
+
       hasDeferredUpdate_: {
         type: Boolean,
         value: false,
@@ -250,6 +261,8 @@
   private isLts_: boolean;
   private regulatoryInfo_: RegulatoryInfo|null;
   private hasEndOfLife_: boolean;
+  private showEolIncentive_: boolean;
+  private shouldShowOfferText_: boolean;
   private hasDeferredUpdate_: boolean;
   private eolMessageWithMonthAndYear_: string;
   private hasInternetConnection_: boolean;
@@ -299,6 +312,8 @@
     this.aboutBrowserProxy_.getEndOfLifeInfo().then(result => {
       this.hasEndOfLife_ = !!result.hasEndOfLife;
       this.eolMessageWithMonthAndYear_ = result.aboutPageEndOfLifeMessage || '';
+      this.showEolIncentive_ = !!result.shouldShowEndOfLifeIncentive;
+      this.shouldShowOfferText_ = !!result.shouldShowOfferText;
     });
 
     this.aboutBrowserProxy_.checkInternetConnection().then(result => {
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_disconnect_drive_dialog.html b/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_disconnect_drive_dialog.html
new file mode 100644
index 0000000..3397dc92
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_disconnect_drive_dialog.html
@@ -0,0 +1,15 @@
+<style include="settings-shared"></style>
+<cr-dialog id="dialog" show-on-attach close-text="$i18n{close}"
+    on-cancel="onDialogCancel_" on-close="onDialogClose_">
+  <div slot="title">$i18n{disconnectGoogleDriveAccount}</div>
+  <!-- TODO(b/274857477): Update text once defined. -->
+  <div slot="body">Replace this text with the correct copy.</div>
+  <div slot="button-container">
+    <cr-button class="cancel-button" on-click="onCancelTap_">
+      $i18n{cancel}
+    </cr-button>
+    <cr-button class="action-button" on-click="onDisconnectTap_">
+      $i18n{googleDriveDisconnectLabel}
+    </cr-button>
+  </div>
+</cr-dialog>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_disconnect_drive_dialog.ts b/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_disconnect_drive_dialog.ts
new file mode 100644
index 0000000..1b22cdee
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_disconnect_drive_dialog.ts
@@ -0,0 +1,87 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview 'settings-disconnect-drive-confirmation-dialog' is a wrapper of
+ * <cr-dialog>.
+ */
+import 'chrome://resources/cr_elements/cr_button/cr_button.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
+import '../../settings_shared.css.js';
+
+import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
+import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {getTemplate} from './google_drive_disconnect_drive_dialog.html.js';
+
+interface SettingsDisconnectDriveConfirmationDialogElement {
+  $: {
+    dialog: CrDialogElement,
+  };
+}
+
+class SettingsDisconnectDriveConfirmationDialogElement extends PolymerElement {
+  static get is() {
+    return 'settings-disconnect-drive-confirmation-dialog';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  /**
+   * Keeps track of whether the user accepts the action of the dialog.
+   */
+  private accept_: boolean;
+
+  constructor() {
+    super();
+    this.accept_ = true;
+  }
+
+  /**
+   * When the cancel button is pressed, cancel the dialog.
+   */
+  private onCancelTap_() {
+    this.$.dialog.cancel();
+  }
+
+  /**
+   * When the disconnect button is pressed, close the dialog.
+   */
+  private onDisconnectTap_() {
+    this.$.dialog.close();
+  }
+
+  /**
+   * When the dialog is cancelled ensure the `accept_` is false.
+   */
+  private onDialogCancel_() {
+    this.accept_ = false;
+  }
+
+  /**
+   * When the dialog is closed (either through cancellation or acceptance) send
+   * a custom event to the enclosing container.
+   */
+  private onDialogClose_(e: Event) {
+    e.stopPropagation();
+
+    const closeEvent = new CustomEvent(
+        'close',
+        {bubbles: true, composed: true, detail: {'accept': this.accept_}});
+    this.dispatchEvent(closeEvent);
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'settings-disconnect-drive-confirmation-dialog':
+        SettingsDisconnectDriveConfirmationDialogElement;
+  }
+}
+
+customElements.define(
+    SettingsDisconnectDriveConfirmationDialogElement.is,
+    SettingsDisconnectDriveConfirmationDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_subpage.html b/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_subpage.html
index 2bd46ca..c2dd819 100644
--- a/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_subpage.html
+++ b/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_subpage.html
@@ -4,22 +4,30 @@
     class="settings-box two-line first"
     deep-link-focus-id$="[[Setting.kGoogleDriveConnection]]">
   <div class="start">
-    <!-- TODO(b/273399125): email associated with current drive account -->
-    $i18n{googleDriveSignedInAs}
+    $i18nRaw{googleDriveSignedInAs}
   </div>
-  <cr-button role="button">
-    $i18n{googleDriveDisconnectLabel}
-  </cr-button>
+  <controlled-button id="driveConnectDisconnect"
+      on-click="onConnectDisconnectTap_"
+      pref="{{prefs.gdata.disabled}}"
+      label="[[getConnectDisconnectButtonLabel_(driveDisabled_)]]"
+      deep-link-focus-id$="[[Setting.kGoogleDriveConnection]]">
+  </controlled-button>
+  <template is="dom-if" if="[[showDisconnectDriveConfirmationDialog_]]" restamp>
+    <settings-disconnect-drive-confirmation-dialog
+        id="drive-disconnect-dialog"
+        on-close="onDriveDisconnectConfirmationDialogClose_">
+    </settings-disconnect-drive-confirmation-dialog>
+  </template>
 </div>
 
 <div class="hr"></div>
 
+<!-- TODO(b/274857720): Update pref to drivefs.bulk_pinning_enabled -->
 <settings-toggle-button
-    id="disconnectGoogleDriveAccount"
+    id="driveBulkPinning"
     pref="{{prefs.gdata.disabled}}"
     label="$i18n{googleDriveOfflineTitle}"
-    sub-label="$i18n{googleDriveOfflineSubtitle}"
-    deep-link-focus-id$="[[Setting.kGoogleDriveConnection]]">
+    sub-label="$i18n{googleDriveOfflineSubtitle}">
 </settings-toggle-button>
 
 <div class="settings-box two-line">
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_subpage.ts b/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_subpage.ts
index 73bb16d..51289b5 100644
--- a/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_subpage.ts
+++ b/chrome/browser/resources/settings/chromeos/os_files_page/google_drive_subpage.ts
@@ -10,8 +10,10 @@
 import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 
+import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {PrefsMixin} from '../../prefs/prefs_mixin.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {Setting} from '../mojom-webui/setting.mojom-webui.js';
 import {routes} from '../os_settings_routes.js';
@@ -21,9 +23,14 @@
 import {getTemplate} from './google_drive_subpage.html.js';
 
 const SettingsGoogleDriveSubpageElementBase =
-    DeepLinkingMixin(RouteObserverMixin(PolymerElement));
+    I18nMixin(PrefsMixin(DeepLinkingMixin(RouteObserverMixin(PolymerElement))));
 
-class SettingsGoogleDriveSubpageElement extends
+/**
+ * The preference containing the value whether Google drive is disabled or not.
+ */
+const GOOGLE_DRIVE_DISABLED_PREF = 'gdata.disabled';
+
+export class SettingsGoogleDriveSubpageElement extends
     SettingsGoogleDriveSubpageElementBase {
   static get is() {
     return 'settings-google-drive-subpage';
@@ -36,24 +43,50 @@
   static get properties() {
     return {
       /**
-       * Preferences state.
-       */
-      prefs: {
-        type: Object,
-        notify: true,
-      },
-
-      /**
        * Used by DeepLinkingMixin to focus this page's deep links.
        */
       supportedSettingIds: {
         type: Object,
         value: () => new Set<Setting>([Setting.kGoogleDriveConnection]),
       },
+
+      /**
+       * Whether to show the confirmation dialog when disconnecting Drive.
+       */
+      showDisconnectDriveConfirmationDialog_: {
+        type: Boolean,
+        value: false,
+      },
     };
   }
 
-  prefs: object;
+  /**
+   * Observe the state of `prefs.gdata.disabled` if it gets changed from another
+   * location (e.g. enterprise policy).
+   */
+  static get observers() {
+    return [
+      `updateDriveDisabled_(prefs.${GOOGLE_DRIVE_DISABLED_PREF}.*)`,
+    ];
+  }
+
+  /**
+   * Reflects the state of `prefs.gdata.disabled` pref.
+   */
+  private driveDisabled_: boolean;
+
+  /**
+   * Tracks the state of the disconnect confirmation dialog.
+   */
+  private showDisconnectDriveConfirmationDialog_: boolean;
+
+  /**
+   * Invoked when the `prefs.gdata.disabled` preference changes value.
+   */
+  private updateDriveDisabled_() {
+    const disabled = this.getPref(GOOGLE_DRIVE_DISABLED_PREF).value;
+    this.driveDisabled_ = disabled;
+  }
 
   override currentRouteChanged(route: Route, _oldRoute?: Route) {
     // Does not apply to this page.
@@ -63,6 +96,42 @@
 
     this.attemptDeepLink();
   }
+
+  /**
+   * Returns the value for the button to Connect/Disconnect Google drive
+   * depending on the current state.
+   */
+  private getConnectDisconnectButtonLabel_(): string {
+    return this.driveDisabled_ ? this.i18n('googleDriveConnectLabel') :
+                                 this.i18n('googleDriveDisconnectLabel');
+  }
+
+  /**
+   * If Drive is disconnected, immediately update the preference. If Drive is
+   * connected, show the confirmation dialog instead of immediately updating the
+   * preference when the button is pressed.
+   */
+  private onConnectDisconnectTap_(): void {
+    if (this.driveDisabled_) {
+      this.setPrefValue(GOOGLE_DRIVE_DISABLED_PREF, false);
+      return;
+    }
+    this.showDisconnectDriveConfirmationDialog_ = true;
+  }
+
+  /**
+   * Update the `gdata.disabled` pref to `true` iff the "Disconnect" button was
+   * pressed, all remaining actions (e.g. Cancel, ESC) should not update the
+   * preference.
+   */
+  private onDriveDisconnectConfirmationDialogClose_(e: CustomEvent) {
+    this.showDisconnectDriveConfirmationDialog_ = false;
+    if (!e.detail.accept) {
+      return;
+    }
+
+    this.setPrefValue(GOOGLE_DRIVE_DISABLED_PREF, true);
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.html b/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.html
index e96eb7f..f32caab5 100644
--- a/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.html
@@ -15,7 +15,7 @@
           id="GoogleDriveLink"
           class="hr" on-click="onGoogleDrive_"
           label="$i18n{googleDriveLabel}"
-          sub-label="$i18n{googleDriveEnabledLabel}"
+          sub-label="[[getGoogleDriveStatus_(driveDisabled_)]]"
           role-description="$i18n{subpageArrowRoleDescription}">
       </cr-link-row>
     </template>
@@ -39,7 +39,7 @@
   </template>
   <template is="dom-if" route-path="/googleDrive">
     <os-settings-subpage page-title="$i18n{googleDriveLabel}">
-      <settings-google-drive-subpage prefs="[[prefs]]">
+      <settings-google-drive-subpage prefs="{{prefs}}">
       </settings-google-drive-subpage>
     </os-settings-subpage>
   </template>
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.ts b/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.ts
index 1925f5f..e240e568 100644
--- a/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.ts
@@ -17,6 +17,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {PrefsMixin} from '../../prefs/prefs_mixin.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {Setting} from '../mojom-webui/setting.mojom-webui.js';
 import {routes} from '../os_settings_routes.js';
@@ -26,7 +27,7 @@
 import {getTemplate} from './os_files_page.html.js';
 
 const OsSettingsFilesPageElementBase =
-    DeepLinkingMixin(RouteObserverMixin(PolymerElement));
+    PrefsMixin(DeepLinkingMixin(RouteObserverMixin(PolymerElement)));
 
 class OsSettingsFilesPageElement extends OsSettingsFilesPageElementBase {
   static get is() {
@@ -40,14 +41,6 @@
   static get properties() {
     return {
       /**
-       * Preferences state.
-       */
-      prefs: {
-        type: Object,
-        notify: true,
-      },
-
-      /**
        * Used by DeepLinkingMixin to focus this page's deep links.
        */
       supportedSettingIds: {
@@ -84,7 +77,17 @@
     };
   }
 
-  prefs: Object;
+  /**
+   * Observe the state of `prefs.gdata.disabled` if it gets changed from another
+   * location (e.g. enterprise policy).
+   */
+  static get observers() {
+    return [
+      `updateDriveDisabled_(prefs.gdata.disabled.*)`,
+    ];
+  }
+
+  private driveDisabled_: boolean;
   private focusConfig_: Map<string, string>;
 
   override currentRouteChanged(route: Route, _oldRoute?: Route) {
@@ -107,6 +110,17 @@
   private onTapOffice_() {
     Router.getInstance().navigateTo(routes.OFFICE);
   }
+
+  private updateDriveDisabled_() {
+    const disabled = this.getPref('gdata.disabled').value;
+    this.driveDisabled_ = disabled;
+  }
+
+  private getGoogleDriveStatus_(): string {
+    return this.driveDisabled_ ?
+        loadTimeData.getString('googleDriveDisabledLabel') :
+        loadTimeData.getString('googleDriveEnabledLabel');
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index a28728d..3e8e729 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -133,6 +133,7 @@
   "chromeos/os_about_page/channel_switcher_dialog.ts",
   "chromeos/os_about_page/consumer_auto_update_toggle_dialog.ts",
   "chromeos/os_about_page/detailed_build_info_subpage.ts",
+  "chromeos/os_about_page/eol_offer_section.ts",
   "chromeos/os_about_page/edit_hostname_dialog.ts",
   "chromeos/os_about_page/os_about_page.ts",
   "chromeos/os_about_page/update_warning_dialog.ts",
@@ -175,6 +176,7 @@
   "chromeos/os_files_page/os_files_page.ts",
   "chromeos/os_files_page/smb_shares_page.ts",
   "chromeos/os_files_page/google_drive_subpage.ts",
+  "chromeos/os_files_page/google_drive_disconnect_drive_dialog.ts",
   "chromeos/os_languages_page/add_input_methods_dialog.ts",
   "chromeos/os_languages_page/add_items_dialog.ts",
   "chromeos/os_languages_page/add_spellcheck_languages_dialog.ts",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.ts b/chrome/browser/resources/settings/chromeos/os_settings.ts
index cc7b278..92ac34f 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings.ts
@@ -115,7 +115,7 @@
 export {fakeKeyboards, fakeKeyboards2, fakeMice, fakeMice2, fakePointingSticks, fakePointingSticks2, fakeTouchpads, fakeTouchpads2} from './device_page/fake_input_device_data.js';
 export {FakeInputDeviceSettingsProvider} from './device_page/fake_input_device_settings_provider.js';
 export {getInputDeviceSettingsProvider, setInputDeviceSettingsProviderForTesting, setupFakeInputDeviceSettingsProvider} from './device_page/input_device_mojo_interface_provider.js';
-export {MetaKey, ModifierKey, Mouse} from './device_page/input_device_settings_types.js';
+export {Keyboard, MetaKey, ModifierKey, Mouse} from './device_page/input_device_settings_types.js';
 export {KeyboardRemapModifierKeyRowElement} from './device_page/keyboard_remap_modifier_key_row.js';
 export {SettingsPerDeviceKeyboardElement} from './device_page/per_device_keyboard.js';
 export {SettingsPerDeviceKeyboardRemapKeysElement} from './device_page/per_device_keyboard_remap_keys.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_icons.html b/chrome/browser/resources/settings/chromeos/os_settings_icons.html
index ccfc8eb..6e5ba23 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_icons.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_icons.html
@@ -122,6 +122,7 @@
       <g id="dictation" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="m12.571 4.5-.008 5c0 1.383-1.14 2.5-2.563 2.5-1.423 0-2.571-1.117-2.571-2.5v-5C7.429 3.117 8.577 2 10 2c1.423 0 2.571 1.117 2.571 2.5Zm-2.524-1a1 1 0 0 0-1 .992l-.04 5a1 1 0 0 0 2 .016l.04-5a1 1 0 0 0-1-1.008ZM10 13.874c-2.366 0-4.543-1.769-4.543-4.295H4c0 2.88 2.331 5.246 5.143 5.659V18h1.714v-2.762C13.67 14.834 16 12.459 16 9.579h-1.457c0 2.526-2.177 4.295-4.543 4.295Z"></path></g>
       <g id="display"><path fill-rule="evenodd" clip-rule="evenodd" d="M17.5 3H2.5C1.6 3 1 3.7 1 4.55556V14.5C1 15.3556 1.6 16 2.5 16H7V18H13V16H17.5C18.4 16 19 15.3556 19 14.5V4.5C19 3.64444 18.4 3 17.5 3ZM17 14H3V5H17V14Z"></path></g>
       <g id="docked-magnifier" viewBox="0 0 20 20"><path d="M14 11V9h2V8h-2V6h-1v2h-2v1h2v2h1Z"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M17.5 3h-15C1.6 3 1 3.7 1 4.556V15.5c0 .856.6 1.5 1.5 1.5h15c.9 0 1.5-.644 1.5-1.5v-11c0-.856-.6-1.5-1.5-1.5Zm-.5 9H3V5h14v7Z"></path></g>
+      <g id="end-of-life-offer" viewBox="0 0 20 20"><path d="M7 20V18H17V20H7ZM11 16V7.825L8.4 10.4L7 9L12 4L17 9L15.6 10.4L13 7.825V16H11Z"></path></g>
       <g id="fullscreen-magnifier" viewBox="0 0 20 20"><path d="M14 11V9h2V8h-2V6h-1v2h-2v1h2v2h1Z"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M17.5 3h-15C1.6 3 1 3.7 1 4.556V15.5c0 .856.6 1.5 1.5 1.5h15c.9 0 1.5-.644 1.5-1.5v-11c0-.856-.6-1.5-1.5-1.5ZM17 15H3V5h14v10Z"></path></g>
       <g id="geolocation"><path d="M12 8C12 9.10457 11.1046 10 10 10C8.89543 10 8 9.10457 8 8C8 6.89543 8.89543 6 10 6C11.1046 6 12 6.89543 12 8Z" fill="#1B1B1F"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M16 8C16 10.2091 14 13.5425 10 18C6 13.5425 4 10.2091 4 8C4 4.68629 6.68629 2 10 2C13.3137 2 16 4.68629 16 8ZM10 4C7.79086 4 6 5.79086 6 8C6 9.32543 7.318 11.7149 10 14.9435C12.682 11.7149 14 9.32543 14 8C14 5.79086 12.2091 4 10 4Z" fill="#1B1B1F"></path></g>
       <g id="google-drive"><path fill-rule="evenodd" clip-rule="evenodd" d="M18.7333 12L13.0167 2H7.31665V2.00833L13.025 12H18.7333ZM8.27502 12.8334L5.41669 17.8334H16.35L19.2084 12.8334H8.27502ZM6.59167 3.26672L1.125 12.8334L3.98333 17.8251L9.45 8.26672C9.45 8.27506 6.59167 3.26672 6.59167 3.26672Z"></path></g>
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
index c2aa7b9..c499b644 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
@@ -89,12 +89,21 @@
   #toggleSpacer {
     padding-top: 33px;  /* Part of a 48px spacer (33px + 12px + 3px). */
   }
+
+  iron-icon {
+    margin-inline-start: 16px;
+  }
+
+  eol-offer-section {
+    margin-top: 20px;
+  }
 </style>
 <template is="dom-if" if="[[showBasicPage_(
     currentRoute_, hasExpandedSection_)]]">
   <div id="basicPage">
     <template is="dom-if" if="[[computeShowUpdateRequiredEolBanner_(
-        hasExpandedSection_, showUpdateRequiredEolBanner_)]]">
+        hasExpandedSection_, showUpdateRequiredEolBanner_,
+        showEOLIncentive_)]]">
       <div id="updateRequiredEolBanner"
           class="settings-box two-line banner">
         <div class="eol-warning-icon">
@@ -109,6 +118,11 @@
         </cr-icon-button>
       </div>
     </template>
+    <template is="dom-if" if="[[computeShowEolIncentive_(hasExpandedSection_,
+        showEolIncentive_)]]">
+      <eol-offer-section should-show-offer-text="[[shouldShowOfferText_]]">
+      </eol-offer-section>
+    </template>
     <div id="secondaryUserBanner" class="settings-box two-line banner"
         hidden="[[!showSecondaryUserBanner_]]">
       <div id="secondaryUserIcon">
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts
index df140c61..52ff3f1 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts
@@ -13,6 +13,7 @@
 import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import './settings_idle_load.js';
+import '../os_about_page/eol_offer_section.js';
 import '../os_apps_page/os_apps_page.js';
 import '../os_people_page/os_people_page.js';
 import '../os_privacy_page/os_privacy_page.js';
@@ -35,6 +36,7 @@
 
 import {castExists} from '../assert_extras.js';
 import {MainPageMixin} from '../main_page_mixin.js';
+import {AboutPageBrowserProxyImpl} from '../os_about_page/about_page_browser_proxy.js';
 import {AndroidAppsBrowserProxyImpl, AndroidAppsInfo} from '../os_apps_page/android_apps_browser_proxy.js';
 import {OsPageVisibility} from '../os_page_visibility.js';
 import {routes} from '../os_settings_routes.js';
@@ -138,6 +140,16 @@
       },
 
       currentRoute_: Object,
+
+      showEolIncentive_: {
+        type: Boolean,
+        value: false,
+      },
+
+      shouldShowOfferText_: {
+        type: Boolean,
+        value: false,
+      },
     };
   }
 
@@ -154,6 +166,8 @@
    * Used to avoid handling a new toggle while currently toggling.
    */
   private advancedTogglingInProgress_: boolean;
+  private showEolIncentive_: boolean;
+  private shouldShowOfferText_: boolean;
 
   constructor() {
     super();
@@ -178,6 +192,12 @@
     this.addWebUiListener(
         'android-apps-info-update', this.androidAppsInfoUpdate_.bind(this));
     AndroidAppsBrowserProxyImpl.getInstance().requestAndroidAppsInfo();
+
+    AboutPageBrowserProxyImpl.getInstance().pageReady();
+    AboutPageBrowserProxyImpl.getInstance().getEndOfLifeInfo().then(result => {
+      this.showEolIncentive_ = !!result.shouldShowEndOfLifeIncentive;
+      this.shouldShowOfferText_ = !!result.shouldShowOfferText;
+    });
   }
 
   override currentRouteChanged(newRoute: Route, oldRoute?: Route) {
@@ -216,7 +236,12 @@
   }
 
   private computeShowUpdateRequiredEolBanner_(): boolean {
-    return !this.hasExpandedSection_ && this.showUpdateRequiredEolBanner_;
+    return !this.hasExpandedSection_ && this.showUpdateRequiredEolBanner_ &&
+        !this.showEolIncentive_;
+  }
+
+  private computeShowEolIncentive_(): boolean {
+    return !this.hasExpandedSection_ && this.showEolIncentive_;
   }
 
   private androidAppsInfoUpdate_(info: AndroidAppsInfo) {
diff --git a/chrome/browser/resources/side_panel/bookmarks/bookmarks_api_proxy.ts b/chrome/browser/resources/side_panel/bookmarks/bookmarks_api_proxy.ts
index 987b9cb9..1ebbee1 100644
--- a/chrome/browser/resources/side_panel/bookmarks/bookmarks_api_proxy.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/bookmarks_api_proxy.ts
@@ -17,6 +17,8 @@
   contextMenuOpenBookmarkInNewWindow(ids: string[], source: ActionSource): void;
   contextMenuOpenBookmarkInIncognitoWindow(ids: string[], source: ActionSource):
       void;
+  contextMenuOpenBookmarkInNewTabGroup(ids: string[], source: ActionSource):
+      void;
   contextMenuAddToBookmarksBar(id: string, source: ActionSource): void;
   contextMenuRemoveFromBookmarksBar(id: string, source: ActionSource): void;
   contextMenuDelete(id: string, source: ActionSource): void;
@@ -86,6 +88,11 @@
         ids.map(id => BigInt(id)), source);
   }
 
+  contextMenuOpenBookmarkInNewTabGroup(ids: string[], source: ActionSource) {
+    this.handler.executeOpenInNewTabGroupCommand(
+        ids.map(id => BigInt(id)), source);
+  }
+
   contextMenuAddToBookmarksBar(id: string, source: ActionSource) {
     this.handler.executeAddToBookmarksBarCommand(BigInt(id), source);
   }
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.html b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.html
index 0dfbd34..36f2dff 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.html
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.html
@@ -13,7 +13,8 @@
       items="[[getMenuItemsForBookmarks_(
                    bookmarks_, priceTracked_, priceTrackingEligible_)]]">
     <template is="dom-if" if="[[!showDivider_(item)]]" restamp>
-      <button class="dropdown-item" on-click="onMenuItemClicked_">
+      <button class="dropdown-item" on-click="onMenuItemClicked_"
+          disabled="[[item.disabled]]">
         [[item.label]]
       </button>
     </template>
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.ts
index 4da747a..a7c91d37 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.ts
@@ -28,18 +28,20 @@
   OPEN_NEW_TAB = 0,
   OPEN_NEW_WINDOW = 1,
   OPEN_INCOGNITO = 2,
-  EDIT = 3,
-  ADD_TO_BOOKMARKS_BAR = 4,
-  REMOVE_FROM_BOOKMARKS_BAR = 5,
-  TRACK_PRICE = 6,
-  RENAME = 7,
-  DELETE = 8,
-  DIVIDER = 9,
+  OPEN_NEW_TAB_GROUP = 3,
+  EDIT = 4,
+  ADD_TO_BOOKMARKS_BAR = 5,
+  REMOVE_FROM_BOOKMARKS_BAR = 6,
+  TRACK_PRICE = 7,
+  RENAME = 8,
+  DELETE = 9,
+  DIVIDER = 10,
 }
 
 export interface MenuItem {
   id: MenuItemId;
   label?: string;
+  disabled?: boolean;
 }
 
 export class PowerBookmarksContextMenuElement extends PolymerElement {
@@ -84,30 +86,53 @@
   }
 
   private getMenuItemsForBookmarks_(): MenuItem[] {
+    // TODO(crbug.com/1428654): Factor in URLs not available in incognito.
+    let bookmarkCount = 0;
+    this.bookmarks_.forEach((bookmark) => {
+      if (bookmark.url) {
+        bookmarkCount += 1;
+      } else if (bookmark.children) {
+        bookmarkCount +=
+            bookmark.children.filter((child) => !!child.url).length;
+      }
+    });
     const menuItems: MenuItem[] = [
       {
         id: MenuItemId.OPEN_NEW_TAB,
-        label: this.bookmarks_.length === 1 ?
+        label: bookmarkCount < 2 ?
             loadTimeData.getString('menuOpenNewTab') :
-            loadTimeData.getStringF(
-                'menuOpenNewTabWithCount', this.bookmarks_.length),
+            loadTimeData.getStringF('menuOpenNewTabWithCount', bookmarkCount),
+        disabled: bookmarkCount === 0,
       },
       {
         id: MenuItemId.OPEN_NEW_WINDOW,
-        label: this.bookmarks_.length === 1 ?
+        label: bookmarkCount < 2 ?
             loadTimeData.getString('menuOpenNewWindow') :
             loadTimeData.getStringF(
-                'menuOpenNewWindowWithCount', this.bookmarks_.length),
+                'menuOpenNewWindowWithCount', bookmarkCount),
+        disabled: bookmarkCount === 0,
       },
     ];
 
     if (!loadTimeData.getBoolean('incognitoMode')) {
       menuItems.push({
         id: MenuItemId.OPEN_INCOGNITO,
-        label: this.bookmarks_.length === 1 ?
+        label: bookmarkCount < 2 ?
             loadTimeData.getString('menuOpenIncognito') :
             loadTimeData.getStringF(
-                'menuOpenIncognitoWithCount', this.bookmarks_.length),
+                'menuOpenIncognitoWithCount', bookmarkCount),
+        disabled: bookmarkCount === 0,
+      });
+    }
+
+    if (this.bookmarks_.length !== 1 || !this.bookmarks_[0]!.url) {
+      menuItems.push({
+        id: MenuItemId.OPEN_NEW_TAB_GROUP,
+        label: bookmarkCount < 2 ?
+            loadTimeData.getString('menuOpenNewTabGroup') :
+            loadTimeData.getStringF(
+                'menuOpenNewTabGroupWithCount', bookmarkCount),
+        disabled: bookmarkCount === 0,
       });
     }
 
@@ -116,6 +141,16 @@
       return menuItems;
     }
 
+    if (this.bookmarks_[0]!.url ||
+        this.bookmarks_[0]!.parentId ===
+            loadTimeData.getString('bookmarksBarId') ||
+        this.bookmarks_[0]!.parentId ===
+            loadTimeData.getString('otherBookmarksId') ||
+        this.bookmarks_[0]!.parentId ===
+            loadTimeData.getString('mobileBookmarksId')) {
+      menuItems.push({id: MenuItemId.DIVIDER});
+    }
+
     if (this.bookmarks_[0]!.url) {
       menuItems.push({
         id: MenuItemId.EDIT,
@@ -125,7 +160,7 @@
 
     if (this.bookmarks_[0]!.parentId ===
         loadTimeData.getString('bookmarksBarId')) {
-      menuItems.push({id: MenuItemId.DIVIDER}, {
+      menuItems.push({
         id: MenuItemId.REMOVE_FROM_BOOKMARKS_BAR,
         label: loadTimeData.getString('menuMoveToAllBookmarks'),
       });
@@ -134,7 +169,7 @@
             loadTimeData.getString('otherBookmarksId') ||
         this.bookmarks_[0]!.parentId ===
             loadTimeData.getString('mobileBookmarksId')) {
-      menuItems.push({id: MenuItemId.DIVIDER}, {
+      menuItems.push({
         id: MenuItemId.ADD_TO_BOOKMARKS_BAR,
         label: loadTimeData.getString('menuMoveToBookmarksBar'),
       });
@@ -200,6 +235,11 @@
             this.bookmarks_.map(bookmark => bookmark.id),
             ActionSource.kBookmark);
         break;
+      case MenuItemId.OPEN_NEW_TAB_GROUP:
+        this.bookmarksApi_.contextMenuOpenBookmarkInNewTabGroup(
+            this.bookmarks_.map(bookmark => bookmark.id),
+            ActionSource.kBookmark);
+        break;
       // Everything below is not expected to ever be called when
       // this.bookmarks_ has more than one entry.
       case MenuItemId.ADD_TO_BOOKMARKS_BAR:
diff --git a/chrome/browser/resources/side_panel/read_anything/app.html b/chrome/browser/resources/side_panel/read_anything/app.html
index 9852629a..e7611a62 100644
--- a/chrome/browser/resources/side_panel/read_anything/app.html
+++ b/chrome/browser/resources/side_panel/read_anything/app.html
@@ -21,6 +21,14 @@
     margin: 0 auto 16px auto;
     width: fit-content;
   }
+  ::selection {
+    background: var(--selection-color);
+  }
+  @media (prefers-color-scheme: dark) {
+    ::selection {
+      color: var(--google-grey-900);
+    }
+  }
 </style>
 <div id="container" hidden="[[!hasContent_]]"></div>
 <div id="empty-state-container" hidden="[[hasContent_]]">
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts
index a4b7452..a0f7242 100644
--- a/chrome/browser/resources/side_panel/read_anything/app.ts
+++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -21,8 +21,11 @@
   default: string;
   visited: string;
 }
-const darkThemeBackgroundSkColor = rgbToSkColor(
-    getComputedStyle(document.body).getPropertyValue('--google-grey-900-rgb'));
+const style = getComputedStyle(document.body);
+const darkThemeBackgroundSkColor =
+    rgbToSkColor(style.getPropertyValue('--google-grey-900-rgb'));
+const lightThemeBackgroundSkColor =
+    rgbToSkColor(style.getPropertyValue('--google-grey-50-rgb'));
 const darkThemeEmptyStateBodyColor = 'var(--google-grey-500)';
 const defaultThemeEmptyStateBodyColor = 'var(--google-grey-700)';
 const defaultLinkColors: LinkColor = {
@@ -33,6 +36,9 @@
   default: 'var(--google-blue-300)',
   visited: 'var(--google-purple-100)',
 };
+const lightThemeSelectionColor = 'var(--google-yellow-100)';
+const darkThemeSelectionColor = 'var(--google-blue-300)';
+const defaultThemeSelctionColor = 'var(--google-blue-100)';
 
 // A two-way map where each key is unique and each value is unique. The keys are
 // DOM nodes and the values are numbers, representing AXNodeIDs.
@@ -71,6 +77,12 @@
     readAnythingApp.updateContent();
   };
 
+  chrome.readAnything.updateSelection = () => {
+    const readAnythingApp = document.querySelector('read-anything-app');
+    assert(readAnythingApp);
+    readAnythingApp.updateSelection();
+  };
+
   chrome.readAnything.updateTheme = () => {
     const readAnythingApp = document.querySelector('read-anything-app');
     assert(readAnythingApp);
@@ -254,10 +266,9 @@
 
     this.hasContent_ = true;
     container.appendChild(node);
-    this.updateSelection_();
   }
 
-  private updateSelection_() {
+  updateSelection() {
     const shadowRoot = this.shadowRoot;
     assert(shadowRoot);
     const selection = shadowRoot.getSelection();
@@ -307,6 +318,17 @@
                     defaultThemeEmptyStateBodyColor;
   }
 
+  private getSelectionColor_(backgroundSkColor: SkColor): string {
+    switch (backgroundSkColor.value) {
+      case lightThemeBackgroundSkColor.value:
+        return lightThemeSelectionColor;
+      case darkThemeBackgroundSkColor.value:
+        return darkThemeSelectionColor;
+      default:
+        return defaultThemeSelctionColor;
+    }
+  }
+
   updateTheme() {
     const foregroundColor:
         SkColor = {value: chrome.readAnything.foregroundColor};
@@ -321,6 +343,7 @@
       '--letter-spacing': chrome.readAnything.letterSpacing + 'em',
       '--line-height': chrome.readAnything.lineSpacing,
       '--link-color': linkColor.default,
+      '--selection-color': this.getSelectionColor_(backgroundColor),
       '--sp-empty-state-heading-color': skColorToRgba(foregroundColor),
       '--sp-empty-state-body-color':
           this.getEmptyStateBodyColor_(backgroundColor),
diff --git a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts
index 38cd9a22..d735cd29 100644
--- a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts
+++ b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts
@@ -70,7 +70,7 @@
 
     // Called when a user makes a selection change. AnchorNodeID and
     // focusAXNodeID are AXNodeIDs which identify the anchor and focus AXNodes
-    // in the main pane.
+    // in the main pane. The selection can either be forward or backwards.
     function onSelectionChange(
         anchorNodeId: number, anchorOffset: number, focusNodeId: number,
         focusOffset: number): void;
@@ -112,6 +112,9 @@
     // and is available to consume.
     function updateContent(): void;
 
+    // Ping that the selection has been updated.
+    function updateSelection(): void;
+
     // Ping that the theme choices of the user have been changed using the
     // toolbar and are ready to consume.
     function updateTheme(): void;
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker.html b/chrome/browser/resources/signin/profile_picker/profile_picker.html
index 59fdc21..9f7fd49f 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_picker.html
+++ b/chrome/browser/resources/signin/profile_picker/profile_picker.html
@@ -1,5 +1,6 @@
 <!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<html dir="$i18n{textdirection}" lang="$i18n{language}"
+    $i18n{chromeRefresh2023Attribute}>
   <head>
     <base href="chrome://profile-picker">
     <meta charset="utf-8">
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc b/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc
index 4c1ab4f5..a2b9dd6 100644
--- a/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc
+++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc
@@ -577,7 +577,9 @@
         ShouldPromptForDeepScanning(response.request_deep_scan());
     if (should_prompt) {
       result = DownloadCheckResult::PROMPT_FOR_SCANNING;
-      reason = DownloadCheckResultReason::REASON_ADVANCED_PROTECTION_PROMPT;
+      reason = DownloadCheckResultReason::REASON_DEEP_SCAN_PROMPT;
+      base::UmaHistogramEnumeration("SBClientDownload.DeepScanEvent",
+                                    DeepScanEvent::kPromptShown);
     }
 
     // Only record the UMA metric if we're in a population that potentially
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
index cf9784d5..1795c2f7 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
@@ -243,8 +243,8 @@
   switch (trigger) {
     case DeepScanningRequest::DeepScanTrigger::TRIGGER_UNKNOWN:
       return "Unknown";
-    case DeepScanningRequest::DeepScanTrigger::TRIGGER_APP_PROMPT:
-      return "AdvancedProtectionPrompt";
+    case DeepScanningRequest::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT:
+      return "ConsumerPrompt";
     case DeepScanningRequest::DeepScanTrigger::TRIGGER_POLICY:
       return "Policy";
   }
@@ -566,7 +566,9 @@
     base::UmaHistogramEnumeration(
         "SBClientDownload.MalwareDeepScanResult." + GetTriggerName(trigger_),
         download_result);
-  } else if (trigger_ == DeepScanTrigger::TRIGGER_APP_PROMPT &&
+    base::UmaHistogramEnumeration("SBClientDownload.DeepScanEvent",
+                                  DeepScanEvent::kScanCompleted);
+  } else if (trigger_ == DeepScanTrigger::TRIGGER_CONSUMER_PROMPT &&
              ResultIsRetriable(result) &&
              MaybeShowDeepScanFailureModalDialog(
                  base::BindOnce(&DeepScanningRequest::Start,
@@ -731,8 +733,9 @@
 }
 
 bool DeepScanningRequest::ReportOnlyScan() {
-  if (trigger_ == DeepScanTrigger::TRIGGER_APP_PROMPT)
+  if (trigger_ == DeepScanTrigger::TRIGGER_CONSUMER_PROMPT) {
     return false;
+  }
 
   return analysis_settings_.block_until_verdict ==
          enterprise_connectors::BlockUntilVerdict::kNoBlock;
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.h b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.h
index 33be6250..845f445 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.h
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.h
@@ -43,8 +43,8 @@
     TRIGGER_UNKNOWN = 0,
 
     // The trigger is the prompt in the download shelf, shown for Advanced
-    // Protection users.
-    TRIGGER_APP_PROMPT = 1,
+    // Protection or Enhanced Protection users.
+    TRIGGER_CONSUMER_PROMPT = 1,
 
     // The trigger is the enterprise policy.
     TRIGGER_POLICY = 2,
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
index fa5acf42..5994f4b 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
@@ -543,11 +543,11 @@
 
 class DeepScanningAPPRequestTest : public DeepScanningRequestTest {};
 
-TEST_F(DeepScanningAPPRequestTest, GeneratesCorrectRequestForAPP) {
+TEST_F(DeepScanningAPPRequestTest, GeneratesCorrectRequestForConsumer) {
   enterprise_connectors::AnalysisSettings settings;
   settings.tags = {{"malware", enterprise_connectors::TagSettings()}};
   DeepScanningRequest request(
-      &item_, DeepScanningRequest::DeepScanTrigger::TRIGGER_APP_PROMPT,
+      &item_, DeepScanningRequest::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
       DownloadCheckResult::SAFE, base::DoNothing(),
       &download_protection_service_, std::move(settings));
   request.Start();
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_util.h b/chrome/browser/safe_browsing/download_protection/download_protection_util.h
index 72a41242..30741edf 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_util.h
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_util.h
@@ -53,7 +53,7 @@
   REASON_SENSITIVE_CONTENT_WARNING = 31,
   REASON_SENSITIVE_CONTENT_BLOCK = 32,
   REASON_DEEP_SCANNED_SAFE = 33,
-  REASON_ADVANCED_PROTECTION_PROMPT = 34,
+  REASON_DEEP_SCAN_PROMPT = 34,
   REASON_BLOCKED_UNSUPPORTED_FILE_TYPE = 35,
   REASON_DOWNLOAD_DANGEROUS_ACCOUNT_COMPROMISE = 36,
   REASON_MAX  // Always add new values before this one.
@@ -82,6 +82,18 @@
   ALLOWLIST_TYPE_MAX
 };
 
+// Enum for events related to the deep scanning of a download. These values
+// are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class DeepScanEvent {
+  kPromptShown = 0,
+  kPromptBypassed = 1,
+  kPromptAccepted = 2,
+  kScanCanceled = 3,
+  kScanCompleted = 4,
+  kMaxValue = kScanCompleted,
+};
+
 // Callback type which is invoked once the download request is done.
 typedef base::OnceCallback<void(DownloadCheckResult)> CheckDownloadCallback;
 
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_unittest.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_unittest.cc
index a08499c6..3e84bef3 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_unittest.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_unittest.cc
@@ -74,13 +74,7 @@
 
   void SetUp() override {
     extensions::ExtensionServiceTestBase::SetUp();
-
-    // By not specifying a pref_file filepath, we get a
-    // sync_preferences::TestingPrefServiceSyncable, which in turn provides us
-    // with a convient way of registring preferences.
-    ExtensionServiceInitParams init_params = CreateDefaultInitParams();
-    init_params.pref_file.clear();
-    InitializeExtensionService(init_params);
+    InitializeExtensionService(ExtensionServiceInitParams());
 
 #if !BUILDFLAG(IS_WIN)
     // In production code, the settings reset prompt profile preferences are
diff --git a/chrome/browser/safe_browsing/tailored_security/chrome_tailored_security_service.cc b/chrome/browser/safe_browsing/tailored_security/chrome_tailored_security_service.cc
index 5d8c4c37..505c6f7 100644
--- a/chrome/browser/safe_browsing/tailored_security/chrome_tailored_security_service.cc
+++ b/chrome/browser/safe_browsing/tailored_security/chrome_tailored_security_service.cc
@@ -32,6 +32,12 @@
 
 namespace safe_browsing {
 
+#if BUILDFLAG(IS_ANDROID)
+// Names for if the observer-based recovery mechanism is triggered.
+const bool kRetryMechanismTriggered = true;
+const bool kRetryMechanismNotTriggered = false;
+#endif
+
 namespace {
 
 #if BUILDFLAG(IS_ANDROID)
@@ -80,6 +86,9 @@
     if (base::FeatureList::IsEnabled(
             safe_browsing::kTailoredSecurityObserverRetries)) {
       AddTabModelListObserver();
+      base::UmaHistogramBoolean(
+          "SafeBrowsing.TailoredSecurity.IsRecoveryTriggered",
+          kRetryMechanismTriggered);
       return;
     }
     if (is_enabled) {
@@ -88,6 +97,12 @@
     }
     return;
   }
+  if (base::FeatureList::IsEnabled(
+          safe_browsing::kTailoredSecurityObserverRetries)) {
+    base::UmaHistogramBoolean(
+        "SafeBrowsing.TailoredSecurity.IsRecoveryTriggered",
+        kRetryMechanismNotTriggered);
+  }
 
   // Since the Android UX is a notice, we simply set Safe Browsing state.
   SetSafeBrowsingState(profile_->GetPrefs(),
diff --git a/chrome/browser/safe_browsing/tailored_security/chrome_tailored_security_service_android_unittest.cc b/chrome/browser/safe_browsing/tailored_security/chrome_tailored_security_service_android_unittest.cc
index cc85798..297f1189 100644
--- a/chrome/browser/safe_browsing/tailored_security/chrome_tailored_security_service_android_unittest.cc
+++ b/chrome/browser/safe_browsing/tailored_security/chrome_tailored_security_service_android_unittest.cc
@@ -53,7 +53,6 @@
     browser_process_ = TestingBrowserProcess::GetGlobal();
     chrome_tailored_security_service_ =
         std::make_unique<TestChromeTailoredSecurityService>(&profile_);
-    // message_dispatcher_bridge_.SetMessagesEnabledForEmbedder(true);
     messages::MessageDispatcherBridge::SetInstanceForTesting(
         &message_dispatcher_bridge_);
   }
@@ -79,7 +78,8 @@
   std::unique_ptr<TestChromeTailoredSecurityService>
       chrome_tailored_security_service_;
   base::HistogramTester histograms_;
-  messages::MockMessageDispatcherBridge message_dispatcher_bridge_;
+  testing::NiceMock<messages::MockMessageDispatcherBridge>
+      message_dispatcher_bridge_;
   base::test::ScopedFeatureList feature_list;
 };
 
@@ -157,7 +157,6 @@
   tab_model.SetWebContents(raw_contents);
   tab_model.tab_count_ = 1;
 
-  EXPECT_CALL(message_dispatcher_bridge_, EnqueueWindowScopedMessage);
   chrome_tailored_security_service_->OnSyncNotificationMessageRequest(
       kTailoredSecurityEnabled);
   histograms_.ExpectBucketCount(
@@ -201,7 +200,6 @@
   tab_model.SetWebContents(raw_contents);
   tab_model.tab_count_ = 1;
 
-  EXPECT_CALL(message_dispatcher_bridge_, EnqueueWindowScopedMessage);
   // Simulate observers being notified after a tab is added.
   tab_model.observer_->DidAddTab(nullptr, TabModel::TabLaunchType::FROM_LINK);
 
@@ -210,4 +208,41 @@
       TailoredSecurityNotificationResult::kShown, 1);
 }
 
+TEST_F(ChromeTailoredSecurityServiceTest,
+       RetryEnabledWithNoWebContentsLogsRetryMechanism) {
+  feature_list.InitAndEnableFeature(
+      safe_browsing::kTailoredSecurityObserverRetries);
+
+  for (TabModel* tab : TabModelList::models()) {
+    TabModelList::RemoveTabModel(tab);
+  }
+
+  EXPECT_EQ(TabModelList::models().size(), 0U);
+
+  chrome_tailored_security_service_->OnSyncNotificationMessageRequest(
+      kTailoredSecurityEnabled);
+  histograms_.ExpectUniqueSample(
+      "SafeBrowsing.TailoredSecurity.IsRecoveryTriggered", true, 1);
+}
+
+TEST_F(ChromeTailoredSecurityServiceTest,
+       RetryEnabledWithWebContentsDoesNotLogRetryMechanism) {
+  feature_list.InitAndEnableFeature(
+      safe_browsing::kTailoredSecurityObserverRetries);
+
+  TestTabModel tab_model(getProfile());
+  TabModelList::AddTabModel(&tab_model);
+
+  std::unique_ptr<content::WebContents> web_contents(
+      content::WebContentsTester::CreateTestWebContents(getProfile(), nullptr));
+  content::WebContents* raw_contents = web_contents.get();
+  tab_model.SetWebContents(raw_contents);
+  tab_model.tab_count_ = 1;
+
+  chrome_tailored_security_service_->OnSyncNotificationMessageRequest(
+      kTailoredSecurityEnabled);
+  histograms_.ExpectUniqueSample(
+      "SafeBrowsing.TailoredSecurity.IsRecoveryTriggered", false, 1);
+}
+
 }  // namespace
diff --git a/chrome/browser/safe_browsing/tailored_security/consented_message_android.cc b/chrome/browser/safe_browsing/tailored_security/consented_message_android.cc
index 44af6e34..488d6c3 100644
--- a/chrome/browser/safe_browsing/tailored_security/consented_message_android.cc
+++ b/chrome/browser/safe_browsing/tailored_security/consented_message_android.cc
@@ -5,12 +5,15 @@
 #include "chrome/browser/safe_browsing/tailored_security/consented_message_android.h"
 
 #include "base/metrics/histogram_functions.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "chrome/browser/android/android_theme_resources.h"
 #include "chrome/browser/android/resource_mapper.h"
 #include "chrome/browser/safe_browsing/android/safe_browsing_settings_launcher_android.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/messages/android/message_dispatcher_bridge.h"
 #include "components/safe_browsing/core/browser/tailored_security_service/tailored_security_outcome.h"
+#include "components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -73,6 +76,13 @@
       &TailoredSecurityConsentedModalAndroid::HandleSettingsClicked,
       base::Unretained(this)));
 
+  if (is_enable_message_) {
+    base::RecordAction(base::UserMetricsAction(
+        safe_browsing::kTailoredSecurityEnabledDialogShown));
+  } else {
+    base::RecordAction(base::UserMetricsAction(
+        safe_browsing::kTailoredSecurityDisabledDialogShown));
+  }
   messages::MessageDispatcherBridge::Get()->EnqueueWindowScopedMessage(
       message_.get(), web_contents_->GetTopLevelNativeWindow(),
       messages::MessagePriority::kNormal);
@@ -95,12 +105,26 @@
 void TailoredSecurityConsentedModalAndroid::HandleSettingsClicked() {
   ShowSafeBrowsingSettings(web_contents_,
                            SettingsAccessPoint::kTailoredSecurity);
+  if (is_enable_message_) {
+    base::RecordAction(base::UserMetricsAction(
+        safe_browsing::kTailoredSecurityEnabledDialogSettingsButtonClicked));
+  } else {
+    base::RecordAction(base::UserMetricsAction(
+        safe_browsing::kTailoredSecurityDisabledDialogSettingsButtonClicked));
+  }
   LogOutcome(TailoredSecurityOutcome::kSettings, is_enable_message_);
   DismissMessageInternal(messages::DismissReason::SECONDARY_ACTION);
 }
 
 void TailoredSecurityConsentedModalAndroid::HandleMessageDismissed(
     messages::DismissReason dismiss_reason) {
+  if (is_enable_message_) {
+    base::RecordAction(base::UserMetricsAction(
+        safe_browsing::kTailoredSecurityEnabledDialogDismissed));
+  } else {
+    base::RecordAction(base::UserMetricsAction(
+        safe_browsing::kTailoredSecurityDisabledDialogDismissed));
+  }
   LogOutcome(TailoredSecurityOutcome::kDismissed, is_enable_message_);
   message_.reset();
   if (dismiss_callback_)
@@ -108,6 +132,13 @@
 }
 
 void TailoredSecurityConsentedModalAndroid::HandleMessageAccepted() {
+  if (is_enable_message_) {
+    base::RecordAction(base::UserMetricsAction(
+        safe_browsing::kTailoredSecurityEnabledDialogOkButtonClicked));
+  } else {
+    base::RecordAction(base::UserMetricsAction(
+        safe_browsing::kTailoredSecurityDisabledDialogOkButtonClicked));
+  }
   LogOutcome(TailoredSecurityOutcome::kAccepted, is_enable_message_);
 }
 
diff --git a/chrome/browser/safe_browsing/tailored_security/consented_message_android.h b/chrome/browser/safe_browsing/tailored_security/consented_message_android.h
index c5c3210..88c0d82 100644
--- a/chrome/browser/safe_browsing/tailored_security/consented_message_android.h
+++ b/chrome/browser/safe_browsing/tailored_security/consented_message_android.h
@@ -27,6 +27,7 @@
   ~TailoredSecurityConsentedModalAndroid();
 
  private:
+  friend class TailoredSecurityConsentedModalAndroidTest;
   void DismissMessageInternal(messages::DismissReason dismiss_reason);
   void HandleSettingsClicked();
   void HandleMessageAccepted();
diff --git a/chrome/browser/safe_browsing/tailored_security/consented_message_android_unittest.cc b/chrome/browser/safe_browsing/tailored_security/consented_message_android_unittest.cc
new file mode 100644
index 0000000..3af15b2
--- /dev/null
+++ b/chrome/browser/safe_browsing/tailored_security/consented_message_android_unittest.cc
@@ -0,0 +1,134 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/safe_browsing/tailored_security/consented_message_android.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/metrics/user_action_tester.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/messages/android/mock_message_dispatcher_bridge.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace safe_browsing {
+class TailoredSecurityConsentedModalAndroidTest : public testing::Test {
+ protected:
+  TailoredSecurityConsentedModalAndroidTest() {
+    messages::MessageDispatcherBridge::SetInstanceForTesting(
+        &message_dispatcher_bridge_);
+    web_contents_ = content::WebContentsTester::CreateTestWebContents(
+        GetProfile(), nullptr);
+  }
+
+  TestingProfile* GetProfile() { return &profile_; }
+
+  void DoMessageAccepted(TailoredSecurityConsentedModalAndroid* modal) {
+    modal->HandleMessageAccepted();
+  }
+
+  void DoMessageDismissed(TailoredSecurityConsentedModalAndroid* modal,
+                          messages::DismissReason dismiss_reason) {
+    modal->HandleMessageDismissed(dismiss_reason);
+  }
+
+  void DoSettingsClicked(TailoredSecurityConsentedModalAndroid* modal) {
+    modal->HandleSettingsClicked();
+  }
+
+  content::BrowserTaskEnvironment task_environment_;
+  raw_ptr<TestingBrowserProcess> browser_process_;
+  TestingProfile profile_;
+  messages::MockMessageDispatcherBridge message_dispatcher_bridge_;
+  base::UserActionTester user_action_tester_;
+  std::unique_ptr<content::WebContents> web_contents_;
+};
+
+TEST_F(TailoredSecurityConsentedModalAndroidTest,
+       DisabledDialogHandleMessageAcceptedLogsUserAction) {
+  TailoredSecurityConsentedModalAndroid consented_modal(
+      web_contents_.get(), /*enabled=*/false, base::DoNothing());
+  DoMessageAccepted(&consented_modal);
+  EXPECT_EQ(
+      user_action_tester_.GetActionCount(
+          "SafeBrowsing.AccountIntegration.DisabledDialog.OkButtonClicked"),
+      1);
+}
+
+TEST_F(TailoredSecurityConsentedModalAndroidTest,
+       DisabledDialogHandleMessageDismissedLogsUserAction) {
+  TailoredSecurityConsentedModalAndroid consented_modal(
+      web_contents_.get(), /*enabled=*/false, base::DoNothing());
+  DoMessageDismissed(&consented_modal, messages::DismissReason::TIMER);
+  EXPECT_EQ(user_action_tester_.GetActionCount(
+                "SafeBrowsing.AccountIntegration.DisabledDialog.Dismissed"),
+            1);
+}
+
+TEST_F(TailoredSecurityConsentedModalAndroidTest,
+       DisabledDialogHandleSettingsClickedLogsUserAction) {
+  TailoredSecurityConsentedModalAndroid consented_modal(
+      web_contents_.get(), /*enabled=*/false, base::DoNothing());
+  DoSettingsClicked(&consented_modal);
+  EXPECT_EQ(user_action_tester_.GetActionCount(
+                "SafeBrowsing.AccountIntegration.DisabledDialog."
+                "SettingsButtonClicked"),
+            1);
+}
+
+TEST_F(TailoredSecurityConsentedModalAndroidTest,
+       DisabledDialogLogsUserActionWhenShown) {
+  auto web_contents =
+      content::WebContentsTester::CreateTestWebContents(GetProfile(), nullptr);
+
+  TailoredSecurityConsentedModalAndroid consented_modal(
+      web_contents.get(), /*enabled=*/false, base::DoNothing());
+  EXPECT_EQ(user_action_tester_.GetActionCount(
+                "SafeBrowsing.AccountIntegration.DisabledDialog.Shown"),
+            1);
+}
+
+TEST_F(TailoredSecurityConsentedModalAndroidTest,
+       EnabledDialogHandleMessageAcceptedLogsUserAction) {
+  TailoredSecurityConsentedModalAndroid consented_modal(
+      web_contents_.get(), /*enabled=*/true, base::DoNothing());
+  DoMessageAccepted(&consented_modal);
+  EXPECT_EQ(
+      user_action_tester_.GetActionCount(
+          "SafeBrowsing.AccountIntegration.EnabledDialog.OkButtonClicked"),
+      1);
+}
+
+TEST_F(TailoredSecurityConsentedModalAndroidTest,
+       EnabledDialogHandleMessageDismissedLogsUserAction) {
+  TailoredSecurityConsentedModalAndroid consented_modal(
+      web_contents_.get(), /*enabled=*/true, base::DoNothing());
+  DoMessageDismissed(&consented_modal, messages::DismissReason::TIMER);
+  EXPECT_EQ(user_action_tester_.GetActionCount(
+                "SafeBrowsing.AccountIntegration.EnabledDialog.Dismissed"),
+            1);
+}
+
+TEST_F(TailoredSecurityConsentedModalAndroidTest,
+       EnabledDialogHandleSettingsClickedLogsUserAction) {
+  TailoredSecurityConsentedModalAndroid consented_modal(
+      web_contents_.get(), /*enabled=*/true, base::DoNothing());
+  DoSettingsClicked(&consented_modal);
+  EXPECT_EQ(
+      user_action_tester_.GetActionCount("SafeBrowsing.AccountIntegration."
+                                         "EnabledDialog.SettingsButtonClicked"),
+      1);
+}
+
+TEST_F(TailoredSecurityConsentedModalAndroidTest,
+       EnabledDialogLogsUserActionWhenShown) {
+  TailoredSecurityConsentedModalAndroid consented_modal(
+      web_contents_.get(), /*enabled=*/true, base::DoNothing());
+  EXPECT_EQ(user_action_tester_.GetActionCount(
+                "SafeBrowsing.AccountIntegration.EnabledDialog.Shown"),
+            1);
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java
index 150b2e6..351c877 100644
--- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java
@@ -13,9 +13,6 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.net.Uri;
@@ -37,18 +34,16 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import org.chromium.base.BuildInfo;
 import org.chromium.base.Callback;
-import org.chromium.base.ContextUtils;
 import org.chromium.base.test.BaseActivityTestRule;
 import org.chromium.base.test.util.Batch;
-import org.chromium.base.test.util.PackageManagerWrapper;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.share.ChromeShareExtras.DetailedContentType;
 import org.chromium.chrome.browser.share.ShareContentTypeHelper.ContentType;
+import org.chromium.chrome.test.AutomotiveContextWrapperTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.components.browser_ui.share.ShareParams;
@@ -76,6 +71,8 @@
 
     @Rule
     public TestRule mFeaturesProcessor = new Features.JUnitProcessor();
+    @Rule
+    public AutomotiveContextWrapperTestRule mAutoTestRule = new AutomotiveContextWrapperTestRule();
 
     @Mock
     private Profile mProfile;
@@ -95,34 +92,6 @@
     private ShareParams mShareParams;
     private ShareSheetBottomSheetContent mShareSheetBottomSheetContent;
 
-    private Context mContextToRestore;
-    private TestContext mTestContext;
-
-    private class TestContext extends ContextWrapper {
-        private boolean mIsAutomotive;
-
-        public TestContext(Context baseContext) {
-            super(baseContext);
-            mIsAutomotive = false;
-        }
-
-        public void setIsAutomotive(boolean isAutomotive) {
-            this.mIsAutomotive = isAutomotive;
-            TestThreadUtils.runOnUiThreadBlocking(BuildInfo::resetForTesting);
-        }
-
-        @Override
-        public PackageManager getPackageManager() {
-            return new PackageManagerWrapper(super.getPackageManager()) {
-                @Override
-                public boolean hasSystemFeature(String name) {
-                    if (PackageManager.FEATURE_AUTOMOTIVE.equals(name)) return mIsAutomotive;
-                    return super.hasSystemFeature(name);
-                }
-            };
-        }
-    }
-
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -130,10 +99,6 @@
         mActivityTestRule.launchActivity(null);
         mActivity = mActivityTestRule.getActivity();
 
-        mContextToRestore = ContextUtils.getApplicationContext();
-        mTestContext = new TestContext(mContextToRestore);
-        ContextUtils.initApplicationContextForTests(mTestContext);
-
         mPreviewUrl = UrlFormatter.formatUrlForDisplayOmitSchemeOmitTrivialSubdomains(sUrl);
         mShareParams = new ShareParams.Builder(/*window=*/null, sTitle, sUrl)
                                .setText(sText)
@@ -157,12 +122,6 @@
 
     @After
     public void tearDown() {
-        // DisableAnimationTestRule requires an initialized context to do proper teardown.
-        // This resets to the original context rather than nulling out.
-        if (mContextToRestore != null) {
-            ContextUtils.initApplicationContextForTests(mContextToRestore);
-        }
-        TestThreadUtils.runOnUiThreadBlocking(BuildInfo::resetForTesting);
         TrackerFactory.setTrackerForTests(null);
     }
 
@@ -378,6 +337,9 @@
     @Test
     @MediumTest
     public void createRecyclerViews_notAutomotive_thirdPartyOptionsVisible() {
+        // By default set the test to run in non-auto environment.
+        mAutoTestRule.setIsAutomotive(false);
+
         String fileContentType = "image/jpeg";
         ShareSheetBottomSheetContent shareSheetBottomSheetContent =
                 new ShareSheetBottomSheetContent(mActivity, new MockLargeIconBridge(), null,
@@ -408,7 +370,7 @@
     @Test
     @MediumTest
     public void createRecyclerViews_isAutomotive_thirdPartyOptionsHidden() {
-        mTestContext.setIsAutomotive(true);
+        mAutoTestRule.setIsAutomotive(true);
 
         String fileContentType = "image/jpeg";
         ShareSheetBottomSheetContent shareSheetBottomSheetContent =
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetTest.java
index 67e3b7e9..1a0af5d 100644
--- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetTest.java
@@ -33,6 +33,7 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.PackageManagerWrapper;
+import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -43,6 +44,7 @@
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetTestSupport;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
+import org.chromium.ui.test.util.DeviceRestriction;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -286,6 +288,8 @@
 
     @Test
     @SmallTest
+    // 3P share sheet is not supported on auto.
+    @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO)
     public void nothingFromDefaultRankingAvailable() {
         replaceRecentShareHistory(defaultTestHistory());
         replaceSystemApps(defaultTestSystemApps());
diff --git a/chrome/browser/ssl/https_upgrades_util.h b/chrome/browser/ssl/https_upgrades_util.h
index 2798513..8179213 100644
--- a/chrome/browser/ssl/https_upgrades_util.h
+++ b/chrome/browser/ssl/https_upgrades_util.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_SSL_HTTPS_UPGRADES_UTIL_H_
 #define CHROME_BROWSER_SSL_HTTPS_UPGRADES_UTIL_H_
 
+#include "base/memory/raw_ptr.h"
 #include "base/memory/stack_allocated.h"
 #include "base/values.h"
 #include "url/gurl.h"
@@ -45,7 +46,7 @@
   ~ScopedAllowHttpForHostnamesForTesting();
 
  private:
-  PrefService* prefs_;
+  raw_ptr<PrefService> prefs_;
 };
 
 #endif  // CHROME_BROWSER_SSL_HTTPS_UPGRADES_UTIL_H_
diff --git a/chrome/browser/supervised_user/supervised_user_extension_unittest.cc b/chrome/browser/supervised_user/supervised_user_extension_unittest.cc
index fa571d8..de6b8ec8 100644
--- a/chrome/browser/supervised_user/supervised_user_extension_unittest.cc
+++ b/chrome/browser/supervised_user/supervised_user_extension_unittest.cc
@@ -38,13 +38,8 @@
 
  protected:
   void InitServices(bool profile_is_supervised) {
-    ExtensionServiceInitParams params = CreateDefaultInitParams();
+    ExtensionServiceInitParams params;
     params.profile_is_supervised = profile_is_supervised;
-    // If profile is supervised, don't pass a pref file such that the testing
-    // profile creates a pref service that uses SupervisedUserPrefStore.
-    if (profile_is_supervised) {
-      params.pref_file = base::FilePath();
-    }
     InitializeExtensionService(params);
 
     supervised_user_service()->Init();
diff --git a/chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.cc b/chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.cc
index d6c4a74..e65a5ef6 100644
--- a/chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.cc
+++ b/chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.cc
@@ -48,44 +48,41 @@
 
 namespace extensions {
 
-SupervisedUserExtensionsDelegateImpl::SupervisedUserExtensionsDelegateImpl() =
-    default;
+SupervisedUserExtensionsDelegateImpl::SupervisedUserExtensionsDelegateImpl(
+    content::BrowserContext* context)
+    : context_(context) {
+  CHECK(context_);
+}
 
 SupervisedUserExtensionsDelegateImpl::~SupervisedUserExtensionsDelegateImpl() =
     default;
 
-bool SupervisedUserExtensionsDelegateImpl::IsChild(
-    content::BrowserContext* context) const {
-  SupervisedUserService* supervised_user_service =
-      SupervisedUserServiceFactory::GetForBrowserContext(context);
-  return supervised_user_service->AreExtensionsPermissionsEnabled();
+bool SupervisedUserExtensionsDelegateImpl::IsChild() const {
+  return SupervisedUserServiceFactory::GetForBrowserContext(context_)
+      ->AreExtensionsPermissionsEnabled();
 }
 
 bool SupervisedUserExtensionsDelegateImpl::IsExtensionAllowedByParent(
-    const extensions::Extension& extension,
-    content::BrowserContext* context) const {
-  SupervisedUserService* supervised_user_service =
-      SupervisedUserServiceFactory::GetForBrowserContext(context);
-  return supervised_user_service->IsExtensionAllowed(extension);
+    const extensions::Extension& extension) const {
+  return SupervisedUserServiceFactory::GetForBrowserContext(context_)
+      ->IsExtensionAllowed(extension);
 }
 
 void SupervisedUserExtensionsDelegateImpl::RequestToAddExtensionOrShowError(
     const extensions::Extension& extension,
-    content::BrowserContext* browser_context,
     content::WebContents* web_contents,
     const gfx::ImageSkia& icon,
     ExtensionApprovalDoneCallback extension_approval_callback) {
-  DCHECK(IsChild(browser_context));
-  DCHECK(!IsExtensionAllowedByParent(extension, browser_context));
+  DCHECK(IsChild());
+  DCHECK(!IsExtensionAllowedByParent(extension));
 
   done_callback_ = std::move(extension_approval_callback);
 
   // Supervised users who can install extensions still need parent permission
   // for installation. If the user isn't allowed to install extensions at all,
   // then we will just show a "blocked" dialog.
-  if (CanInstallExtensions(browser_context)) {
-    ShowParentPermissionDialogForExtension(extension, browser_context,
-                                           web_contents, icon);
+  if (CanInstallExtensions()) {
+    ShowParentPermissionDialogForExtension(extension, web_contents, icon);
     return;
   }
 
@@ -96,24 +93,22 @@
 
 void SupervisedUserExtensionsDelegateImpl::RequestToEnableExtensionOrShowError(
     const extensions::Extension& extension,
-    content::BrowserContext* browser_context,
     content::WebContents* web_contents,
     ExtensionApprovalDoneCallback extension_approval_callback) {
-  DCHECK(IsChild(browser_context));
-  DCHECK(!IsExtensionAllowedByParent(extension, browser_context));
+  DCHECK(IsChild());
+  DCHECK(!IsExtensionAllowedByParent(extension));
 
   done_callback_ = std::move(extension_approval_callback);
 
   // Supervised users who can install extensions still require parent permission
   // for installation or enablement. If the user isn't allowed to install
   // extensions at all, then we will just show a "blocked" dialog.
-  if (CanInstallExtensions(browser_context)) {
+  if (CanInstallExtensions()) {
     auto icon_callback = base::BindOnce(
         &SupervisedUserExtensionsDelegateImpl::OnExtensionDataLoaded,
-        base::Unretained(this), std::cref(extension), browser_context,
-        web_contents);
+        base::Unretained(this), std::cref(extension), web_contents);
     icon_loader_ = std::make_unique<ExtensionIconLoader>();
-    icon_loader_->Load(extension, browser_context, std::move(icon_callback));
+    icon_loader_->Load(extension, context_, std::move(icon_callback));
     return;
   }
 
@@ -122,17 +117,14 @@
       ExtensionInstalledBlockedByParentDialogAction::kEnable);
 }
 
-bool SupervisedUserExtensionsDelegateImpl::CanInstallExtensions(
-    content::BrowserContext* context) const {
-  SupervisedUserService* supervised_user_service =
-      SupervisedUserServiceFactory::GetForBrowserContext(context);
-  return supervised_user_service->CanInstallExtensions();
+bool SupervisedUserExtensionsDelegateImpl::CanInstallExtensions() const {
+  return SupervisedUserServiceFactory::GetForBrowserContext(context_)
+      ->CanInstallExtensions();
 }
 
 void SupervisedUserExtensionsDelegateImpl::
     ShowParentPermissionDialogForExtension(
         const extensions::Extension& extension,
-        content::BrowserContext* context,
         content::WebContents* contents,
         const gfx::ImageSkia& icon) {
   ParentPermissionDialog::DoneCallback inner_done_callback = base::BindOnce(
@@ -142,8 +134,8 @@
       contents ? contents->GetTopLevelNativeWindow() : nullptr;
   parent_permission_dialog_ =
       ParentPermissionDialog::CreateParentPermissionDialogForExtension(
-          Profile::FromBrowserContext(context), parent_window, icon, &extension,
-          std::move(inner_done_callback));
+          Profile::FromBrowserContext(context_), parent_window, icon,
+          &extension, std::move(inner_done_callback));
   parent_permission_dialog_->ShowDialog();
 }
 
@@ -170,10 +162,9 @@
 
 void SupervisedUserExtensionsDelegateImpl::OnExtensionDataLoaded(
     const extensions::Extension& extension,
-    content::BrowserContext* context,
     content::WebContents* contents,
     const gfx::ImageSkia& icon) {
-  ShowParentPermissionDialogForExtension(extension, context, contents, icon);
+  ShowParentPermissionDialogForExtension(extension, contents, icon);
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.h b/chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.h
index 0ee89fa9..d5960149 100644
--- a/chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.h
+++ b/chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/memory/raw_ptr.h"
 #include "extensions/browser/supervised_user_extensions_delegate.h"
 
 namespace content {
@@ -28,36 +29,33 @@
 class SupervisedUserExtensionsDelegateImpl
     : public extensions::SupervisedUserExtensionsDelegate {
  public:
-  SupervisedUserExtensionsDelegateImpl();
+  explicit SupervisedUserExtensionsDelegateImpl(
+      content::BrowserContext* browser_context);
   ~SupervisedUserExtensionsDelegateImpl() override;
 
   // extensions::SupervisedUserExtensionsDelegate overrides
-  bool IsChild(content::BrowserContext* context) const override;
+  bool IsChild() const override;
   bool IsExtensionAllowedByParent(
-      const extensions::Extension& extension,
-      content::BrowserContext* context) const override;
+      const extensions::Extension& extension) const override;
   void RequestToAddExtensionOrShowError(
       const extensions::Extension& extension,
-      content::BrowserContext* browser_context,
       content::WebContents* web_contents,
       const gfx::ImageSkia& icon,
       ExtensionApprovalDoneCallback extension_approval_callback) override;
   void RequestToEnableExtensionOrShowError(
       const extensions::Extension& extension,
-      content::BrowserContext* browser_context,
       content::WebContents* web_contents,
       ExtensionApprovalDoneCallback extension_approval_callback) override;
 
  private:
-  // Returns true if |context| represents a supervised child account who may
+  // Returns true if |context_| represents a supervised child account who may
   // install extensions with parent permission.
-  bool CanInstallExtensions(content::BrowserContext* context) const;
+  bool CanInstallExtensions() const;
 
   // Shows a parent permission dialog for |extension| and call |done_callback|
   // when it completes.
   void ShowParentPermissionDialogForExtension(
       const extensions::Extension& extension,
-      content::BrowserContext* context,
       content::WebContents* contents,
       const gfx::ImageSkia& icon);
   // Shows a dialog indicating that |extension| has been blocked and call
@@ -69,7 +67,6 @@
       ExtensionInstalledBlockedByParentDialogAction blocked_action);
 
   void OnExtensionDataLoaded(const extensions::Extension& extension,
-                             content::BrowserContext* context,
                              content::WebContents* contents,
                              const gfx::ImageSkia& icon);
 
@@ -83,6 +80,7 @@
       done_callback_;
 
   std::unique_ptr<ExtensionIconLoader> icon_loader_;
+  const raw_ptr<content::BrowserContext> context_;
 };
 
 }  // namespace extensions
diff --git a/chrome/browser/supervised_user/supervised_user_service_unittest.cc b/chrome/browser/supervised_user/supervised_user_service_unittest.cc
index 5f67d73..f6ed1c2 100644
--- a/chrome/browser/supervised_user/supervised_user_service_unittest.cc
+++ b/chrome/browser/supervised_user/supervised_user_service_unittest.cc
@@ -244,8 +244,7 @@
 
   void SetUp() override {
     ExtensionServiceTestBase::SetUp();
-    ExtensionServiceTestBase::ExtensionServiceInitParams params =
-        CreateDefaultInitParams();
+    ExtensionServiceInitParams params;
     params.profile_is_supervised = is_supervised_;
     InitializeExtensionService(params);
     // Flush the message loop, to ensure that credentials have been loaded in
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 089c1790..da225fcf 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -133,6 +133,11 @@
 #endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) ||
         // BUILDFLAG(IS_WIN)
 
+#if !BUILDFLAG(IS_ANDROID)
+#include "chrome/browser/webauthn/passkey_model_factory.h"
+#include "components/webauthn/core/browser/passkey_model.h"
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/components/arc/arc_util.h"
 #include "ash/constants/ash_features.h"
@@ -707,6 +712,13 @@
           ->GetControllerDelegate();
     }
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+#if !BUILDFLAG(IS_ANDROID)
+    case syncer::WEBAUTHN_CREDENTIAL: {
+      DCHECK(base::FeatureList::IsEnabled(syncer::kSyncWebauthnCredentials));
+      return PasskeyModelFactory::GetForProfile(profile_)
+          ->GetModelTypeControllerDelegate();
+    }
+#endif  //  !BUILDFLAG(IS_ANDROID)
     // We don't exercise this function for certain datatypes, because their
     // controllers get the delegate elsewhere.
     case syncer::AUTOFILL:
diff --git a/chrome/browser/sync/sync_service_factory.cc b/chrome/browser/sync/sync_service_factory.cc
index 17022fee..2f53334 100644
--- a/chrome/browser/sync/sync_service_factory.cc
+++ b/chrome/browser/sync/sync_service_factory.cc
@@ -80,6 +80,10 @@
 #endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) ||
         // BUILDFLAG(IS_WIN)
 
+#if !BUILDFLAG(IS_ANDROID)
+#include "chrome/browser/webauthn/passkey_model_factory.h"
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 namespace {
 
 std::unique_ptr<KeyedService> BuildSyncService(
@@ -235,6 +239,9 @@
   DependsOn(HistoryServiceFactory::GetInstance());
   DependsOn(IdentityManagerFactory::GetInstance());
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
+#if !BUILDFLAG(IS_ANDROID)
+  DependsOn(PasskeyModelFactory::GetInstance());
+#endif  // !BUILDFLAG(IS_ANDROID)
   DependsOn(PasswordStoreFactory::GetInstance());
   DependsOn(PowerBookmarkServiceFactory::GetInstance());
   DependsOn(SecurityEventRecorderFactory::GetInstance());
diff --git a/chrome/browser/sync/sync_service_factory_unittest.cc b/chrome/browser/sync/sync_service_factory_unittest.cc
index 2fd507c..4da141c 100644
--- a/chrome/browser/sync/sync_service_factory_unittest.cc
+++ b/chrome/browser/sync/sync_service_factory_unittest.cc
@@ -171,6 +171,9 @@
     datatypes.Put(syncer::USER_CONSENTS);
     datatypes.Put(syncer::SEND_TAB_TO_SELF);
     datatypes.Put(syncer::SHARING_MESSAGE);
+    if (base::FeatureList::IsEnabled(syncer::kSyncWebauthnCredentials)) {
+      datatypes.Put(syncer::WEBAUTHN_CREDENTIAL);
+    }
     return datatypes;
   }
 
diff --git a/chrome/browser/sync/test/integration/apps_helper.cc b/chrome/browser/sync/test/integration/apps_helper.cc
index 3ef5677..1e53c7c 100644
--- a/chrome/browser/sync/test/integration/apps_helper.cc
+++ b/chrome/browser/sync/test/integration/apps_helper.cc
@@ -49,17 +49,10 @@
 
     // First, wait for all installations to complete.
 
-    std::set<web_app::AppId> apps_to_be_installed =
-        web_app::WebAppProvider::GetForTest(profile)
-            ->install_manager()
-            .GetEnqueuedInstallAppIdsForTesting();
-
-    std::vector<web_app::AppId> apps_to_be_sync_installed =
+    base::flat_set<web_app::AppId> apps_to_be_installed =
         web_app::WebAppProvider::GetForTest(profile)
             ->registrar_unsafe()
             .GetAppsFromSyncAndPendingInstallation();
-    apps_to_be_installed.insert(apps_to_be_sync_installed.begin(),
-                                apps_to_be_sync_installed.end());
 
     if (!apps_to_be_installed.empty()) {
       // Because we don't know whether these have been installed yet or if we
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc b/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
index 6c83d9c..ed9d92c 100644
--- a/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
 #include "chrome/browser/web_applications/test/web_app_test_utils.h"
 #include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
@@ -592,6 +593,13 @@
   // Propagate any possible re-installs back to profile 0.
   AwaitQuiescence();
 
+  WebAppProvider::GetForTest(GetProfile(0))
+      ->command_manager()
+      .AwaitAllCommandsCompleteForTesting();
+  WebAppProvider::GetForTest(GetProfile(1))
+      ->command_manager()
+      .AwaitAllCommandsCompleteForTesting();
+
   // No apps pending install.
   EXPECT_TRUE(GetRegistrar(GetProfile(0))
                   .GetAppsFromSyncAndPendingInstallation()
@@ -614,14 +622,14 @@
             0);
 
   // No pending installs tasks.
-  EXPECT_TRUE(WebAppProvider::GetForTest(GetProfile(1))
-                  ->install_manager()
-                  .GetEnqueuedInstallAppIdsForTesting()
-                  .empty());
-  EXPECT_TRUE(WebAppProvider::GetForTest(GetProfile(0))
-                  ->install_manager()
-                  .GetEnqueuedInstallAppIdsForTesting()
-                  .empty());
+  EXPECT_EQ(WebAppProvider::GetForTest(GetProfile(1))
+                ->command_manager()
+                .GetCommandCountForTesting(),
+            0ul);
+  EXPECT_EQ(WebAppProvider::GetForTest(GetProfile(0))
+                ->command_manager()
+                .GetCommandCountForTesting(),
+            0ul);
 }
 
 IN_PROC_BROWSER_TEST_F(TwoClientWebAppsBMOSyncTest, NoShortcutsCreatedOnSync) {
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc
index 04fe402..6b163568e 100644
--- a/chrome/browser/themes/theme_service_unittest.cc
+++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -135,10 +135,7 @@
 
   void SetUp() override {
     extensions::ExtensionServiceTestBase::SetUp();
-    extensions::ExtensionServiceTestBase::ExtensionServiceInitParams params =
-        CreateDefaultInitParams();
-    params.pref_file = base::FilePath();
-    InitializeExtensionService(params);
+    InitializeExtensionService(ExtensionServiceInitParams());
     service_->Init();
     registry_ = extensions::ExtensionRegistry::Get(profile());
     ASSERT_TRUE(registry_);
diff --git a/chrome/browser/tracing/chrome_tracing_delegate.cc b/chrome/browser/tracing/chrome_tracing_delegate.cc
index e39d259..da177fd 100644
--- a/chrome/browser/tracing/chrome_tracing_delegate.cc
+++ b/chrome/browser/tracing/chrome_tracing_delegate.cc
@@ -149,11 +149,10 @@
 }
 #endif  // BUILDFLAG(IS_ANDROID)
 
-bool ChromeTracingDelegate::IsActionAllowed(
-    BackgroundScenarioAction action,
-    const content::BackgroundTracingConfig& config,
-    bool requires_anonymized_data,
-    bool ignore_trace_limit) const {
+bool ChromeTracingDelegate::IsActionAllowed(BackgroundScenarioAction action,
+                                            const std::string& scenario_name,
+                                            bool requires_anonymized_data,
+                                            bool ignore_trace_limit) const {
   // If the background tracing is specified on the command-line, we allow
   // any scenario to be traced and uploaded.
   if (IsBackgroundTracingCommandLine())
@@ -180,7 +179,8 @@
 
   // Check the trace limit for both kStartTracing and kUploadTrace actions
   // because there is no point starting a trace that can't be uploaded.
-  if (!ignore_trace_limit && state.DidRecentlyUploadForScenario(config)) {
+  if (!ignore_trace_limit &&
+      state.DidRecentlyUploadForScenario(scenario_name)) {
     tracing::RecordDisallowedMetric(
         tracing::TracingFinalizationDisallowedReason::kTraceUploadedRecently);
     return false;
@@ -190,8 +190,9 @@
 }
 
 bool ChromeTracingDelegate::IsAllowedToBeginBackgroundScenario(
-    const content::BackgroundTracingConfig& config,
-    bool requires_anonymized_data) {
+    const std::string& scenario_name,
+    bool requires_anonymized_data,
+    bool is_crash_scenario) {
   // We call Initialize() only when a tracing scenario tries to start, and
   // unless this happens we never save state. In particular, if the background
   // tracing experiment is disabled, Initialize() will never be called, and we
@@ -209,9 +210,9 @@
   // If the config includes a crash scenario, ignore the trace limit so that a
   // trace can be taken on crash. We check if the trigger is actually due to a
   // crash later before uploading.
-  const bool ignore_trace_limit = config.has_crash_scenario();
+  const bool ignore_trace_limit = is_crash_scenario;
 
-  if (!IsActionAllowed(BackgroundScenarioAction::kStartTracing, config,
+  if (!IsActionAllowed(BackgroundScenarioAction::kStartTracing, scenario_name,
                        requires_anonymized_data, ignore_trace_limit)) {
     return false;
   }
@@ -221,7 +222,7 @@
 }
 
 bool ChromeTracingDelegate::IsAllowedToEndBackgroundScenario(
-    const content::BackgroundTracingConfig& config,
+    const std::string& scenario_name,
     bool requires_anonymized_data,
     bool is_crash_scenario) {
   BackgroundTracingStateManager& state =
@@ -232,12 +233,12 @@
   // uploading.
   const bool ignore_trace_limit = is_crash_scenario;
 
-  if (!IsActionAllowed(BackgroundScenarioAction::kUploadTrace, config,
+  if (!IsActionAllowed(BackgroundScenarioAction::kUploadTrace, scenario_name,
                        requires_anonymized_data, ignore_trace_limit)) {
     return false;
   }
 
-  state.OnScenarioUploaded(config.scenario_name());
+  state.OnScenarioUploaded(scenario_name);
   return true;
 }
 
diff --git a/chrome/browser/tracing/chrome_tracing_delegate.h b/chrome/browser/tracing/chrome_tracing_delegate.h
index 9555ef2..347ecf9c 100644
--- a/chrome/browser/tracing/chrome_tracing_delegate.h
+++ b/chrome/browser/tracing/chrome_tracing_delegate.h
@@ -39,17 +39,16 @@
   // before tracing is started. If this returns true, a tasks is posted 30
   // seconds into the future that will mark a successful startup / run of a
   // trace and will allow tracing to run next time.
-  bool IsAllowedToBeginBackgroundScenario(
-      const content::BackgroundTracingConfig& config,
-      bool requires_anonymized_data) override;
+  bool IsAllowedToBeginBackgroundScenario(const std::string& scenario_name,
+                                          bool requires_anonymized_data,
+                                          bool is_crash_scenario) override;
 
   // Returns true if tracing is allowed to end. Also updates the background
   // tracing state in prefs using BackgroundTracingStateManager when returning
   // true. This is required to be called before stopping background tracing.
-  bool IsAllowedToEndBackgroundScenario(
-      const content::BackgroundTracingConfig& config,
-      bool requires_anonymized_data,
-      bool is_crash_scenario) override;
+  bool IsAllowedToEndBackgroundScenario(const std::string& scenario_name,
+                                        bool requires_anonymized_data,
+                                        bool is_crash_scenario) override;
 
   bool IsSystemWideTracingEnabled() override;
 
@@ -91,7 +90,7 @@
   // Returns true if the delegate should be allowed to perform `action` for the
   // scenario described in `config`.
   bool IsActionAllowed(BackgroundScenarioAction action,
-                       const content::BackgroundTracingConfig& config,
+                       const std::string& scenario_name,
                        bool requires_anonymized_data,
                        bool ignore_trace_limit) const;
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index d985a34..1674795 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1239,6 +1239,8 @@
       "performance_controls/high_efficiency_bubble_delegate.cc",
       "performance_controls/high_efficiency_bubble_delegate.h",
       "performance_controls/high_efficiency_bubble_observer.h",
+      "performance_controls/high_efficiency_chip_tab_helper.cc",
+      "performance_controls/high_efficiency_chip_tab_helper.h",
       "performance_controls/high_efficiency_opt_in_iph_controller.cc",
       "performance_controls/high_efficiency_opt_in_iph_controller.h",
       "performance_controls/performance_controls_hats_service.cc",
@@ -1247,8 +1249,6 @@
       "performance_controls/performance_controls_hats_service_factory.h",
       "performance_controls/performance_controls_metrics.cc",
       "performance_controls/performance_controls_metrics.h",
-      "performance_controls/tab_discard_tab_helper.cc",
-      "performance_controls/tab_discard_tab_helper.h",
       "permission_bubble/permission_prompt.h",
       "privacy_sandbox/privacy_sandbox_prompt.cc",
       "privacy_sandbox/privacy_sandbox_prompt.h",
@@ -2229,6 +2229,8 @@
       "../ash/app_list/search/system_info/cpu_data.h",
       "../ash/app_list/search/system_info/cpu_usage_data.cc",
       "../ash/app_list/search/system_info/cpu_usage_data.h",
+      "../ash/app_list/search/system_info/memory_answer_result.cc",
+      "../ash/app_list/search/system_info/memory_answer_result.h",
       "../ash/app_list/search/system_info/system_info_answer_result.cc",
       "../ash/app_list/search/system_info/system_info_answer_result.h",
       "../ash/app_list/search/system_info/system_info_card_provider.cc",
@@ -2362,6 +2364,8 @@
       "ash/global_media_controls/cast_media_notification_producer_keyed_service.h",
       "ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.cc",
       "ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.h",
+      "ash/global_media_controls/media_item_ui_device_selector_delegate_ash.cc",
+      "ash/global_media_controls/media_item_ui_device_selector_delegate_ash.h",
       "ash/global_media_controls/media_notification_provider_impl.cc",
       "ash/global_media_controls/media_notification_provider_impl.h",
       "ash/google_one_offer_iph_tab_helper.cc",
diff --git a/chrome/browser/ui/android/layouts/java/src/org/chromium/chrome/browser/layouts/LayoutStateProvider.java b/chrome/browser/ui/android/layouts/java/src/org/chromium/chrome/browser/layouts/LayoutStateProvider.java
index 47d7442..a4d417e 100644
--- a/chrome/browser/ui/android/layouts/java/src/org/chromium/chrome/browser/layouts/LayoutStateProvider.java
+++ b/chrome/browser/ui/android/layouts/java/src/org/chromium/chrome/browser/layouts/LayoutStateProvider.java
@@ -54,19 +54,28 @@
     }
 
     /**
-     * @return Whether or not the {@link Layout} is visible.
-     * @param layoutType whether the {@link Layout} give {@link LayoutType} is visible.
+     * Determines whether the layout for a specific type is visible.
+     * @return {@code true} if the {@link Layout} is visible, {@code false} otherwise.
+     * @param layoutType The {@link LayoutType} of the {@link Layout} that is visible.
      */
     boolean isLayoutVisible(@LayoutType int layoutType);
 
     /**
-     * @return Whether or not the {@link Layout} is starting to hide.
-     * @param layoutType whether the {@link Layout} give {@link LayoutType} is starting to hide.
+     * Determines whether a layout has started and is in the process of hiding.
+     * @return {@code true} if the {@link Layout} is starting to hide, {@code false} otherwise.
+     * @param layoutType The {@link LayoutType} of the {@link Layout} that is starting to hide.
      */
     boolean isLayoutStartingToHide(@LayoutType int layoutType);
 
     /**
-     * Get the type of the layout that is currently active.
+     * Determines whether a layout has started and is in the process of showing.
+     * @return {@code true} if the {@link Layout} is starting to show, {@code false} otherwise.
+     * @param layoutType The {@link LayoutType} of the {@link Layout} that is starting to show.
+     */
+    boolean isLayoutStartingToShow(@LayoutType int layoutType);
+
+    /**
+     * Gets the type of the layout that is currently active.
      * @return The {@link LayoutType} of the active layout.
      */
     @LayoutType
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
index 5f788276..a948c56 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
@@ -458,11 +458,21 @@
         updateButtonVisibility();
     }
 
+    @Override
+    public boolean shouldClearOmniboxOnFocus() {
+        return mLocationBarMediator.shouldClearOmniboxOnFocus();
+    }
+
     /** @see UrlBarCoordinator#getVisibleTextPrefixHint() */
     public CharSequence getOmniboxVisibleTextPrefixHint() {
         return mUrlCoordinator.getVisibleTextPrefixHint();
     }
 
+    /** @see UrlBarCoordinator#getTextWithoutAutocomplete() */
+    public String getUrlBarTextWithoutAutocomplete() {
+        return mUrlCoordinator.getTextWithoutAutocomplete();
+    }
+
     /**
      * Returns the {@link LocationBarCoordinatorPhone} for this coordinator.
      *
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
index 365f56c..829340b 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
@@ -199,6 +199,7 @@
     private @BrandedColorScheme int mBrandedColorScheme = BrandedColorScheme.APP_DEFAULT;
     private ObservableSupplierImpl<Boolean> mBackPressStateSupplier =
             new ObservableSupplierImpl<>();
+    private boolean mShouldClearOmniboxOnFocus = true;
 
     /*package */ LocationBarMediator(@NonNull Context context,
             @NonNull LocationBarLayout locationBarLayout,
@@ -664,6 +665,8 @@
         if (!mIsTablet && !showExpandedState) {
             mLocationBarLayout.setUrlActionContainerVisibility(View.GONE);
         }
+        // Reset to the default value.
+        mShouldClearOmniboxOnFocus = true;
     }
 
     /**
@@ -938,6 +941,10 @@
         mAutocompleteCoordinator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete);
     }
 
+    /* package */ boolean shouldClearOmniboxOnFocus() {
+        return mShouldClearOmniboxOnFocus;
+    }
+
     // Private methods
 
     private void setProfile(Profile profile) {
@@ -1299,6 +1306,8 @@
                 mUrlFocusedFromFakebox = true;
             }
 
+            mShouldClearOmniboxOnFocus = pastedText == null;
+
             if (urlHasFocus && mUrlFocusedWithoutAnimations) {
                 handleUrlFocusAnimation(true);
             } else {
@@ -1313,7 +1322,19 @@
             // This must be happen after requestUrlFocus(), which changes the selection.
             mUrlCoordinator.setUrlBarData(UrlBarData.forNonUrlText(pastedText),
                     UrlBar.ScrollType.NO_SCROLL, UrlBarCoordinator.SelectionState.SELECT_END);
-            forceOnTextChanged();
+            /*
+              When the URL bar text is programmatically set on omnibox state restoration during a
+              device fold transition, {@code AutocompleteEditText#getTextWithoutAutocomplete()}
+              invoked by {@code #forceOnTextChanged()} returns an empty string because {@code
+              AutocompleteEditText#mModel} is not initialized. To trigger the autocomplete system in
+              this case, {@code AutocompleteCoordinator#onTextChanged()} will be directly called on
+              the restored omnibox text input.
+             */
+            if (reason == OmniboxFocusReason.FOLD_TRANSITION_RESTORATION) {
+                mAutocompleteCoordinator.onTextChanged(pastedText, pastedText);
+            } else {
+                forceOnTextChanged();
+            }
         }
     }
 
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java
index a706534..ab1a02e7 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java
@@ -17,7 +17,8 @@
         OmniboxFocusReason.TASKS_SURFACE_FAKE_BOX_LONG_PRESS,
         OmniboxFocusReason.DEFAULT_WITH_HARDWARE_KEYBOARD, OmniboxFocusReason.SEARCH_QUERY,
         OmniboxFocusReason.LAUNCH_NEW_INCOGNITO_TAB, OmniboxFocusReason.MENU_OR_KEYBOARD_ACTION,
-        OmniboxFocusReason.UNFOCUS, OmniboxFocusReason.QUERY_TILES_NTP_TAP})
+        OmniboxFocusReason.UNFOCUS, OmniboxFocusReason.QUERY_TILES_NTP_TAP,
+        OmniboxFocusReason.FOLD_TRANSITION_RESTORATION})
 @Retention(RetentionPolicy.SOURCE)
 public @interface OmniboxFocusReason {
     int OMNIBOX_TAP = 0;
@@ -35,5 +36,6 @@
     int MENU_OR_KEYBOARD_ACTION = 11;
     int UNFOCUS = 12;
     int QUERY_TILES_NTP_TAP = 13;
+    int FOLD_TRANSITION_RESTORATION = 14;
     int NUM_ENTRIES = 15;
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java
index 43da3a1..37759e0 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java
@@ -14,4 +14,11 @@
      * @param text The text that should be displayed in the omnibox.
      */
     void setOmniboxEditingText(String text);
+
+    /**
+     * Returns {@code true} when the omnibox should be cleared on focus, {@code false} otherwise.
+     */
+    default boolean shouldClearOmniboxOnFocus() {
+        return true;
+    }
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
index 0a0165f..3cce772 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
@@ -82,7 +82,7 @@
             return false;
         }
 
-        if (!mHasClearedOmniboxForFocus) {
+        if (!mHasClearedOmniboxForFocus && mUrlBarDelegate.shouldClearOmniboxOnFocus()) {
             mHasClearedOmniboxForFocus = true;
             mUrlBarDelegate.setOmniboxEditingText("");
         }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
index 01c6f65..19962ee 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
@@ -30,9 +30,12 @@
 import org.chromium.base.TraceEvent;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.layouts.LayoutStateProvider;
+import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiThemeUtil;
 import org.chromium.chrome.browser.toolbar.ConstraintsChecker;
@@ -135,18 +138,21 @@
      * @param compositorInMotionSupplier Whether there is an ongoing touch or gesture.
      * @param browserStateBrowserControlsVisibilityDelegate Used to keep controls locked when
      *        captures are stale and not able to be taken.
+     * @param layoutStateProvider Used to check the current layout type.
      */
     public void setPostInitializationDependencies(Toolbar toolbar, boolean isIncognito,
             ObservableSupplier<Integer> constraintsSupplier, Supplier<Tab> tabSupplier,
             ObservableSupplier<Boolean> compositorInMotionSupplier,
             BrowserStateBrowserControlsVisibilityDelegate
-                    browserStateBrowserControlsVisibilityDelegate) {
+                    browserStateBrowserControlsVisibilityDelegate,
+            OneshotSupplier<LayoutStateProvider> layoutStateProviderSupplier) {
         mToolbar = toolbar;
 
         BooleanSupplier isVisible = () -> this.getVisibility() == View.VISIBLE;
         mToolbarContainer.setPostInitializationDependencies(mToolbar, constraintsSupplier,
                 tabSupplier, compositorInMotionSupplier,
-                browserStateBrowserControlsVisibilityDelegate, isVisible);
+                browserStateBrowserControlsVisibilityDelegate, isVisible,
+                layoutStateProviderSupplier);
 
         View toolbarView = findViewById(R.id.toolbar);
         assert toolbarView != null;
@@ -242,12 +248,13 @@
                 ObservableSupplier<Boolean> compositorInMotionSupplier,
                 BrowserStateBrowserControlsVisibilityDelegate
                         browserStateBrowserControlsVisibilityDelegate,
-                BooleanSupplier isVisible) {
+                BooleanSupplier isVisible,
+                OneshotSupplier<LayoutStateProvider> layoutStateProviderSupplier) {
             ToolbarViewResourceAdapter adapter =
                     ((ToolbarViewResourceAdapter) getResourceAdapter());
             adapter.setPostInitializationDependencies(toolbar, constraintsSupplier, tabSupplier,
                     compositorInMotionSupplier, browserStateBrowserControlsVisibilityDelegate,
-                    isVisible);
+                    isVisible, layoutStateProviderSupplier);
         }
 
         @Override
@@ -294,6 +301,8 @@
                 mBrowserStateBrowserControlsVisibilityDelegate;
         @Nullable
         private BooleanSupplier mControlContainerIsVisibleSupplier;
+        @Nullable
+        private LayoutStateProvider mLayoutStateProvider;
 
         private int mControlsToken = TokenHolder.INVALID_TOKEN;
 
@@ -312,13 +321,15 @@
          * @param browserStateBrowserControlsVisibilityDelegate Used to keep controls locked when
          *        captures are stale and not able to be taken.
          * @param controlContainerIsVisibleSupplier Whether the toolbar is visible.
+         * @param layoutStateProvider Used to check the current layout type.
          */
         public void setPostInitializationDependencies(Toolbar toolbar,
                 ObservableSupplier<Integer> constraintsSupplier, Supplier<Tab> tabSupplier,
                 ObservableSupplier<Boolean> compositorInMotionSupplier,
                 BrowserStateBrowserControlsVisibilityDelegate
                         browserStateBrowserControlsVisibilityDelegate,
-                BooleanSupplier controlContainerIsVisibleSupplier) {
+                BooleanSupplier controlContainerIsVisibleSupplier,
+                OneshotSupplier<LayoutStateProvider> layoutStateProviderSupplier) {
             assert mToolbar == null;
             mToolbar = toolbar;
             mTabStripHeightPx = mToolbar.getTabStripHeight();
@@ -335,6 +346,8 @@
             mBrowserStateBrowserControlsVisibilityDelegate =
                     browserStateBrowserControlsVisibilityDelegate;
             mControlContainerIsVisibleSupplier = controlContainerIsVisibleSupplier;
+            layoutStateProviderSupplier.onAvailable(
+                    (layoutStateProvider) -> mLayoutStateProvider = layoutStateProvider);
         }
 
         /**
@@ -353,7 +366,9 @@
                 return false;
             }
 
-            if (ToolbarFeatures.shouldSuppressCaptures()) {
+            final @LayoutType int layoutType = getCurrentLayoutType();
+            if (ToolbarFeatures.shouldSuppressCaptures()
+                    && layoutType != LayoutType.TOOLBAR_SWIPE) {
                 if (mConstraintsObserver != null && mTabSupplier != null) {
                     Tab tab = mTabSupplier.get();
 
@@ -498,6 +513,11 @@
                 }
             }
         }
+
+        private @LayoutType int getCurrentLayoutType() {
+            return mLayoutStateProvider == null ? LayoutType.NONE
+                                                : mLayoutStateProvider.getActiveLayoutType();
+        }
     }
 
     @Override
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java
index 671fa847..b8f92e00 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java
@@ -23,12 +23,15 @@
 import org.chromium.base.metrics.UmaRecorderHolder;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.cc.input.BrowserControlsState;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.layouts.LayoutStateProvider;
+import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.ToolbarFeatures;
 import org.chromium.chrome.browser.toolbar.top.CaptureReadinessResult.TopToolbarAllowCaptureReason;
@@ -61,6 +64,8 @@
     private Toolbar mToolbar;
     @Mock
     private Tab mTab;
+    @Mock
+    private LayoutStateProvider mLayoutStateProvider;
 
     private final Supplier<Tab> mTabSupplier = () -> mTab;
     private final ObservableSupplierImpl<Boolean> mCompositorInMotionSupplier =
@@ -76,6 +81,8 @@
     private boolean mHasTestConstraintsOverride;
     private final ObservableSupplierImpl<Integer> mConstraintsSupplier =
             new ObservableSupplierImpl<>();
+    private final OneshotSupplierImpl<LayoutStateProvider> mLayoutStateProviderSupplier =
+            new OneshotSupplierImpl<>();
 
     /**
      * Returns an initialized ObservableSupplier<Boolean>, otherwise not possible to init inline.
@@ -99,7 +106,7 @@
     private void initAdapter(ToolbarViewResourceAdapter adapter) {
         adapter.setPostInitializationDependencies(mToolbar, mConstraintsSupplier, mTabSupplier,
                 mCompositorInMotionSupplier, mBrowserStateBrowserControlsVisibilityDelegate,
-                mIsVisibleSupplier);
+                mIsVisibleSupplier, mLayoutStateProviderSupplier);
         // The adapter may observe some of these already, which will post events.
         ShadowLooper.idleMainLooper();
         // The initial addObserver triggers an event that we don't care about. Reset count.
@@ -383,9 +390,7 @@
 
     @Test
     public void testIsDirty_ConstraintsIgnoredOnNativePage() {
-        ToolbarViewResourceAdapter adapter =
-                new ToolbarViewResourceAdapter(mToolbarContainer, false);
-        initAdapter(adapter);
+        ToolbarViewResourceAdapter adapter = makeAndInitAdapter();
         Mockito.when(mToolbar.isReadyForTextureCapture())
                 .thenReturn(CaptureReadinessResult.readyWithSnapshotDifference(
                         ToolbarSnapshotDifference.URL_TEXT));
@@ -397,9 +402,7 @@
 
     @Test
     public void testInMotion_viewNotVisible() {
-        ToolbarViewResourceAdapter adapter =
-                new ToolbarViewResourceAdapter(mToolbarContainer, false);
-        initAdapter(adapter);
+        ToolbarViewResourceAdapter adapter = makeAndInitAdapter();
         Mockito.doReturn(CaptureReadinessResult.readyWithSnapshotDifference(
                                  ToolbarSnapshotDifference.URL_TEXT))
                 .when(mToolbar)
@@ -408,4 +411,26 @@
 
         changeInMotion(true, false);
     }
+
+    @Test
+    public void testIsDirty_InMotionAndToolbarSwipe() {
+        ToolbarViewResourceAdapter adapter = makeAndInitAdapter();
+        changeInMotion(true, false);
+        Mockito.doReturn(CaptureReadinessResult.readyWithSnapshotDifference(
+                                 ToolbarSnapshotDifference.URL_TEXT))
+                .when(mToolbar)
+                .isReadyForTextureCapture();
+        adapter.forceInvalidate();
+        Mockito.doReturn(LayoutType.BROWSING).when(mLayoutStateProvider).getActiveLayoutType();
+        mLayoutStateProviderSupplier.set(mLayoutStateProvider);
+        // The supplier posts the notification so idle to let it through.
+        ShadowLooper.idleMainLooper();
+
+        Assert.assertFalse(adapter.isDirty());
+
+        // TOOLBAR_SWIPE should bypass the in motion check and return dirty.
+        Mockito.doReturn(LayoutType.TOOLBAR_SWIPE).when(mLayoutStateProvider).getActiveLayoutType();
+
+        Assert.assertTrue(adapter.isDirty());
+    }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
index b07f98c58..13527ee 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
@@ -216,7 +216,7 @@
         }
         controlContainer.setPostInitializationDependencies(this, initializeWithIncognitoColors,
                 constraintsSupplier, toolbarDataProvider::getTab, compositorInMotionSupplier,
-                browserStateBrowserControlsVisibilityDelegate);
+                browserStateBrowserControlsVisibilityDelegate, layoutStateProviderSupplier);
         mToolbarLayout.initialize(toolbarDataProvider, tabController, mMenuButtonCoordinator,
                 historyDelegate, partnerHomepageEnabledSupplier, offlineDownloader);
         mToolbarLayout.setThemeColorProvider(normalThemeColorProvider);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediator.java
index 6f61d7fa..0e0684f 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediator.java
@@ -75,6 +75,9 @@
     /** Whether a layout that this overlay can be displayed on is showing. */
     private boolean mIsOnValidLayout;
 
+    /** Whether the current page has a native implementation with Android views. */
+    private boolean mIsNativePage;
+
     TopToolbarOverlayMediator(PropertyModel model, Context context,
             LayoutStateProvider layoutStateProvider,
             Callback<ClipDrawableProgressBar.DrawingInfo> progressInfoCallback,
@@ -89,14 +92,13 @@
         mTopUiThemeColorProvider = topUiThemeColorProvider;
         mModel = model;
         mIsVisibilityManuallyControlled = manualVisibilityControl;
-
         mIsOnValidLayout = (mLayoutStateProvider.getActiveLayoutType() & layoutsToShowOn) > 0;
         updateVisibility();
 
         mSceneChangeObserver = new LayoutStateObserver() {
             @Override
-            public void onStartedShowing(@LayoutType int layout, boolean showToolbar) {
-                mIsOnValidLayout = (layout & layoutsToShowOn) > 0;
+            public void onStartedShowing(@LayoutType int layoutType, boolean showToolbar) {
+                mIsOnValidLayout = (layoutType & layoutsToShowOn) > 0;
                 updateVisibility();
             }
         };
@@ -106,6 +108,7 @@
         // properties including theme color.
         Callback<Tab> activityTabCallback = (tab) -> {
             if (tab == null) return;
+            mIsNativePage = tab.isNativePage();
             updateVisibility();
             updateThemeColor(tab);
             updateProgress();
@@ -123,6 +126,7 @@
 
             @Override
             public void onContentChanged(Tab tab) {
+                mIsNativePage = tab != null && tab.isNativePage();
                 updateVisibility();
                 updateThemeColor(tab);
             }
@@ -255,9 +259,13 @@
         if (mIsVisibilityManuallyControlled) {
             mModel.set(TopToolbarOverlayProperties.VISIBLE, mManualVisibility && mIsOnValidLayout);
         } else {
-            mModel.set(TopToolbarOverlayProperties.VISIBLE,
+            boolean visibility =
                     !BrowserControlsUtils.areBrowserControlsOffScreen(mBrowserControlsStateProvider)
-                            && mIsOnValidLayout);
+                    && mIsOnValidLayout;
+            if (ToolbarFeatures.shouldSuppressCaptures()) {
+                visibility &= !mIsNativePage;
+            }
+            mModel.set(TopToolbarOverlayProperties.VISIBLE, visibility);
         }
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediatorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediatorTest.java
index f4c6bfe..35a6caaa 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediatorTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediatorTest.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.toolbar.top;
 
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -253,4 +254,21 @@
 
         mMediator.setVisibilityManuallyControlledForTesting(false);
     }
+
+    @Test
+    @EnableFeatures(ChromeFeatureList.SUPPRESS_TOOLBAR_CAPTURES)
+    public void testVisibility_suppressToolbarCaptures_nativePage() {
+        Assert.assertTrue(mModel.get(TopToolbarOverlayProperties.VISIBLE));
+        doReturn(true).when(mTab2).isNativePage();
+
+        setTabSupplierTab(mTab2);
+
+        Assert.assertFalse(mModel.get(TopToolbarOverlayProperties.VISIBLE));
+
+        verify(mTab2).addObserver(mTabObserverCaptor.capture());
+        doReturn(false).when(mTab2).isNativePage();
+        mTabObserverCaptor.getValue().onContentChanged(mTab2);
+
+        Assert.assertTrue(mModel.get(TopToolbarOverlayProperties.VISIBLE));
+    }
 }
diff --git a/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate_unittest.cc b/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate_unittest.cc
similarity index 87%
rename from chrome/browser/ui/ash/desks/chrome_desks_templates_delegate_unittest.cc
rename to chrome/browser/ui/ash/desks/chrome_saved_desk_delegate_unittest.cc
index cf615a0..c544dd77 100644
--- a/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate_unittest.cc
+++ b/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate_unittest.cc
@@ -73,26 +73,25 @@
 void ReturnEmptyGetBrowserInformation(
     const std::string& window_unique_id,
     crosapi::BrowserManager::GetBrowserInformationCallback callback) {
-  // Returns empty Lacros browser information.
+  // Returns empty lacros browser information.
   std::move(callback).Run({});
 }
 }  // namespace
 
-class ChromeDesksTemplatesDelegateTest : public testing::Test {
+class ChromeSavedDeskDelegateTest : public testing::Test {
  public:
-  ChromeDesksTemplatesDelegateTest()
+  ChromeSavedDeskDelegateTest()
       : user_manager_enabler_(std::make_unique<ash::FakeChromeUserManager>()) {}
 
-  ChromeDesksTemplatesDelegateTest(const ChromeDesksTemplatesDelegateTest&) =
+  ChromeSavedDeskDelegateTest(const ChromeSavedDeskDelegateTest&) = delete;
+  ChromeSavedDeskDelegateTest& operator=(const ChromeSavedDeskDelegateTest&) =
       delete;
-  ChromeDesksTemplatesDelegateTest& operator=(
-      const ChromeDesksTemplatesDelegateTest&) = delete;
 
-  ~ChromeDesksTemplatesDelegateTest() override = default;
+  ~ChromeSavedDeskDelegateTest() override = default;
 
   void SetUp() override {
-    // Create a test user and profile so the ChromeSavedDeskDelegate does
-    // not return empty result simply because of missing user profile.
+    // Create a test user and profile so the `ChromeSavedDeskDelegate` does not
+    // return empty result simply because of missing user profile.
     auto account_id = AccountId::FromUserEmail(kTestProfileEmail);
     const auto* user = GetFakeUserManager()->AddUser(account_id);
 
@@ -105,8 +104,8 @@
     ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(
         user, profile_.get());
 
-    // Set up Full Restore Save Handler so that ChromeSavedDeskDelegate can
-    // get launch info for a Lacros window.
+    // Set up `FullRestoreSaveHandler` so that `ChromeSavedDeskDelegate` can get
+    // launch info for a lacros window.
     full_restore::FullRestoreSaveHandler* save_handler = GetSaveHandler();
     save_handler->SetPrimaryProfilePath(profile_dir_.GetPath());
 
@@ -162,10 +161,10 @@
   user_manager::ScopedUserManager user_manager_enabler_;
 };
 
-TEST_F(ChromeDesksTemplatesDelegateTest, NullWindowReturnsEmptyAppLaunchData) {
+TEST_F(ChromeSavedDeskDelegateTest, NullWindowReturnsEmptyAppLaunchData) {
   base::RunLoop loop;
   chrome_saved_desk_delegate()->GetAppLaunchDataForSavedDesk(
-      /*window*/ nullptr,
+      /*window=*/nullptr,
       base::BindLambdaForTesting(
           [&](std::unique_ptr<app_restore::AppLaunchInfo> app_launch_info) {
             EXPECT_FALSE(app_launch_info);
@@ -174,15 +173,15 @@
   loop.Run();
 }
 
-TEST_F(ChromeDesksTemplatesDelegateTest,
+TEST_F(ChromeSavedDeskDelegateTest,
        EmptyLacrosWindowInfoReturnsEmptyAppLaunchData) {
   ASSERT_EQ(&mock_desks_client(), DesksClient::Get());
 
   std::unique_ptr<aura::Window> window =
       CreateLacrosWindow(base::NumberToString(kLacrosWindowId));
 
-  // Saves window info so that GetAppLaunchDataForDeskTemplate will attempt to
-  // get Lacros window information.
+  // Saves window info so that `GetAppLaunchDataForSavedDesk` will attempt to
+  // get lacros window information.
   SaveWindowInfo(window.get(), kActivationIndex1);
 
   EXPECT_CALL(mock_browser_manager(), IsRunning()).WillOnce(Return(true));
diff --git a/chrome/browser/ui/ash/global_media_controls/media_item_ui_device_selector_delegate_ash.cc b/chrome/browser/ui/ash/global_media_controls/media_item_ui_device_selector_delegate_ash.cc
new file mode 100644
index 0000000..3362cce
--- /dev/null
+++ b/chrome/browser/ui/ash/global_media_controls/media_item_ui_device_selector_delegate_ash.cc
@@ -0,0 +1,38 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/global_media_controls/media_item_ui_device_selector_delegate_ash.h"
+
+#include "base/notreached.h"
+
+void MediaItemUIDeviceSelectorDelegateAsh::OnAudioSinkChosen(
+    const std::string& id,
+    const std::string& sink_id) {
+  // TODO(crbug.com/1427284): Implement this.
+  NOTIMPLEMENTED();
+}
+
+base::CallbackListSubscription MediaItemUIDeviceSelectorDelegateAsh::
+    RegisterAudioOutputDeviceDescriptionsCallback(
+        MediaNotificationDeviceProvider::GetOutputDevicesCallbackList::
+            CallbackType callback) {
+  // TODO(crbug.com/1427284): Implement this.
+  NOTIMPLEMENTED();
+  return base::CallbackListSubscription();
+}
+
+base::CallbackListSubscription MediaItemUIDeviceSelectorDelegateAsh::
+    RegisterIsAudioOutputDeviceSwitchingSupportedCallback(
+        const std::string& id,
+        base::RepeatingCallback<void(bool)> callback) {
+  // TODO(crbug.com/1427284): Implement this.
+  NOTIMPLEMENTED();
+  return base::CallbackListSubscription();
+}
+
+void MediaItemUIDeviceSelectorDelegateAsh::OnMediaRemotingRequested(
+    const std::string& item_id) {
+  // TODO(crbug.com/1427284): Implement this.
+  NOTIMPLEMENTED();
+}
diff --git a/chrome/browser/ui/ash/global_media_controls/media_item_ui_device_selector_delegate_ash.h b/chrome/browser/ui/ash/global_media_controls/media_item_ui_device_selector_delegate_ash.h
new file mode 100644
index 0000000..704a8d7
--- /dev/null
+++ b/chrome/browser/ui/ash/global_media_controls/media_item_ui_device_selector_delegate_ash.h
@@ -0,0 +1,31 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ASH_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_DELEGATE_ASH_H_
+#define CHROME_BROWSER_UI_ASH_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_DELEGATE_ASH_H_
+
+#include "chrome/browser/ui/global_media_controls/media_item_ui_device_selector_delegate.h"
+
+// Used by MediaItemUIDeviceSelectorView for controlling audio devices,
+// excluding Cast devices.
+class MediaItemUIDeviceSelectorDelegateAsh
+    : public MediaItemUIDeviceSelectorDelegate {
+ public:
+  MediaItemUIDeviceSelectorDelegateAsh() = default;
+  ~MediaItemUIDeviceSelectorDelegateAsh() override = default;
+
+  // MediaItemUIDeviceSelectorDelegate:
+  void OnAudioSinkChosen(const std::string& id,
+                         const std::string& sink_id) override;
+  base::CallbackListSubscription RegisterAudioOutputDeviceDescriptionsCallback(
+      MediaNotificationDeviceProvider::GetOutputDevicesCallbackList::
+          CallbackType callback) override;
+  base::CallbackListSubscription
+  RegisterIsAudioOutputDeviceSwitchingSupportedCallback(
+      const std::string& id,
+      base::RepeatingCallback<void(bool)> callback) override;
+  void OnMediaRemotingRequested(const std::string& item_id) override;
+};
+
+#endif  // CHROME_BROWSER_UI_ASH_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_DELEGATE_ASH_H_
diff --git a/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl.cc b/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl.cc
index ebbc5e8..a6eae3d 100644
--- a/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl.cc
+++ b/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl.cc
@@ -7,12 +7,19 @@
 #include "ash/system/media/media_notification_provider.h"
 #include "ash/system/media/media_notification_provider_observer.h"
 #include "base/metrics/histogram_functions.h"
+#include "chrome/browser/ash/crosapi/crosapi_ash.h"
+#include "chrome/browser/ash/crosapi/crosapi_manager.h"
+#include "chrome/browser/ash/crosapi/media_ui_ash.h"
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/global_media_controls/cast_media_notification_item.h"
+#include "chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h"
+#include "chrome/browser/ui/views/global_media_controls/media_item_ui_helper.h"
 #include "chrome/browser/ui/views/global_media_controls/media_item_ui_legacy_cast_footer_view.h"
+#include "components/global_media_controls/public/constants.h"
 #include "components/global_media_controls/public/media_item_manager.h"
 #include "components/global_media_controls/public/media_session_item_producer.h"
+#include "components/global_media_controls/public/mojom/device_service.mojom.h"
 #include "components/global_media_controls/public/views/media_item_ui_list_view.h"
 #include "components/global_media_controls/public/views/media_item_ui_view.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -152,7 +159,10 @@
                          : ProfileManager::GetActiveUserProfile();
   auto item_ui = std::make_unique<global_media_controls::MediaItemUIView>(
       id, item, BuildFooterView(item, profile),
-      /*device_selector_view=*/nullptr, color_theme_);
+      BuildDeviceSelector(
+          id, item, GetDeviceService(item), &device_selector_delegate_, profile,
+          global_media_controls::GlobalMediaControlsEntryPoint::kSystemTray),
+      color_theme_);
   auto* item_ui_ptr = item_ui.get();
   item_ui_observer_set_.Observe(id, item_ui_ptr);
 
@@ -190,4 +200,19 @@
   item_ui_observer_set_.StopObserving(id);
 }
 
+global_media_controls::mojom::DeviceService*
+MediaNotificationProviderImpl::GetDeviceService(
+    base::WeakPtr<media_message_center::MediaNotificationItem> item) const {
+  if (!item || !item->GetSourceId()) {
+    return nullptr;
+  }
+  if (device_service_for_testing_) {
+    return device_service_for_testing_;
+  }
+  return crosapi::CrosapiManager::Get()
+      ->crosapi_ash()
+      ->media_ui_ash()
+      ->GetDeviceService(*item->GetSourceId());
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl.h b/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl.h
index 097f595..34d74c3f 100644
--- a/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl.h
+++ b/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl.h
@@ -9,6 +9,7 @@
 #include "ash/system/media/media_notification_provider.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "chrome/browser/ui/ash/global_media_controls/media_item_ui_device_selector_delegate_ash.h"
 #include "components/global_media_controls/public/media_dialog_delegate.h"
 #include "components/global_media_controls/public/media_item_manager_observer.h"
 #include "components/global_media_controls/public/media_item_ui_observer.h"
@@ -19,6 +20,9 @@
 class Profile;
 
 namespace global_media_controls {
+namespace mojom {
+class DeviceService;
+}  // namespace mojom
 class MediaItemManager;
 class MediaItemUIListView;
 class MediaSessionItemProducer;
@@ -84,7 +88,15 @@
     profile_for_testing_ = profile;
   }
 
+  void set_device_service_for_testing(
+      global_media_controls::mojom::DeviceService* device_service) {
+    device_service_for_testing_ = device_service;
+  }
+
  private:
+  global_media_controls::mojom::DeviceService* GetDeviceService(
+      base::WeakPtr<media_message_center::MediaNotificationItem> item) const;
+
   base::ObserverList<MediaNotificationProviderObserver> observers_;
 
   base::WeakPtr<global_media_controls::MediaItemUIListView>
@@ -99,7 +111,11 @@
 
   global_media_controls::MediaItemUIObserverSet item_ui_observer_set_{this};
 
+  MediaItemUIDeviceSelectorDelegateAsh device_selector_delegate_;
+
   raw_ptr<Profile> profile_for_testing_ = nullptr;
+  raw_ptr<global_media_controls::mojom::DeviceService>
+      device_service_for_testing_ = nullptr;
 };
 
 }  // namespace ash
diff --git a/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl_unittest.cc b/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl_unittest.cc
index 19ec3d7..e3e601be 100644
--- a/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl_unittest.cc
+++ b/chrome/browser/ui/ash/global_media_controls/media_notification_provider_impl_unittest.cc
@@ -9,6 +9,8 @@
 #include "ash/test_shell_delegate.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/unguessable_token.h"
+#include "chrome/browser/ash/crosapi/test_crosapi_environment.h"
+#include "chrome/browser/media/router/discovery/mdns/dns_sd_registry.h"
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/ui/global_media_controls/cast_media_notification_item.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
@@ -17,11 +19,14 @@
 #include "components/global_media_controls/public/constants.h"
 #include "components/global_media_controls/public/media_item_manager.h"
 #include "components/global_media_controls/public/media_session_item_producer.h"
+#include "components/global_media_controls/public/mojom/device_service.mojom.h"
 #include "components/global_media_controls/public/views/media_item_ui_footer.h"
 #include "components/global_media_controls/public/views/media_item_ui_list_view.h"
 #include "components/global_media_controls/public/views/media_item_ui_view.h"
+#include "components/media_message_center/mock_media_notification_item.h"
 #include "components/media_message_center/notification_theme.h"
 #include "components/media_router/common/media_route.h"
+#include "content/public/test/browser_task_environment.h"
 #include "services/media_session/public/cpp/media_session_service.h"
 #include "services/media_session/public/mojom/audio_focus.mojom.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
@@ -32,6 +37,8 @@
 #include "ui/views/test/button_test_api.h"
 #include "ui/views/view.h"
 
+using global_media_controls::mojom::DeviceListClient;
+using global_media_controls::mojom::DeviceListHost;
 using media_session::mojom::AudioFocusRequestState;
 using media_session::mojom::AudioFocusRequestStatePtr;
 using media_session::mojom::MediaSessionInfo;
@@ -54,11 +61,23 @@
               (global_media_controls::GlobalMediaControlsEntryPoint));
 };
 
+class MockDeviceService : public global_media_controls::mojom::DeviceService {
+  MOCK_METHOD(void,
+              GetDeviceListHostForSession,
+              (const std::string& session_id,
+               mojo::PendingReceiver<DeviceListHost> host_receiver,
+               mojo::PendingRemote<DeviceListClient> client_remote));
+  MOCK_METHOD(void,
+              GetDeviceListHostForPresentation,
+              (mojo::PendingReceiver<DeviceListHost> host_receiver,
+               mojo::PendingRemote<DeviceListClient> client_remote));
+};
+
 class MockMediaNotificationProviderObserver
     : public MediaNotificationProviderObserver {
  public:
-  MOCK_METHOD0(OnNotificationListChanged, void());
-  MOCK_METHOD0(OnNotificationListViewSizeChanged, void());
+  MOCK_METHOD(void, OnNotificationListChanged, ());
+  MOCK_METHOD(void, OnNotificationListViewSizeChanged, ());
 };
 
 class FakeMediaSessionService : public media_session::MediaSessionService {
@@ -99,15 +118,28 @@
   FakeMediaSessionService media_session_service_;
 };
 
+class TestMediaNotificationItem
+    : public media_message_center::test::MockMediaNotificationItem {
+ public:
+  absl::optional<base::UnguessableToken> GetSourceId() const override {
+    return source_id_;
+  }
+
+ private:
+  const base::UnguessableToken source_id_{base::UnguessableToken::Create()};
+};
+
 }  // namespace
 
 class MediaNotificationProviderImplTest : public ChromeAshTestBase {
  protected:
-  MediaNotificationProviderImplTest() = default;
+  MediaNotificationProviderImplTest()
+      : ChromeAshTestBase(std::make_unique<content::BrowserTaskEnvironment>(
+            content::BrowserTaskEnvironment::REAL_IO_THREAD)) {}
   ~MediaNotificationProviderImplTest() override = default;
 
   void SetUp() override {
-    AshTestBase::SetUp(std::make_unique<MediaTestShellDelegate>());
+    ChromeAshTestBase::SetUp(std::make_unique<MediaTestShellDelegate>());
 
     provider_ = static_cast<MediaNotificationProviderImpl*>(
         MediaNotificationProvider::Get());
@@ -209,14 +241,27 @@
  public:
   void SetUp() override {
     MediaNotificationProviderImplTest::SetUp();
+    crosapi_environment_.SetUp();
+    profile_ = crosapi_environment_.profile_manager()->CreateTestingProfile(
+        "Profile", /*is_main_profile=*/true);
     scoped_feature_list_.InitAndEnableFeature(
         media_router::kGlobalMediaControlsCastStartStop);
     InitProvider();
   }
 
+  void TearDown() override {
+    profile_ = nullptr;
+    crosapi_environment_.TearDown();
+    // This is needed for avoiding a DCHECK failure caused by
+    // TestNetworkConnectionTracker having an observer when it's destroyed.
+    media_router::DnsSdRegistry::GetInstance()->ResetForTest();
+
+    MediaNotificationProviderImplTest::TearDown();
+  }
+
  protected:
   void InitProvider() {
-    provider_->set_profile_for_testing(&profile_);
+    provider_->set_profile_for_testing(profile_);
     provider_->SetColorTheme(media_message_center::NotificationTheme());
     // We must initialize the list view before we can show individual media
     // items.
@@ -224,14 +269,15 @@
         provider_->GetMediaNotificationListView(1, /*should_clip_height=*/true);
   }
 
-  TestingProfile profile_;
+  Profile* profile_ = nullptr;
+  crosapi::TestCrosapiEnvironment crosapi_environment_;
   base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<views::View> list_view_;
 };
 
 TEST_F(CastStartStopMediaNotificationProviderImplTest, ShowCastFooterView) {
   MockCastMediaNotificationItem item{
-      media_router::MediaRoute{}, provider_->GetMediaItemManager(), &profile_};
+      media_router::MediaRoute{}, provider_->GetMediaItemManager(), profile_};
   auto* media_item_ui_view =
       provider_->ShowMediaItem("item_id", item.GetWeakPtr());
   global_media_controls::MediaItemUIFooter* footer_view =
@@ -253,4 +299,16 @@
                                   ui::EF_LEFT_MOUSE_BUTTON, 0));
 }
 
+TEST_F(CastStartStopMediaNotificationProviderImplTest, ShowDeviceSelectorView) {
+  MockDeviceService device_service;
+  TestMediaNotificationItem item;
+  provider_->set_device_service_for_testing(&device_service);
+  auto* media_item_ui_view =
+      provider_->ShowMediaItem("item_id", item.GetWeakPtr());
+  global_media_controls::MediaItemUIDeviceSelector* selector_view =
+      static_cast<global_media_controls::MediaItemUIView*>(media_item_ui_view)
+          ->device_selector_view_for_testing();
+  EXPECT_TRUE(selector_view);
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc b/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc
index 9d2e396c..d4f57eb5 100644
--- a/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc
+++ b/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc
@@ -108,7 +108,6 @@
 
   // Prior to navigation, there is only one browser available.
   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
-  Browser* old_browser = browser();
 
   // We have to listen for both the browser being removed AND the new browser
   // being added.
@@ -136,16 +135,10 @@
   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
   // Select the first available browser, which should be the SWA.
   SelectFirstBrowser();
-  Browser* new_browser = browser();
-  // However, the new browser is not the same as the previous browser because
-  // the previous one closed.
-  EXPECT_NE(old_browser, new_browser);
-
   Browser* app_browser =
       FindSystemWebAppBrowser(profile(), SystemWebAppType::PROJECTOR);
   // Projector SWA is now open.
   ASSERT_TRUE(app_browser);
-  EXPECT_EQ(app_browser, new_browser);
   content::WebContents* tab =
       app_browser->tab_strip_model()->GetActiveWebContents();
   ASSERT_TRUE(tab);
@@ -185,7 +178,6 @@
                        AppNavigationRedirectNoBlankTab) {
   // Prior to navigation, there is only one browser available.
   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
-  Browser* old_browser = browser();
 
   // Suppose the user clicks a link like https://screencast.apps.chrome in
   // gchat. The redirect URL actually looks like the below.
@@ -216,16 +208,11 @@
   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
   // Select the first available browser, which should be the SWA.
   SelectFirstBrowser();
-  Browser* new_browser = browser();
-  // Check that the new browser is not the same as the previous browser because
-  // we should have closed the previous one.
-  EXPECT_NE(old_browser, new_browser);
-
   Browser* app_browser =
       FindSystemWebAppBrowser(profile(), SystemWebAppType::PROJECTOR);
+
   // Projector SWA is now open.
   ASSERT_TRUE(app_browser);
-  EXPECT_EQ(app_browser, new_browser);
   content::WebContents* tab =
       app_browser->tab_strip_model()->GetActiveWebContents();
   ASSERT_TRUE(tab);
diff --git a/chrome/browser/ui/color/new_tab_page_color_mixer.cc b/chrome/browser/ui/color/new_tab_page_color_mixer.cc
index 757c4be..47a852b 100644
--- a/chrome/browser/ui/color/new_tab_page_color_mixer.cc
+++ b/chrome/browser/ui/color/new_tab_page_color_mixer.cc
@@ -325,7 +325,7 @@
                                    gfx::kGoogleGrey900),
         /* 10% opacity */ 0.1 * SK_AlphaOPAQUE);
     mixer[kColorRealboxResultsDimSelected] = {
-        kColorOmniboxResultsBackgroundSelected};
+        kColorOmniboxResultsTextDimmedSelected};
     mixer[kColorRealboxResultsForeground] = {kColorOmniboxText};
     mixer[kColorRealboxResultsForegroundDimmed] = {
         kColorOmniboxResultsTextDimmed};
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.cc b/chrome/browser/ui/extensions/extension_enable_flow.cc
index 86987f35..1ca1775a 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.cc
+++ b/chrome/browser/ui/extensions/extension_enable_flow.cc
@@ -104,15 +104,14 @@
   if (profile_->IsChild() && extension &&
       // Only ask for parent approval if the extension still requires approval.
       !supervised_user_extensions_delegate->IsExtensionAllowedByParent(
-          *extension, profile_)) {
+          *extension)) {
     // Either ask for parent permission or notify the child that their parent
     // has disabled this action.
     auto extension_approval_callback =
         base::BindOnce(&ExtensionEnableFlow::OnExtensionApprovalDone,
                        weak_ptr_factory_.GetWeakPtr());
     supervised_user_extensions_delegate->RequestToEnableExtensionOrShowError(
-        *extension, profile_, parent_contents_,
-        std::move(extension_approval_callback));
+        *extension, parent_contents_, std::move(extension_approval_callback));
     return;
   }
 #endif  // BUILDFLAG(ENABLE_SUPERVISED_USERS)
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service.cc b/chrome/browser/ui/global_media_controls/media_notification_service.cc
index 423de5b..f1e2a0b2 100644
--- a/chrome/browser/ui/global_media_controls/media_notification_service.cc
+++ b/chrome/browser/ui/global_media_controls/media_notification_service.cc
@@ -34,11 +34,21 @@
 #include "content/public/browser/media_session_service.h"
 #include "media/base/media_switches.h"
 #include "media/remoting/device_capability_checker.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "chrome/browser/ash/crosapi/crosapi_ash.h"
+#include "chrome/browser/ash/crosapi/crosapi_manager.h"
+#include "chrome/browser/ash/crosapi/media_ui_ash.h"
+#elif BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chromeos/crosapi/mojom/media_ui.mojom.h"
+#include "chromeos/lacros/lacros_service.h"
+#endif
+
 namespace mojom {
 using global_media_controls::mojom::DeviceListClient;
 using global_media_controls::mojom::DeviceListHost;
@@ -79,9 +89,9 @@
 
 }  // namespace
 
-MediaNotificationService::MediaNotificationService(
-    Profile* profile,
-    bool show_from_all_profiles) {
+MediaNotificationService::MediaNotificationService(Profile* profile,
+                                                   bool show_from_all_profiles)
+    : receiver_(this) {
   item_manager_ = global_media_controls::MediaItemManager::Create();
 
   absl::optional<base::UnguessableToken> source_id;
@@ -125,6 +135,24 @@
     item_manager_->AddItemProducer(
         presentation_request_notification_producer_.get());
   }
+
+  // On Lacros-enabled Chrome OS, MediaNotificationService instances exist on
+  // both Ash and Lacros sides. The Ash-side instance manages Casting from
+  // System Web Apps.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  crosapi::CrosapiManager::Get()
+      ->crosapi_ash()
+      ->media_ui_ash()
+      ->RegisterDeviceService(content::MediaSession::GetSourceId(profile),
+                              receiver_.BindNewPipeAndPassRemote());
+#elif BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (chromeos::LacrosService::Get()->IsAvailable<crosapi::mojom::MediaUI>()) {
+    chromeos::LacrosService::Get()
+        ->GetRemote<crosapi::mojom::MediaUI>()
+        ->RegisterDeviceService(content::MediaSession::GetSourceId(profile),
+                                receiver_.BindNewPipeAndPassRemote());
+  }
+#endif
 }
 
 MediaNotificationService::~MediaNotificationService() {
@@ -133,9 +161,9 @@
 }
 
 void MediaNotificationService::Shutdown() {
-  // |cast_notification_producer_| and
-  // |presentation_request_notification_producer_| depend on MediaRouter,
-  // which is another keyed service.
+  // `cast_notification_producer_` and
+  // `presentation_request_notification_producer_` depend on MediaRouter,
+  // which is another keyed service. So they must be destroyed here.
   if (cast_notification_producer_) {
     item_manager_->RemoveItemProducer(cast_notification_producer_.get());
   }
@@ -143,7 +171,6 @@
     item_manager_->RemoveItemProducer(
         presentation_request_notification_producer_.get());
   }
-
   cast_notification_producer_.reset();
   presentation_request_notification_producer_.reset();
 }
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service.h b/chrome/browser/ui/global_media_controls/media_notification_service.h
index 683d3b2b..aecfda9c 100644
--- a/chrome/browser/ui/global_media_controls/media_notification_service.h
+++ b/chrome/browser/ui/global_media_controls/media_notification_service.h
@@ -22,6 +22,7 @@
 #include "content/public/browser/presentation_observer.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -165,6 +166,8 @@
   // source. We use this to cap the number of UKM recordings per site.
   std::map<ukm::SourceId, int> actions_recorded_to_ukm_;
 
+  mojo::Receiver<global_media_controls::mojom::DeviceService> receiver_;
+
   base::WeakPtrFactory<MediaNotificationService> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service_unittest.cc b/chrome/browser/ui/global_media_controls/media_notification_service_unittest.cc
index 51dc752d..7ade220 100644
--- a/chrome/browser/ui/global_media_controls/media_notification_service_unittest.cc
+++ b/chrome/browser/ui/global_media_controls/media_notification_service_unittest.cc
@@ -42,6 +42,10 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "chrome/browser/ash/crosapi/test_crosapi_environment.h"
+#endif
+
 namespace mojom {
 using global_media_controls::mojom::DeviceListClient;
 using global_media_controls::mojom::DeviceListHost;
@@ -86,6 +90,9 @@
 
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    crosapi_environment_.SetUp();
+#endif
     media_router::ChromeMediaRouterFactory::GetInstance()->SetTestingFactory(
         profile(), base::BindRepeating(&media_router::MockMediaRouter::Create));
     service_ = std::make_unique<MediaNotificationService>(profile(), false);
@@ -94,6 +101,9 @@
   void TearDown() override {
     SimulateCloseDialog();
     service_.reset();
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    crosapi_environment_.TearDown();
+#endif
     ChromeRenderViewHostTestHarness::TearDown();
   }
 
@@ -183,6 +193,9 @@
 
  private:
   std::unique_ptr<MediaNotificationService> service_;
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  crosapi::TestCrosapiEnvironment crosapi_environment_;
+#endif
 };
 
 // This class enables the features for starting/stopping cast sessions from
diff --git a/chrome/browser/ui/global_media_controls/presentation_request_notification_producer_unittest.cc b/chrome/browser/ui/global_media_controls/presentation_request_notification_producer_unittest.cc
index 60ff6a42..316da41 100644
--- a/chrome/browser/ui/global_media_controls/presentation_request_notification_producer_unittest.cc
+++ b/chrome/browser/ui/global_media_controls/presentation_request_notification_producer_unittest.cc
@@ -26,6 +26,10 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "chrome/browser/ash/crosapi/test_crosapi_environment.h"
+#endif
+
 using testing::_;
 using testing::AtLeast;
 using testing::NiceMock;
@@ -44,6 +48,9 @@
         media_router::kGlobalMediaControlsCastStartStop);
     ChromeRenderViewHostTestHarness::SetUp();
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    crosapi_environment_.SetUp();
+#endif
     media_router::ChromeMediaRouterFactory::GetInstance()->SetTestingFactory(
         profile(), base::BindRepeating(&media_router::MockMediaRouter::Create));
     notification_service_ =
@@ -60,6 +67,9 @@
 
   void TearDown() override {
     notification_service_.reset();
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    crosapi_environment_.TearDown();
+#endif
     media_router::WebContentsPresentationManager::SetTestInstance(nullptr);
     ChromeRenderViewHostTestHarness::TearDown();
   }
@@ -112,6 +122,9 @@
       nullptr;
   std::unique_ptr<MockWebContentsPresentationManager> presentation_manager_;
   base::test::ScopedFeatureList feature_list_;
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  crosapi::TestCrosapiEnvironment crosapi_environment_;
+#endif
 };
 
 TEST_F(PresentationRequestNotificationProducerTest,
diff --git a/chrome/browser/ui/media_router/media_router_ui_service.cc b/chrome/browser/ui/media_router/media_router_ui_service.cc
index 409fb3d..72e27c40 100644
--- a/chrome/browser/ui/media_router/media_router_ui_service.cc
+++ b/chrome/browser/ui/media_router/media_router_ui_service.cc
@@ -8,6 +8,7 @@
 #include "base/observer_list.h"
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/global_media_controls/media_notification_service_factory.h"
 #include "chrome/browser/ui/media_router/media_router_ui_service_factory.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -56,11 +57,20 @@
 }
 
 void MediaRouterUIService::ConfigureService() {
-  if (!MediaRouterEnabled(profile_)) {
+  if (MediaRouterEnabled(profile_)) {
+    if (!action_controller_) {
+      action_controller_ =
+          std::make_unique<MediaRouterActionController>(profile_);
+    }
+#if BUILDFLAG(IS_CHROMEOS)
+    if (GlobalMediaControlsCastStartStopEnabled(profile_)) {
+      // Ensure that MediaNotificationService is instantiated so that it can
+      // show the Cast device picker in Global Media Controls.
+      MediaNotificationServiceFactory::GetForProfile(profile_);
+    }
+#endif
+  } else {
     DisableService();
-  } else if (!action_controller_ && MediaRouterEnabled(profile_)) {
-    action_controller_ =
-        std::make_unique<MediaRouterActionController>(profile_);
   }
 }
 
diff --git a/chrome/browser/ui/performance_controls/tab_discard_tab_helper.cc b/chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.cc
similarity index 73%
rename from chrome/browser/ui/performance_controls/tab_discard_tab_helper.cc
rename to chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.cc
index eee3506..21f01a1 100644
--- a/chrome/browser/ui/performance_controls/tab_discard_tab_helper.cc
+++ b/chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/performance_controls/tab_discard_tab_helper.h"
+#include "chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.h"
 
 #include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h"
 #include "content/public/common/url_constants.h"
@@ -12,33 +12,34 @@
 constexpr size_t kKiloByte = 1024;
 }  // namespace
 
-TabDiscardTabHelper::~TabDiscardTabHelper() = default;
+HighEfficiencyChipTabHelper::~HighEfficiencyChipTabHelper() = default;
 
-TabDiscardTabHelper::TabDiscardTabHelper(content::WebContents* contents)
+HighEfficiencyChipTabHelper::HighEfficiencyChipTabHelper(
+    content::WebContents* contents)
     : content::WebContentsObserver(contents),
-      content::WebContentsUserData<TabDiscardTabHelper>(*contents) {}
+      content::WebContentsUserData<HighEfficiencyChipTabHelper>(*contents) {}
 
-bool TabDiscardTabHelper::ShouldChipBeVisible() const {
+bool HighEfficiencyChipTabHelper::ShouldChipBeVisible() const {
   return was_discarded_ && is_page_supported_;
 }
 
-bool TabDiscardTabHelper::ShouldIconAnimate() const {
+bool HighEfficiencyChipTabHelper::ShouldIconAnimate() const {
   return was_discarded_ && !was_animated_;
 }
 
-void TabDiscardTabHelper::SetWasAnimated() {
+void HighEfficiencyChipTabHelper::SetWasAnimated() {
   was_animated_ = true;
 }
 
-void TabDiscardTabHelper::SetChipHasBeenHidden() {
+void HighEfficiencyChipTabHelper::SetChipHasBeenHidden() {
   was_chip_hidden_ = true;
 }
 
-bool TabDiscardTabHelper::HasChipBeenHidden() {
+bool HighEfficiencyChipTabHelper::HasChipBeenHidden() {
   return was_chip_hidden_;
 }
 
-uint64_t TabDiscardTabHelper::GetMemorySavingsInBytes() const {
+uint64_t HighEfficiencyChipTabHelper::GetMemorySavingsInBytes() const {
   auto* pre_discard_resource_usage =
       performance_manager::user_tuning::UserPerformanceTuningManager::
           PreDiscardResourceUsage::FromWebContents(&GetWebContents());
@@ -48,7 +49,7 @@
                    kKiloByte;
 }
 
-void TabDiscardTabHelper::DidStartNavigation(
+void HighEfficiencyChipTabHelper::DidStartNavigation(
     content::NavigationHandle* navigation_handle) {
   // Pages can only be discarded while they are in the background, and we only
   // need to inform the user after they have been subsequently reloaded so it
@@ -71,12 +72,12 @@
   is_page_supported_ = DoesChipSupportPage(navigation_handle->GetURL());
 }
 
-bool TabDiscardTabHelper::DoesChipSupportPage(const GURL& url) const {
+bool HighEfficiencyChipTabHelper::DoesChipSupportPage(const GURL& url) const {
   return !url.SchemeIs(content::kChromeUIScheme);
 }
 
 absl::optional<mojom::LifecycleUnitDiscardReason>
-TabDiscardTabHelper::GetDiscardReason(
+HighEfficiencyChipTabHelper::GetDiscardReason(
     content::NavigationHandle* navigation_handle) const {
   if (navigation_handle->ExistingDocumentWasDiscarded()) {
     auto* pre_discard_resource_usage = performance_manager::user_tuning::
@@ -91,4 +92,4 @@
   return absl::nullopt;
 }
 
-WEB_CONTENTS_USER_DATA_KEY_IMPL(TabDiscardTabHelper);
+WEB_CONTENTS_USER_DATA_KEY_IMPL(HighEfficiencyChipTabHelper);
diff --git a/chrome/browser/ui/performance_controls/tab_discard_tab_helper.h b/chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.h
similarity index 66%
rename from chrome/browser/ui/performance_controls/tab_discard_tab_helper.h
rename to chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.h
index 344d93d1..19c9c6a 100644
--- a/chrome/browser/ui/performance_controls/tab_discard_tab_helper.h
+++ b/chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TAB_DISCARD_TAB_HELPER_H_
-#define CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TAB_DISCARD_TAB_HELPER_H_
+#ifndef CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_HIGH_EFFICIENCY_CHIP_TAB_HELPER_H_
+#define CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_HIGH_EFFICIENCY_CHIP_TAB_HELPER_H_
 
 #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-shared.h"
 #include "content/public/browser/navigation_handle.h"
@@ -11,18 +11,20 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
-// Per-tab class to manage discard state. When pages are in the background, they
-// can be discarded to save memory. When the user returns to that tab, we need
-// information about whether the page had previously been discarded in order to
-// convey this information to the user.
-class TabDiscardTabHelper
+// When a page in the background has been discarded due to high efficiency mode,
+// and the user returns to that tab, a page action chip should be shown to the
+// user which conveys information about the discarded tab to the user.
+// The HighEfficiencyChipTabHelper is a per-tab class which manages the state of
+// the high efficiency chip.
+class HighEfficiencyChipTabHelper
     : public content::WebContentsObserver,
-      public content::WebContentsUserData<TabDiscardTabHelper> {
+      public content::WebContentsUserData<HighEfficiencyChipTabHelper> {
  public:
-  TabDiscardTabHelper(const TabDiscardTabHelper&) = delete;
-  TabDiscardTabHelper& operator=(const TabDiscardTabHelper&) = delete;
+  HighEfficiencyChipTabHelper(const HighEfficiencyChipTabHelper&) = delete;
+  HighEfficiencyChipTabHelper& operator=(const HighEfficiencyChipTabHelper&) =
+      delete;
 
-  ~TabDiscardTabHelper() override;
+  ~HighEfficiencyChipTabHelper() override;
 
   // Returns whether the chip associated with a discarded tab should be shown.
   bool ShouldChipBeVisible() const;
@@ -52,8 +54,8 @@
       content::NavigationHandle* navigation_handle) override;
 
  private:
-  friend class content::WebContentsUserData<TabDiscardTabHelper>;
-  explicit TabDiscardTabHelper(content::WebContents* contents);
+  friend class content::WebContentsUserData<HighEfficiencyChipTabHelper>;
+  explicit HighEfficiencyChipTabHelper(content::WebContents* contents);
 
   // Returns whether the high efficiency chip should be supported for the
   // given URL
@@ -70,4 +72,4 @@
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 };
 
-#endif  // CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TAB_DISCARD_TAB_HELPER_H_
+#endif  // CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_HIGH_EFFICIENCY_CHIP_TAB_HELPER_H_
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 7dfcadf..f4d3163 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -84,7 +84,7 @@
 #include "chrome/browser/ui/focus_tab_after_navigation_helper.h"
 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
 #include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h"
-#include "chrome/browser/ui/performance_controls/tab_discard_tab_helper.h"
+#include "chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.h"
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
 #include "chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.h"
 #include "chrome/browser/ui/recently_audible_helper.h"
@@ -488,7 +488,7 @@
   TabDialogs::CreateForWebContents(web_contents);
   if (base::FeatureList::IsEnabled(
           performance_manager::features::kHighEfficiencyModeAvailable)) {
-    TabDiscardTabHelper::CreateForWebContents(web_contents);
+    HighEfficiencyChipTabHelper::CreateForWebContents(web_contents);
   }
   if (base::FeatureList::IsEnabled(features::kTabHoverCardImages) ||
       base::FeatureList::IsEnabled(features::kWebUITabStrip)) {
diff --git a/chrome/browser/ui/tabs/tab_style.cc b/chrome/browser/ui/tabs/tab_style.cc
index 2070b595..78a9f73 100644
--- a/chrome/browser/ui/tabs/tab_style.cc
+++ b/chrome/browser/ui/tabs/tab_style.cc
@@ -22,6 +22,10 @@
 
 TabStyle::~TabStyle() = default;
 
+float TabStyle::GetSelectedTabOpacity() const {
+  return kDefaultSelectedTabOpacity;
+}
+
 // static
 int TabStyle::GetStandardWidth() {
   // The standard tab width is 240 DIP including both separators.
diff --git a/chrome/browser/ui/tabs/tab_style.h b/chrome/browser/ui/tabs/tab_style.h
index 02a30e4..07f4ba90 100644
--- a/chrome/browser/ui/tabs/tab_style.h
+++ b/chrome/browser/ui/tabs/tab_style.h
@@ -149,7 +149,7 @@
   virtual void HideHover(HideHoverStyle style) = 0;
 
   // Opacity of the active tab background painted over inactive selected tabs.
-  static constexpr float kSelectedTabOpacity = 0.75f;
+  virtual float GetSelectedTabOpacity() const;
 
   // Returns the preferred width of a single Tab, assuming space is
   // available.
@@ -186,6 +186,8 @@
   // values larger than 7.
   static constexpr float kMaximumZValue = 7.0f;
 
+  static constexpr float kDefaultSelectedTabOpacity = 0.75f;
+
  protected:
   // Avoid implicitly-deleted constructor.
   TabStyle() = default;
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
index 736cf35e..e7f0d4c2 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
+++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
@@ -1199,7 +1199,8 @@
 
 // Test that remember by choice checkbox works for open PWA option.
 IN_PROC_BROWSER_TEST_F(IntentPickerBubbleViewBrowserTestChromeOS,
-                       RememberOpenPWA) {
+                       // TODO(crbug.com/1428813): Re-enable this test
+                       DISABLED_RememberOpenPWA) {
   base::HistogramTester histogram_tester;
 
   GURL test_url(InScopeAppUrl());
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_bubble_view.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_bubble_view.cc
index 8bbb3f8..92cf29f 100644
--- a/chrome/browser/ui/views/performance_controls/high_efficiency_bubble_view.cc
+++ b/chrome/browser/ui/views/performance_controls/high_efficiency_bubble_view.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/performance_controls/high_efficiency_bubble_delegate.h"
 #include "chrome/browser/ui/performance_controls/high_efficiency_bubble_observer.h"
-#include "chrome/browser/ui/performance_controls/tab_discard_tab_helper.h"
+#include "chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
@@ -76,8 +76,9 @@
                        .SetLabel(l10n_util::GetStringUTF16(IDS_OK))
                        .SetId(kHighEfficiencyDialogOkButton));
 
-  TabDiscardTabHelper* const tab_helper = TabDiscardTabHelper::FromWebContents(
-      browser->tab_strip_model()->GetActiveWebContents());
+  HighEfficiencyChipTabHelper* const tab_helper =
+      HighEfficiencyChipTabHelper::FromWebContents(
+          browser->tab_strip_model()->GetActiveWebContents());
   const uint64_t memory_savings = tab_helper->GetMemorySavingsInBytes();
 
   ui::DialogModelLabel::TextReplacement memory_savings_text =
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view.cc
index a990e66..bfea993 100644
--- a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view.cc
+++ b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/performance_controls/tab_discard_tab_helper.h"
+#include "chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
@@ -93,8 +93,8 @@
   }
 
   if (selection.active_tab_changed()) {
-    TabDiscardTabHelper* const tab_helper =
-        TabDiscardTabHelper::FromWebContents(web_contents);
+    HighEfficiencyChipTabHelper* const tab_helper =
+        HighEfficiencyChipTabHelper::FromWebContents(web_contents);
     tab_helper->SetChipHasBeenHidden();
   }
 }
@@ -104,8 +104,8 @@
   if (!web_contents) {
     return;
   }
-  TabDiscardTabHelper* const tab_helper =
-      TabDiscardTabHelper::FromWebContents(web_contents);
+  HighEfficiencyChipTabHelper* const tab_helper =
+      HighEfficiencyChipTabHelper::FromWebContents(web_contents);
   if (tab_helper->ShouldChipBeVisible() && is_high_efficiency_mode_enabled_) {
     SetVisible(true);
     if (tab_helper->ShouldIconAnimate()) {
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc
index 3cd4128..4f55183 100644
--- a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc
+++ b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/resource_coordinator/utils.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
-#include "chrome/browser/ui/performance_controls/tab_discard_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_controller.h"
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_unittest.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_unittest.cc
index 1e2bb727..052f299d 100644
--- a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_unittest.cc
+++ b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_unittest.cc
@@ -10,8 +10,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-shared.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
+#include "chrome/browser/ui/performance_controls/high_efficiency_chip_tab_helper.h"
 #include "chrome/browser/ui/performance_controls/performance_controls_metrics.h"
-#include "chrome/browser/ui/performance_controls/tab_discard_tab_helper.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/test_with_browser_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
@@ -72,23 +72,23 @@
   void AddNewTab(int memory_savings,
                  mojom::LifecycleUnitDiscardReason discard_reason) {
     AddTab(browser(), GURL("http://foo"));
-    content::WebContents* contents =
+    content::WebContents* const contents =
         browser()->tab_strip_model()->GetActiveWebContents();
-    TabDiscardTabHelper::CreateForWebContents(contents);
+    HighEfficiencyChipTabHelper::CreateForWebContents(contents);
     performance_manager::user_tuning::UserPerformanceTuningManager::
         PreDiscardResourceUsage::CreateForWebContents(contents, memory_savings,
                                                       discard_reason);
   }
 
   void SetTabDiscardState(int tab_index, bool is_discarded) {
-    TabDiscardTabHelper* tab_helper = TabDiscardTabHelper::FromWebContents(
-        browser()->tab_strip_model()->GetWebContentsAt(tab_index));
+    content::WebContents* const web_contents =
+        browser()->tab_strip_model()->GetWebContentsAt(tab_index);
     std::unique_ptr<DiscardMockNavigationHandle> navigation_handle =
         std::make_unique<DiscardMockNavigationHandle>();
     navigation_handle.get()->SetWasDiscarded(is_discarded);
-    navigation_handle.get()->SetWebContents(
-        browser()->tab_strip_model()->GetWebContentsAt(tab_index));
-    tab_helper->DidStartNavigation(navigation_handle.get());
+    navigation_handle.get()->SetWebContents(web_contents);
+    HighEfficiencyChipTabHelper::FromWebContents(web_contents)
+        ->DidStartNavigation(navigation_handle.get());
 
     browser_view()
         ->GetLocationBarView()
diff --git a/chrome/browser/ui/views/profiles/enterprise_profile_welcome_ui_browsertest.cc b/chrome/browser/ui/views/profiles/enterprise_profile_welcome_ui_browsertest.cc
index 22cbe6d..8f97c7b0 100644
--- a/chrome/browser/ui/views/profiles/enterprise_profile_welcome_ui_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/enterprise_profile_welcome_ui_browsertest.cc
@@ -59,6 +59,8 @@
                           .use_right_to_left_language = true}},
     {.pixel_test_param = {.test_suffix = "EnterpriseWelcomeSmallWindow",
                           .use_small_window = true}},
+    {.pixel_test_param = {.test_suffix = "EnterpriseWelcomeCR2023",
+                          .use_chrome_refresh_2023_style = true}},
     {.pixel_test_param = {.test_suffix = "EnterpriseWelcomeFre",
                           .use_fre_style = true},
      .use_tangible_sync_style = true},
@@ -71,6 +73,9 @@
     {.pixel_test_param = {.test_suffix = "EnterpriseWelcomeFreSmallWindow",
                           .use_small_window = true},
      .use_tangible_sync_style = true},
+    {.pixel_test_param = {.test_suffix = "EnterpriseWelcomeFreCR2023",
+                          .use_chrome_refresh_2023_style = true},
+     .use_tangible_sync_style = true},
 };
 
 const EnterpriseWelcomeTestParam kDialogTestParams[] = {
@@ -87,6 +92,8 @@
     {.pixel_test_param = {.test_suffix = "EnterpriseWelcomeRtl",
                           .use_right_to_left_language = true},
      .show_link_data_checkbox = true},
+    {.pixel_test_param = {.test_suffix = "EnterpriseWelcomeCR2023",
+                          .use_chrome_refresh_2023_style = true}},
     {.pixel_test_param = {.test_suffix = "EnterpriseWelcomeFre"},
      .use_tangible_sync_style = true},
     {.pixel_test_param = {.test_suffix =
@@ -105,6 +112,9 @@
                           .use_right_to_left_language = true},
      .show_link_data_checkbox = true,
      .use_tangible_sync_style = true},
+    {.pixel_test_param = {.test_suffix = "EnterpriseWelcomeFreCR2023",
+                          .use_chrome_refresh_2023_style = true},
+     .use_tangible_sync_style = true},
 };
 
 // Creates a step to represent the enterprise-profile-welcome
diff --git a/chrome/browser/ui/views/profiles/first_run_intro_browsertest.cc b/chrome/browser/ui/views/profiles/first_run_intro_browsertest.cc
index bf6e5bd..72402e94 100644
--- a/chrome/browser/ui/views/profiles/first_run_intro_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/first_run_intro_browsertest.cc
@@ -53,6 +53,9 @@
     {.pixel_test_param = {.test_suffix = "RightToLeftLanguage",
                           .use_right_to_left_language = true,
                           .use_fre_style = true}},
+    {.pixel_test_param = {.test_suffix = "CR2023",
+                          .use_fre_style = true,
+                          .use_chrome_refresh_2023_style = true}},
 };
 
 const char kMakeCardDescriptionLongerJsString[] =
diff --git a/chrome/browser/ui/views/profiles/profile_management_step_controller.cc b/chrome/browser/ui/views/profiles/profile_management_step_controller.cc
index 4204cc35..ff0e8f2 100644
--- a/chrome/browser/ui/views/profiles/profile_management_step_controller.cc
+++ b/chrome/browser/ui/views/profiles/profile_management_step_controller.cc
@@ -151,6 +151,11 @@
   ~FinishSamlSignInStepController() override {
     if (finish_flow_callback_.value()) {
       finish_flow_callback_->Reset();
+
+      // The profile setup did not continue. Schedule it for deletion.
+      g_browser_process->profile_manager()
+          ->GetDeleteProfileHelper()
+          .ScheduleEphemeralProfileForDeletion(profile_->GetPath());
     }
   }
 
diff --git a/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider.cc b/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider.cc
index 715725b9..7e36d3c 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider.cc
@@ -66,6 +66,15 @@
   if (callback_) {
     if (IsInitialized()) {
       contents()->SetDelegate(nullptr);
+
+      // Schedule the ephemeral profile for deletion if it wasn't deleted yet,
+      // since it's not needed any more.
+      if (!profile_path_.has_value() &&
+          !IsProfileDirectoryMarkedForDeletion(profile_->GetPath())) {
+        g_browser_process->profile_manager()
+            ->GetDeleteProfileHelper()
+            .ScheduleEphemeralProfileForDeletion(profile_->GetPath());
+      }
     }
 
     ProfileMetrics::LogProfileAddSignInFlowOutcome(
diff --git a/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider_browsertest.cc b/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider_browsertest.cc
index da6c4d8..a1215acc 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider_browsertest.cc
@@ -7,17 +7,12 @@
 #include "base/functional/callback_helpers.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/nuke_profile_directory_utils.h"
 #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_manager.h"
 #include "chrome/browser/signin/signin_features.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/profiles/profile_picker_web_contents_host.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/profile_deletion_observer.h"
 #include "components/signin/public/base/signin_metrics.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
@@ -84,7 +79,6 @@
 
 IN_PROC_BROWSER_TEST_P(ProfilePickerDiceSignInProviderBrowserTest,
                        SwitchToSignInThenExit) {
-  ProfileDeletionObserver observer;
   base::FilePath provider_profile_path;
   base::RunLoop switch_finished_loop;
   base::MockCallback<ProfilePickerDiceSignInProvider::SignedInCallback>
@@ -121,14 +115,8 @@
     switch_finished_loop.Run();
   }
 
-  // On exit, the profile it created should be scheduled for deletion since it
-  // has no more keep alives.
-  observer.Wait();
-  ProfileAttributesEntry* entry =
-      g_browser_process->profile_manager()
-          ->GetProfileAttributesStorage()
-          .GetProfileAttributesWithPath(provider_profile_path);
-  EXPECT_EQ(entry, nullptr);
+  // On exit, the provider should schedule the profile it created for deletion.
+  EXPECT_TRUE(IsProfileDirectoryMarkedForDeletion(provider_profile_path));
 }
 
 IN_PROC_BROWSER_TEST_P(ProfilePickerDiceSignInProviderBrowserTest,
diff --git a/chrome/browser/ui/views/profiles/profile_picker_flow_controller.cc b/chrome/browser/ui/views/profiles/profile_picker_flow_controller.cc
index 1012c818..4d92b119 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_flow_controller.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_flow_controller.cc
@@ -143,6 +143,11 @@
   ~ProfileCreationSignedInFlowController() override {
     // Record unfinished signed-in profile creation.
     if (!is_finishing_) {
+      // Schedule the profile for deletion, it's not needed any more.
+      g_browser_process->profile_manager()
+          ->GetDeleteProfileHelper()
+          .ScheduleEphemeralProfileForDeletion(profile()->GetPath());
+
       // TODO(crbug.com/1300109): Consider moving this recording into
       // ProfilePickerTurnSyncOnDelegate and unify this code with Cancel().
       ProfileMetrics::LogProfileAddSignInFlowOutcome(
@@ -172,6 +177,11 @@
       return;
 
     is_finishing_ = true;
+
+    // Schedule the profile for deletion, it's not needed any more.
+    g_browser_process->profile_manager()
+        ->GetDeleteProfileHelper()
+        .ScheduleEphemeralProfileForDeletion(profile()->GetPath());
   }
 
   void FinishAndOpenBrowser(PostHostClearedCallback callback) override {
diff --git a/chrome/browser/ui/views/profiles/profile_picker_ui_browsertest.cc b/chrome/browser/ui/views/profiles/profile_picker_ui_browsertest.cc
index 0625261..fab1ec5 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_ui_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_ui_browsertest.cc
@@ -50,6 +50,8 @@
                           .use_right_to_left_language = true,
                           .use_small_window = true},
      .use_multiple_profiles = true},
+    {.pixel_test_param = {.test_suffix = "CR2023",
+                          .use_chrome_refresh_2023_style = true}},
     {.pixel_test_param = {.test_suffix = "TS"}, .use_tangible_sync_flow = true},
     {.pixel_test_param = {.test_suffix = "TSMultipleProfiles"},
      .use_tangible_sync_flow = true,
@@ -60,6 +62,9 @@
                           .use_small_window = true},
      .use_tangible_sync_flow = true,
      .use_multiple_profiles = true},
+    {.pixel_test_param = {.test_suffix = "TSCR2023",
+                          .use_chrome_refresh_2023_style = true},
+     .use_tangible_sync_flow = true},
 };
 
 void AddMultipleProfiles(Profile* profile, size_t number_of_profiles) {
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
index c1c8b1cc..84cb43e9 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
@@ -32,7 +32,6 @@
 #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
 #include "chrome/browser/policy/profile_policy_connector.h"
 #include "chrome/browser/policy/profile_policy_connector_builder.h"
-#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
 #include "chrome/browser/profiles/nuke_profile_directory_utils.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
@@ -51,7 +50,6 @@
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/profile_ui_test_utils.h"
 #include "chrome/browser/ui/startup/first_run_service.h"
@@ -758,11 +756,9 @@
       GetSyncConfirmationURL(), "joe.consumer@gmail.com", "Joe");
 
   // Close the flow with the [X] button.
-  ProfileDeletionObserver observer;
   base::FilePath canceled_path = profile_to_cancel->GetPath();
   widget()->CloseWithReason(views::Widget::ClosedReason::kCloseButtonClicked);
   WaitForPickerClosed();
-  observer.Wait();
 
   ProfileAttributesStorage& storage =
       g_browser_process->profile_manager()->GetProfileAttributesStorage();
@@ -808,10 +804,8 @@
   base::FilePath profile_to_cancel_path = profile_to_cancel->GetPath();
 
   // Close the flow with the [X] button.
-  ProfileDeletionObserver observer;
   widget()->CloseWithReason(views::Widget::ClosedReason::kCloseButtonClicked);
   WaitForPickerClosed();
-  observer.Wait();
 
   // The profile entry is deleted.
   ProfileAttributesEntry* entry =
@@ -845,7 +839,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ProfilePickerCreationFlowBrowserTest,
-                       PRE_CancelWhileSigningInWithNoOtherWindow) {
+                       CancelWhileSigningInWithNoOtherWindow) {
   ASSERT_EQ(1u, BrowserList::GetInstance()->size());
   Profile* profile_to_cancel = StartDiceSignIn();
   base::FilePath profile_to_cancel_path = profile_to_cancel->GetPath();
@@ -859,30 +853,17 @@
   widget()->CloseWithReason(views::Widget::ClosedReason::kCloseButtonClicked);
   WaitForPickerClosed();
 
-  // The profile entry is not yet deleted when Chrome is shutting down, but it
-  // will be deleted at next startup since it is an ephemeral profile.
+  // The profile entry is deleted.
   ProfileAttributesEntry* entry =
       g_browser_process->profile_manager()
           ->GetProfileAttributesStorage()
           .GetProfileAttributesWithPath(profile_to_cancel_path);
-  EXPECT_NE(entry, nullptr);
-  EXPECT_TRUE(entry->IsEphemeral());
-  ASSERT_EQ(2u, g_browser_process->profile_manager()
-                    ->GetProfileAttributesStorage()
-                    .GetNumberOfProfiles());
+  EXPECT_EQ(entry, nullptr);
 
   // Still no browser window is open.
   EXPECT_EQ(0u, BrowserList::GetInstance()->size());
 }
 
-IN_PROC_BROWSER_TEST_F(ProfilePickerCreationFlowBrowserTest,
-                       CancelWhileSigningInWithNoOtherWindow) {
-  // There is only one profile left.
-  ASSERT_EQ(1u, g_browser_process->profile_manager()
-                    ->GetProfileAttributesStorage()
-                    .GetNumberOfProfiles());
-}
-
 // Tests dice-specific logic for keeping track of the new profile color.
 IN_PROC_BROWSER_TEST_F(ProfilePickerCreationFlowBrowserTest,
                        CreateSignedInProfileDiceReenter) {
@@ -1825,14 +1806,12 @@
   EXPECT_EQ(ProfilePicker::GetSwitchProfilePath(), other_path);
 
   // Simulate clicking on the cancel button.
-  ProfileDeletionObserver observer;
   ProfilePickerHandler* handler = profile_picker_handler();
   base::Value::List args;
   handler->HandleCancelProfileSwitch(args);
 
   // Check expectations when the profile creation flow is done.
   WaitForPickerClosed();
-  observer.Wait();
 
   // Only one browser should be displayed.
   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
@@ -2152,8 +2131,14 @@
   EXPECT_FALSE(new_browser->signin_view_controller()->ShowsModalDialog());
 }
 
+// TODO(crbug.com/1367031): Test is flaky on Linux and macOS
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
+#define MAYBE_CancelLocalProfileCreation DISABLED_CancelLocalProfileCreation
+#else
+#define MAYBE_CancelLocalProfileCreation CancelLocalProfileCreation
+#endif
 IN_PROC_BROWSER_TEST_F(ProfilePickerLocalProfileCreationDialogBrowserTest,
-                       CancelLocalProfileCreation) {
+                       MAYBE_CancelLocalProfileCreation) {
   ASSERT_EQ(1u, BrowserList::GetInstance()->size());
   ASSERT_EQ(1u, g_browser_process->profile_manager()
                     ->GetProfileAttributesStorage()
@@ -2194,9 +2179,8 @@
 
   // Simulate clicking the "Delete profile" button on the profile customization
   // dialog.
-  ProfileDeletionObserver observer;
   DeleteLocalProfile(dialog_web_contents);
-  observer.Wait();
+  ui_test_utils::WaitForBrowserToClose(new_browser);
 
   ASSERT_EQ(1u, g_browser_process->profile_manager()
                     ->GetProfileAttributesStorage()
diff --git a/chrome/browser/ui/views/profiles/profile_type_choice_ui_browsertest.cc b/chrome/browser/ui/views/profiles/profile_type_choice_ui_browsertest.cc
index 63b91fd..3f6c8426 100644
--- a/chrome/browser/ui/views/profiles/profile_type_choice_ui_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_type_choice_ui_browsertest.cc
@@ -49,6 +49,8 @@
                           .use_right_to_left_language = true,
                           .use_small_window = true},
      .use_tangible_sync_flow = true},
+    {.pixel_test_param = {.test_suffix = "CR2023",
+                          .use_chrome_refresh_2023_style = true}},
 };
 
 const char kRemoveAvatarIconJS[] =
diff --git a/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.cc b/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.cc
index 9ecbb16..b729a5cf 100644
--- a/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.cc
+++ b/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.cc
@@ -13,6 +13,7 @@
 #include "components/signin/public/base/signin_buildflags.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/identity_test_utils.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/base/ui_base_switches.h"
 
 namespace {
@@ -82,6 +83,9 @@
   if (params.use_dark_theme) {
     enabled_features.push_back(features::kWebUIDarkMode);
   }
+  if (params.use_chrome_refresh_2023_style) {
+    enabled_features.push_back(features::kChromeRefresh2023);
+  }
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   if (params.use_fre_style) {
     enabled_features.push_back(kForYouFre);
diff --git a/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h b/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h
index cf89bbf..09651e29 100644
--- a/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h
+++ b/chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h
@@ -31,6 +31,7 @@
   bool use_right_to_left_language = false;
   bool use_small_window = false;
   bool use_fre_style = false;
+  bool use_chrome_refresh_2023_style = false;
 };
 
 enum class AccountManagementStatus {
diff --git a/chrome/browser/ui/views/profiles/sync_confirmation_ui_browsertest.cc b/chrome/browser/ui/views/profiles/sync_confirmation_ui_browsertest.cc
index 159c8bb..a4dddac4 100644
--- a/chrome/browser/ui/views/profiles/sync_confirmation_ui_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/sync_confirmation_ui_browsertest.cc
@@ -61,6 +61,8 @@
                           .use_small_window = true}},
     {.pixel_test_param = {.test_suffix = "LegacySyncManagedAccount"},
      .account_management_status = AccountManagementStatus::kManaged},
+    {.pixel_test_param = {.test_suffix = "LegacySyncCR2023",
+                          .use_chrome_refresh_2023_style = true}},
     {.pixel_test_param = {.test_suffix = "TangibleSync"},
      .use_tangible_sync = true},
     {.pixel_test_param = {.test_suffix = "TangibleSyncDarkTheme",
@@ -75,6 +77,8 @@
     {.pixel_test_param = {.test_suffix = "TangibleSyncManagedAccount"},
      .use_tangible_sync = true,
      .account_management_status = AccountManagementStatus::kManaged},
+    {.pixel_test_param = {.test_suffix = "TangibleSyncCR2023",
+                          .use_chrome_refresh_2023_style = true}},
 };
 
 const SyncConfirmationTestParam kDialogTestParams[] = {
@@ -91,6 +95,9 @@
     {.pixel_test_param = {.test_suffix = "LegacySyncManagedAccount"},
      .account_management_status = AccountManagementStatus::kManaged,
      .sync_style = SyncConfirmationStyle::kSigninInterceptModal},
+    {.pixel_test_param = {.test_suffix = "LegacySyncCR2023",
+                          .use_chrome_refresh_2023_style = true},
+     .sync_style = SyncConfirmationStyle::kDefaultModal},
     {.pixel_test_param = {.test_suffix = "TangibleSync"},
      .use_tangible_sync = true,
      .sync_style = SyncConfirmationStyle::kDefaultModal},
@@ -109,6 +116,9 @@
      .use_tangible_sync = true,
      .account_management_status = AccountManagementStatus::kManaged,
      .sync_style = SyncConfirmationStyle::kDefaultModal},
+    {.pixel_test_param = {.test_suffix = "TangibleSyncCR2023",
+                          .use_chrome_refresh_2023_style = true},
+     .sync_style = SyncConfirmationStyle::kDefaultModal},
 };
 
 GURL BuildSyncConfirmationWindowURL() {
diff --git a/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog_manager.cc b/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog_manager.cc
index 31bcadf..841143d 100644
--- a/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog_manager.cc
+++ b/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog_manager.cc
@@ -19,6 +19,7 @@
 #include "chrome/grit/theme_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "components/safe_browsing/core/browser/tailored_security_service/tailored_security_outcome.h"
+#include "components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/interaction/element_identifier.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -87,10 +88,11 @@
   DisabledDialogModelDelegate()
       : TailoredSecurityDialogModelDelegate(
             kDisabledDialogOutcome,
-            base::UserMetricsAction("SafeBrowsing.AccountIntegration."
-                                    "DisabledDialog.OkButtonClicked"),
-            base::UserMetricsAction("SafeBrowsing.AccountIntegration."
-                                    "DisabledDialog.SettingsButtonClicked")) {}
+            base::UserMetricsAction(
+                safe_browsing::kTailoredSecurityDisabledDialogOkButtonClicked),
+            base::UserMetricsAction(
+                safe_browsing::
+                    kTailoredSecurityDisabledDialogSettingsButtonClicked)) {}
 };
 
 class EnabledDialogModelDelegate : public TailoredSecurityDialogModelDelegate {
@@ -98,10 +100,11 @@
   EnabledDialogModelDelegate()
       : TailoredSecurityDialogModelDelegate(
             kEnabledDialogOutcome,
-            base::UserMetricsAction("SafeBrowsing.AccountIntegration."
-                                    "EnabledDialog.OkButtonClicked"),
-            base::UserMetricsAction("SafeBrowsing.AccountIntegration."
-                                    "EnabledDialog.SettingsButtonClicked")) {}
+            base::UserMetricsAction(
+                safe_browsing::kTailoredSecurityEnabledDialogOkButtonClicked),
+            base::UserMetricsAction(
+                safe_browsing::
+                    kTailoredSecurityEnabledDialogSettingsButtonClicked)) {}
 };
 
 TailoredSecurityDesktopDialogManager::TailoredSecurityDesktopDialogManager() =
@@ -152,7 +155,7 @@
   }
   close_dialog_callback_ = model_delegate_ptr->GetCloseDialogCallback();
   base::RecordAction(base::UserMetricsAction(
-      "SafeBrowsing.AccountIntegration.EnabledDialog.Shown"));
+      safe_browsing::kTailoredSecurityEnabledDialogShown));
   constrained_window::ShowBrowserModal(std::move(dialog_model),
                                        browser->window()->GetNativeWindow());
 }
@@ -196,7 +199,7 @@
   }
   close_dialog_callback_ = model_delegate_ptr->GetCloseDialogCallback();
   base::RecordAction(base::UserMetricsAction(
-      "SafeBrowsing.AccountIntegration.DisabledDialog.Shown"));
+      safe_browsing::kTailoredSecurityDisabledDialogShown));
   constrained_window::ShowBrowserModal(std::move(dialog_model),
                                        browser->window()->GetNativeWindow());
 }
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
index b4bc7850..d6ae3c53 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -632,7 +632,7 @@
 
   // Check that the caller field is set correctly.
   ASSERT_TRUE(dialog_->owner_.dialog_caller.has_value());
-  ASSERT_EQ(dialog_->owner_.dialog_caller->url_or_path.value(), url);
+  ASSERT_EQ(dialog_->owner_.dialog_caller->url_or_path().value(), url);
 
   // Click the "Cancel" button.
   CloseDialog(DIALOG_BTN_CANCEL, owning_window);
diff --git a/chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h b/chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h
index 3f2c504..17a3a08 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h
+++ b/chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h
@@ -59,7 +59,7 @@
    private:
     std::unique_ptr<ui::MenuModel> CreateMenuModel();
 
-    BrowserView* browser_view_;
+    raw_ptr<BrowserView> browser_view_;
     SidePanelEntry::Id id_;
   };
 
diff --git a/chrome/browser/ui/views/tabs/tab_group_style.cc b/chrome/browser/ui/views/tabs/tab_group_style.cc
index d6045fbe5..2ed2e79 100644
--- a/chrome/browser/ui/views/tabs/tab_group_style.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_style.cc
@@ -106,6 +106,10 @@
   return kSyncIconWidth;
 }
 
+float TabGroupStyle::GetSelectedTabOpacity() const {
+  return TabStyle::kDefaultSelectedTabOpacity;
+}
+
 // static
 int TabGroupStyle::GetChipCornerRadius() {
   return TabStyle::GetCornerRadius() - TabGroupUnderline::kStrokeThickness;
diff --git a/chrome/browser/ui/views/tabs/tab_group_style.h b/chrome/browser/ui/views/tabs/tab_group_style.h
index 1b4f800..a6ac0bc 100644
--- a/chrome/browser/ui/views/tabs/tab_group_style.h
+++ b/chrome/browser/ui/views/tabs/tab_group_style.h
@@ -46,6 +46,10 @@
   // Returns the sync icon width.
   virtual float GetSyncIconWidth() const;
 
+  // Returns the selected opacity value, This value should match the
+  // corresponding value for the matching TabStyle.
+  virtual float GetSelectedTabOpacity() const;
+
   // The radius of the tab group header chip
   static int GetChipCornerRadius();
 
diff --git a/chrome/browser/ui/views/tabs/tab_group_views.cc b/chrome/browser/ui/views/tabs/tab_group_views.cc
index a97b4ba..bbd00ae 100644
--- a/chrome/browser/ui/views/tabs/tab_group_views.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_views.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/tabs/tab_style.h"
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 #include "chrome/browser/ui/views/tabs/tab_group_header.h"
 #include "chrome/browser/ui/views/tabs/tab_group_highlight.h"
@@ -145,7 +144,7 @@
   const SkColor active_color = tab_slot_controller_->GetTabBackgroundColor(
       TabActive::kActive, BrowserFrameActiveState::kUseCurrent);
   return SkColorSetA(active_color, gfx::Tween::IntValueBetween(
-                                       TabStyle::kSelectedTabOpacity,
+                                       style_->GetSelectedTabOpacity(),
                                        SK_AlphaTRANSPARENT, SK_AlphaOPAQUE));
 }
 
diff --git a/chrome/browser/ui/views/tabs/tab_style_views.cc b/chrome/browser/ui/views/tabs/tab_style_views.cc
index 222cdf9..b3669dd 100644
--- a/chrome/browser/ui/views/tabs/tab_style_views.cc
+++ b/chrome/browser/ui/views/tabs/tab_style_views.cc
@@ -453,7 +453,7 @@
   if (tab_->IsActive())
     return 1.0f;
   if (tab_->IsSelected())
-    return kSelectedTabOpacity;
+    return GetSelectedTabOpacity();
   if (tab_->mouse_hovered())
     return GetHoverOpacity();
   return 0.0f;
@@ -720,10 +720,10 @@
 
 float GM2TabStyle::GetThrobValue() const {
   const bool is_selected = tab_->IsSelected();
-  double val = is_selected ? kSelectedTabOpacity : 0;
+  double val = is_selected ? GetSelectedTabOpacity() : 0;
 
   if (IsHoverActive()) {
-    constexpr float kSelectedTabThrobScale = 0.95f - kSelectedTabOpacity;
+    const float kSelectedTabThrobScale = 0.95f - GetSelectedTabOpacity();
     const float opacity = GetHoverOpacity();
     const float offset =
         is_selected ? (kSelectedTabThrobScale * opacity) : opacity;
diff --git a/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.h b/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.h
index 5967a41..9452d467 100644
--- a/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.h
+++ b/chrome/browser/ui/views/web_apps/web_app_identity_update_confirmation_view.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/web_app_callback_app_identity.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
+#include "components/webapps/browser/uninstall_result_code.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/metadata/view_factory.h"
 #include "ui/views/window/dialog_delegate.h"
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_cros.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_cros.cc
index d2c0f23..05a2b60 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_cros.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_cros.cc
@@ -12,14 +12,6 @@
 using WebAppIntegration = WebAppIntegrationTest;
 
 // Generated tests:
-IN_PROC_BROWSER_TEST_F(WebAppIntegration, WAI_29FileHandlerWindowed) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-}
-
 IN_PROC_BROWSER_TEST_F(WebAppIntegration, WAI_29FileHandlerBrowser) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -29,16 +21,6 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegration,
-                       WAI_32FileHandlerWithShortcutWindowedWebApp) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegration,
                        WAI_32FileHandlerWithShortcutBrowserWebApp) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -49,16 +31,6 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIntegration,
-                       WAI_32FileHandlerNoShortcutWindowedWebApp) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppIntegration,
                        WAI_32FileHandlerNoShortcutBrowserWebApp) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -68,5 +40,39 @@
                            WindowOptions::kBrowser, InstallMode::kWebApp);
 }
 
+IN_PROC_BROWSER_TEST_F(WebAppIntegration,
+                       WAI_29FileHandlerWindowed_149FileHandler) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_149FileHandler) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_149FileHandler) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+}
+
 }  // namespace
 }  // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
index afb7970..2906060 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
@@ -1612,354 +1612,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain_126FileHandlerOneBarFile) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -2030,58 +1682,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_126FileHandlerOneFooFile_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain_126FileHandlerMultipleFooFiles) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
-                                 FilesOptions::kMultipleFooFiles);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain_126FileHandlerOneBarFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_126FileHandlerOneFooFile_120FileHandlerOneFooFileAllowAskAgain) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -2137,61 +1737,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_126FileHandlerOneFooFile_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain_126FileHandlerMultipleFooFiles) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
-                                 FilesOptions::kMultipleFooFiles);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain_126FileHandlerOneBarFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_126FileHandlerOneFooFile_120FileHandlerOneFooFileAllowAskAgain) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -2229,61 +1774,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_126FileHandlerOneFooFile_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain_126FileHandlerMultipleFooFiles) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
-                                 FilesOptions::kMultipleFooFiles);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain_126FileHandlerOneBarFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_29MinimalUiWindowed_116MinimalUiWco_117MinimalUi_143_1MinimalUi_112MinimalUiShown_114MinimalUi_113MinimalUiOn_112MinimalUiShown) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -2495,23 +1985,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain_126FileHandlerMultipleBarFiles) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
-                                 FilesOptions::kMultipleBarFiles);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain_126FileHandlerMultipleBarFiles) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -2530,24 +2003,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain_126FileHandlerMultipleBarFiles) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
-                                 FilesOptions::kMultipleBarFiles);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain_126FileHandlerMultipleBarFiles) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -2566,24 +2021,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain_126FileHandlerMultipleBarFiles) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
-                                 FilesOptions::kMultipleBarFiles);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_116StandaloneTabbed_143_117Standalone_1Standalone_24_94_144) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -3889,5 +3326,1058 @@
   helper_.CheckRunOnOsLoginDisabled(Site::kStandalone);
 }
 
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_22_126FileHandlerOneFooFile_120FileHandlerOneFooFileAllowAskAgain) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain_22_126FileHandlerMultipleFooFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleFooFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain_22_126FileHandlerMultipleBarFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleBarFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_22_126FileHandlerOneFooFile_120FileHandlerOneFooFileAllowAskAgain) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain_22_126FileHandlerMultipleFooFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleFooFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain_22_126FileHandlerOneBarFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain_22_126FileHandlerMultipleBarFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleBarFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_22_126FileHandlerOneFooFile_120FileHandlerOneFooFileAllowAskAgain) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain_22_126FileHandlerMultipleFooFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleFooFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain_22_126FileHandlerOneBarFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain_22_126FileHandlerMultipleBarFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleBarFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain_22_126FileHandlerOneBarFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerOneFooFileAllowAskAgain_22_126FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerMultipleFooFilesAllowAskAgain_22_126FileHandlerMultipleFooFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleFooFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerOneBarFileAllowAskAgain_22_126FileHandlerOneBarFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerMultipleBarFilesAllowAskAgain_22_126FileHandlerMultipleBarFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleBarFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerOneFooFileAllowAskAgain_22_126FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerMultipleFooFilesAllowAskAgain_22_126FileHandlerMultipleFooFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleFooFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerOneBarFileAllowAskAgain_22_126FileHandlerOneBarFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerMultipleBarFilesAllowAskAgain_22_126FileHandlerMultipleBarFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleBarFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_94_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_94_122FileHandlerFoo_122FileHandlerBar) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kRemember);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_94_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_94_122FileHandlerFoo_122FileHandlerBar) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kRemember);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerOneFooFileAllowAskAgain_22_126FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerMultipleFooFilesAllowAskAgain_22_126FileHandlerMultipleFooFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleFooFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerOneBarFileAllowAskAgain_22_126FileHandlerOneBarFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerMultipleBarFilesAllowAskAgain_22_126FileHandlerMultipleBarFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleBarFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerOneFooFileAllowAskAgain_22_126FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerMultipleFooFilesAllowAskAgain_22_126FileHandlerMultipleFooFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleFooFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerOneBarFileAllowAskAgain_22_126FileHandlerOneBarFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerMultipleBarFilesAllowAskAgain_22_126FileHandlerMultipleBarFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleBarFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_94_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_94_122FileHandlerFoo_122FileHandlerBar) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kRemember);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_94_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_94_122FileHandlerFoo_122FileHandlerBar) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kRemember);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerOneFooFileAllowAskAgain_22_126FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerMultipleFooFilesAllowAskAgain_22_126FileHandlerMultipleFooFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleFooFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerOneBarFileAllowAskAgain_22_126FileHandlerOneBarFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_149FileHandler_120FileHandlerMultipleBarFilesAllowAskAgain_22_126FileHandlerMultipleBarFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppSettings(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleBarFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerOneFooFileAllowAskAgain_22_126FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerMultipleFooFilesAllowAskAgain_22_126FileHandlerMultipleFooFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleFooFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerOneBarFileAllowAskAgain_22_126FileHandlerOneBarFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneBarFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_147FileHandler_120FileHandlerMultipleBarFilesAllowAskAgain_22_126FileHandlerMultipleBarFiles) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.SetOpenInTabFromAppHome(Site::kFileHandler);
+  helper_.LaunchFileExpectDialog(
+      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
+      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
+  helper_.CheckTabCreated();
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler,
+                                 FilesOptions::kMultipleBarFiles);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_94_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_94_122FileHandlerFoo_122FileHandlerBar) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kRemember);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_94_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kAskAgain);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kAskAgain);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_94_122FileHandlerFoo_122FileHandlerBar) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kBrowser, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kDeny,
+                                 AskAgainOptions::kRemember);
+  helper_.CheckWindowNotCreated();
+  helper_.CheckTabNotCreated();
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kRemember);
+  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
+                                   FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_28_121FileHandlerOneFooFile_126FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kRemember);
+  helper_.ClosePwa();
+  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
+                                   FilesOptions::kOneFooFile);
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kRemember);
+  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
+                                   FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_28_121FileHandlerOneFooFile_126FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kRemember);
+  helper_.ClosePwa();
+  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
+                                   FilesOptions::kOneFooFile);
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kRemember);
+  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
+                                   FilesOptions::kOneFooFile);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_28_121FileHandlerOneFooFile_126FileHandlerOneFooFile) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
+                                 AllowDenyOptions::kAllow,
+                                 AskAgainOptions::kRemember);
+  helper_.ClosePwa();
+  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
+                                   FilesOptions::kOneFooFile);
+  helper_.CheckFilesLoadedInSite(Site::kFileHandler, FilesOptions::kOneFooFile);
+}
+
 }  // namespace
 }  // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
index 1367738..6a17f8e 100644
--- a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
@@ -128,8 +128,7 @@
   auto* provider = WebAppProvider::GetForWebContents(web_contents);
   DCHECK(provider);
 
-  if (provider->install_manager().IsInstallingForWebContents(web_contents) ||
-      provider->command_manager().IsInstallingForWebContents(web_contents)) {
+  if (provider->command_manager().IsInstallingForWebContents(web_contents)) {
     return;
   }
 
@@ -159,8 +158,7 @@
   if (!provider)
     return false;
 
-  if (provider->install_manager().IsInstallingForWebContents(web_contents) ||
-      provider->command_manager().IsInstallingForWebContents(web_contents)) {
+  if (provider->command_manager().IsInstallingForWebContents(web_contents)) {
     return false;
   }
 
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.h b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
index 909df32..7b5b903 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler.h
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
+#include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "extensions/browser/extension_registry_observer.h"
 #include "extensions/common/constants.h"
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload.mojom b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload.mojom
index 12478b7..a158ae6 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload.mojom
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload.mojom
@@ -47,7 +47,7 @@
 
   // The local file tasks the user can pick from to open the files. Displayed in
   // the `kFileHandlerDialog` dialog.
-  array<DialogTask> tasks;
+  array<DialogTask> local_tasks;
 
   // True if the setup flow is running for the first time. False if running
   // fixup flow.
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
index 0888d83a..4a52a080 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
@@ -653,8 +653,7 @@
       dialog_task->icon_url = task.icon_url.spec();
       dialog_task->app_id = task.task_descriptor.app_id;
 
-      // TODO(petermarshall): Rename args->tasks to local_tasks.
-      args->tasks.push_back(std::move(dialog_task));
+      args->local_tasks.push_back(std::move(dialog_task));
       local_tasks_.push_back(std::move(task.task_descriptor));
     }
   }
@@ -865,7 +864,7 @@
       dialog_args_(std::move(args)),
       callback_(std::move(callback)),
       dialog_page_(dialog_page),
-      num_local_tasks_(dialog_args_->tasks.size()),
+      num_local_tasks_(dialog_args_->local_tasks.size()),
       office_move_confirmation_shown_(office_move_confirmation_shown) {}
 
 CloudUploadDialog::~CloudUploadDialog() = default;
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc
index 62306b21..5424a1eb 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc
@@ -402,13 +402,14 @@
   std::string result;
   while (!dialog_init_complete) {
     // It is possible that the `FileHandlerPageElement` element still hasn't
-    // been initiated yet. It is completed when the `tasks` member is non-empty.
+    // been initiated yet. It is completed when the `localTasks` member is
+    // non-empty.
     if (!content::ExecuteScriptAndExtractString(
             web_contents,
             base::StringPrintf(
                 "domAutomationController.send(%s)",
                 ScriptFillPlaceholder(
-                    "JSON.stringify(%s.tasks.map(task => task.appId))",
+                    "JSON.stringify(%s.localTasks.map(task => task.appId))",
                     "file-handler-page")
                     .c_str()),
             &result)) {
@@ -433,7 +434,7 @@
   // task to be opened. Use this to find the `selected_task_position` and to
   // watch for the appropriate url in `urls_` to open.
   size_t selected_task = 1;
-  // Position of the selected task in dialog's tasks array - this is not
+  // Position of the selected task in dialog's localTasks array - this is not
   // necessarily the same as the `tasks_` vector. Its position is its id
   // so use this to click the task's button.
   size_t selected_task_position;
diff --git a/chrome/browser/ui/webui/ash/login/oobe_ui.cc b/chrome/browser/ui/webui/ash/login/oobe_ui.cc
index 5a070ebb..2ba3a26 100644
--- a/chrome/browser/ui/webui/ash/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/ash/login/oobe_ui.cc
@@ -297,6 +297,10 @@
   source->AddBoolean("isTouchpadScrollEnabled",
                      (features::IsOobeChoobeEnabled() &&
                       features::IsOobeTouchpadScrollEnabled()));
+  // Whether the timings in oobe_trace.js will be output to the console.
+  source->AddBoolean(
+      "printFrontendTimings",
+      command_line->HasSwitch(switches::kOobePrintFrontendLoadTimings));
 
   // Configure shared resources
   AddProductLogoResources(source);
diff --git a/chrome/browser/ui/webui/intro/intro_ui.cc b/chrome/browser/ui/webui/intro/intro_ui.cc
index 56239e97..73446c1 100644
--- a/chrome/browser/ui/webui/intro/intro_ui.cc
+++ b/chrome/browser/ui/webui/intro/intro_ui.cc
@@ -26,6 +26,7 @@
 #include "components/strings/grit/components_google_chrome_strings.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_base_features.h"
 
 IntroUI::IntroUI(content::WebUI* web_ui) : content::WebUIController(web_ui) {
   DCHECK(base::FeatureList::IsEnabled(kForYouFre));
@@ -115,6 +116,10 @@
 #endif
 #endif
 
+  source->AddString(
+      "chromeRefresh2023Attribute",
+      features::IsChromeRefresh2023() ? "chrome-refresh-2023" : "");
+
   // Unretained ok: `this` owns the handler.
   auto intro_handler = std::make_unique<IntroHandler>(
       base::BindRepeating(&IntroUI::HandleSigninChoice, base::Unretained(this)),
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc
index 4a80c603..416addc 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc
@@ -340,7 +340,7 @@
   content::TestWebContentsFactory factory_;
   raw_ptr<content::WebContents> web_contents_;  // Weak. Owned by factory_.
   // Pointer to mock that will eventually be solely owned by the handler.
-  MockCustomizeChromeFeaturePromoHelper*
+  raw_ptr<MockCustomizeChromeFeaturePromoHelper>
       mock_customize_chrome_feature_promo_helper_;
   std::unique_ptr<MockCustomizeChromeFeaturePromoHelper>
       mock_customize_chrome_feature_promo_helper_ptr_;
diff --git a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
index 240c162d..3796f0e 100644
--- a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
+++ b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
@@ -79,6 +79,7 @@
      IDS_PASSWORD_MANAGER_UI_ADD_SHORTCUT_DESCRIPTION},
     {"alreadyChangedPasswordLink",
      IDS_PASSWORD_MANAGER_UI_ALREADY_CHANGED_PASSWORD},
+    {"appsLabel", IDS_PASSWORD_MANAGER_UI_APPS_LABEL},
     {"authTimedOut", IDS_PASSWORD_MANAGER_UI_AUTH_TIMED_OUT},
     {"autosigninDescription", IDS_PASSWORD_MANAGER_UI_AUTOSIGNIN_TOGGLE_DESC},
     {"autosigninLabel", IDS_PASSWORD_MANAGER_UI_AUTOSIGNIN_TOGGLE_LABEL},
@@ -193,6 +194,7 @@
     {"settings", IDS_PASSWORD_MANAGER_UI_SETTINGS},
     {"showMore", IDS_PASSWORD_MANAGER_UI_SHOW_MORE},
     {"showPassword", IDS_PASSWORD_MANAGER_UI_SHOW_PASSWORD},
+    {"sitesAndAppsLabel", IDS_PASSWORD_MANAGER_UI_SITES_AND_APPS_LABEL},
     {"sitesLabel", IDS_PASSWORD_MANAGER_UI_SITES_LABEL},
     {"title", IDS_PASSWORD_MANAGER_UI_TITLE},
     {"trustedVaultBannerLabelOfferOptIn",
diff --git a/chrome/browser/ui/webui/password_manager/promo_cards_handler_unittest.cc b/chrome/browser/ui/webui/password_manager/promo_cards_handler_unittest.cc
index 380a66d..9f5b6ba 100644
--- a/chrome/browser/ui/webui/password_manager/promo_cards_handler_unittest.cc
+++ b/chrome/browser/ui/webui/password_manager/promo_cards_handler_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/memory/raw_ptr.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "chrome/browser/ui/webui/password_manager/promo_card.h"
@@ -106,9 +107,9 @@
  private:
   TestingPrefServiceSimple prefs_;
   content::TestWebUI web_ui_;
-  PromoCardsHandler* handler_;
-  MockPromoCard* card1_;
-  MockPromoCard* card2_;
+  raw_ptr<PromoCardsHandler> handler_;
+  raw_ptr<MockPromoCard> card1_;
+  raw_ptr<MockPromoCard> card2_;
 };
 
 TEST_F(PromoCardsHandlerTest, GetAvailablePromoCard) {
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index 739fa74..b1cd9af 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -58,6 +58,7 @@
 #include "base/i18n/time_formatting.h"
 #include "base/strings/strcat.h"
 #include "chrome/browser/ash/arc/arc_util.h"
+#include "chrome/browser/ash/eol_incentive_util.h"
 #include "chrome/browser/ash/ownership/owner_settings_service_ash.h"
 #include "chrome/browser/ash/ownership/owner_settings_service_ash_factory.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -336,6 +337,10 @@
       base::BindRepeating(&AboutHandler::HandleGetEndOfLifeInfo,
                           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
+      "openEndOfLifeIncentive",
+      base::BindRepeating(&AboutHandler::HandleOpenEndOfLifeIncentive,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
       "launchReleaseNotes",
       base::BindRepeating(&AboutHandler::HandleLaunchReleaseNotes,
                           base::Unretained(this)));
@@ -672,13 +677,41 @@
                                                     icu::TimeZone::getGMT()),
             base::ASCIIToUTF16(has_eol_passed ? chrome::kEolNotificationURL
                                               : chrome::kAutoUpdatePolicyURL)));
+    const ash::eol_incentive_util::EolIncentiveType eolIncentiveType =
+        ash::eol_incentive_util::ShouldShowEolIncentive(
+            profile_, eol_info.eol_date, clock_->Now());
+    response.Set(
+        "shouldShowEndOfLifeIncentive",
+        (eolIncentiveType ==
+             ash::eol_incentive_util::EolIncentiveType::kEolPassedRecently ||
+         eolIncentiveType ==
+             ash::eol_incentive_util::EolIncentiveType::kEolPassed) &&
+            has_eol_passed);
+    eol_incentive_shows_offer_ =
+        (ash::features::kEolIncentiveParam.Get() !=
+             ash::features::EolIncentiveParam::kNoOffer &&
+         eolIncentiveType ==
+             ash::eol_incentive_util::EolIncentiveType::kEolPassedRecently);
+    response.Set("shouldShowOfferText", eol_incentive_shows_offer_);
   } else {
     response.Set("hasEndOfLife", false);
     response.Set("aboutPageEndOfLifeMessage", "");
+    response.Set("shouldShowEndOfLifeIncentive", false);
+    response.Set("shouldShowOfferText", false);
   }
   ResolveJavascriptCallback(base::Value(callback_id), response);
 }
 
+void AboutHandler::HandleOpenEndOfLifeIncentive(const base::Value::List& args) {
+  DCHECK(args.empty());
+  ash::NewWindowDelegate::GetPrimary()->OpenUrl(
+      GURL(eol_incentive_shows_offer_
+               ? chrome::kEolIncentiveNotificationOfferURL
+               : chrome::kEolIncentiveNotificationNoOfferURL),
+      ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction,
+      ash::NewWindowDelegate::Disposition::kNewForegroundTab);
+}
+
 void AboutHandler::HandleIsManagedAutoUpdateEnabled(
     const base::Value::List& args) {
   CHECK_EQ(1U, args.size());
diff --git a/chrome/browser/ui/webui/settings/about_handler.h b/chrome/browser/ui/webui/settings/about_handler.h
index 02e47b0c..3e9863ca 100644
--- a/chrome/browser/ui/webui/settings/about_handler.h
+++ b/chrome/browser/ui/webui/settings/about_handler.h
@@ -185,6 +185,9 @@
   void OnGetEndOfLifeInfo(std::string callback_id,
                           ash::UpdateEngineClient::EolInfo eol_info);
 
+  // Opens the end of life incentive URL.
+  void HandleOpenEndOfLifeIncentive(const base::Value::List& args);
+
   // Get the managed auto update cros setting.
   void HandleIsManagedAutoUpdateEnabled(const base::Value::List& args);
 
@@ -198,6 +201,9 @@
 
   void HandleSetConsumerAutoUpdate(const base::Value::List& args);
   void HandleOpenProductLicenseOther(const base::Value::List& args);
+
+  // Whether the end of life incentive includes an offer.
+  bool eol_incentive_shows_offer_ = false;
 #endif
 
   const raw_ptr<Profile> profile_;
diff --git a/chrome/browser/ui/webui/settings/ash/about_section.cc b/chrome/browser/ui/webui/settings/ash/about_section.cc
index 716af24..761256b2 100644
--- a/chrome/browser/ui/webui/settings/ash/about_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/about_section.cc
@@ -445,6 +445,24 @@
                              ui::GetChromeOSDeviceName(),
                              base::ASCIIToUTF16(chrome::kEolNotificationURL)));
 
+  html_source->AddString("eolIncentiveOfferTitle",
+                         l10n_util::GetStringUTF16(
+                             IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_TITLE));
+  html_source->AddString("eolIncentiveOfferMessage",
+                         l10n_util::GetStringUTF16(
+                             IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_MESSAGE));
+  html_source->AddString("eolIncentiveButtonOfferText",
+                         l10n_util::GetStringUTF16(
+                             IDS_SETTINGS_END_OF_LIFE_INCENTIVE_OFFER_BUTTON));
+  html_source->AddString(
+      "eolIncentiveNoOfferTitle",
+      l10n_util::GetStringUTF16(
+          IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_TITLE));
+  html_source->AddString(
+      "eolIncentiveNoOfferMessage",
+      l10n_util::GetStringUTF16(
+          IDS_SETTINGS_END_OF_LIFE_INCENTIVE_NO_OFFER_MESSAGE));
+
   std::string safetyInfoLink = GetSafetyInfoLink();
   html_source->AddBoolean("shouldShowSafetyInfo", !safetyInfoLink.empty());
 
diff --git a/chrome/browser/ui/webui/settings/ash/files_section.cc b/chrome/browser/ui/webui/settings/ash/files_section.cc
index 264cc56..5e00dc27a 100644
--- a/chrome/browser/ui/webui/settings/ash/files_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/files_section.cc
@@ -7,6 +7,7 @@
 #include "ash/constants/ash_features.h"
 #include "base/functional/callback_helpers.h"
 #include "base/no_destructor.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h"
 #include "chrome/browser/ui/webui/ash/smb_shares/smb_handler.h"
@@ -106,7 +107,7 @@
       {"googleDriveEnabledLabel", IDS_SETTINGS_GOOGLE_DRIVE_ENABLED},
       {"googleDriveDisabledLabel", IDS_SETTINGS_GOOGLE_DRIVE_DISABLED},
       {"googleDriveDisconnectLabel", IDS_SETTINGS_GOOGLE_DRIVE_DISCONNECT},
-      {"googleDriveSignedInAs", IDS_SETTINGS_GOOGLE_DRIVE_SIGNED_IN_AS},
+      {"googleDriveConnectLabel", IDS_SETTINGS_GOOGLE_DRIVE_CONNECT},
       {"googleDriveOfflineTitle", IDS_SETTINGS_GOOGLE_DRIVE_OFFLINE_TITLE},
       {"googleDriveOfflineSubtitle",
        IDS_SETTINGS_GOOGLE_DRIVE_OFFLINE_SUBTITLE},
@@ -156,6 +157,14 @@
   html_source->AddBoolean("isActiveDirectoryUser",
                           user && user->IsActiveDirectoryUser());
 
+  if (user && user->GetAccountId().is_valid()) {
+    html_source->AddString(
+        "googleDriveSignedInAs",
+        l10n_util::GetStringFUTF16(
+            IDS_SETTINGS_GOOGLE_DRIVE_SIGNED_IN_AS,
+            base::ASCIIToUTF16(user->GetAccountId().GetUserEmail())));
+  }
+
   html_source->AddBoolean("enableDriveFsBulkPinning",
                           features::IsDriveFsBulkPinningEnabled());
 }
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom
index 7e141bc..fbd5fcd4 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom
@@ -54,6 +54,10 @@
   ExecuteOpenInIncognitoWindowCommand(array<int64> node_ids,
                                       ActionSource source);
 
+  // Opens the bookmarks specified by node_ids in a new tab group, using
+  // the same logic as the native bookmarks context menu.
+  ExecuteOpenInNewTabGroupCommand(array<int64> node_ids, ActionSource source);
+
   // Moves bookmark specified by node_id to be a direct descendant of the
   // Bookmarks Bar folder, using the same logic as the native bookmarks context
   // menu.
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc
index adcfea2..2774b0e 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc
@@ -207,6 +207,13 @@
                             IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO);
 }
 
+void BookmarksPageHandler::ExecuteOpenInNewTabGroupCommand(
+    const std::vector<int64_t>& node_ids,
+    side_panel::mojom::ActionSource source) {
+  ExecuteContextMenuCommand(node_ids, source,
+                            IDC_BOOKMARK_BAR_OPEN_ALL_NEW_TAB_GROUP);
+}
+
 void BookmarksPageHandler::ExecuteAddToBookmarksBarCommand(
     const int64_t node_id,
     side_panel::mojom::ActionSource source) {
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h
index 6bd77b7..e89796b 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h
@@ -36,6 +36,9 @@
   void ExecuteOpenInIncognitoWindowCommand(
       const std::vector<int64_t>& node_ids,
       side_panel::mojom::ActionSource source) override;
+  void ExecuteOpenInNewTabGroupCommand(
+      const std::vector<int64_t>& node_ids,
+      side_panel::mojom::ActionSource source) override;
   void ExecuteAddToBookmarksBarCommand(
       int64_t node_id,
       side_panel::mojom::ActionSource source) override;
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
index 6249ccf4..cf1e5de 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
@@ -106,6 +106,9 @@
       {"menuOpenIncognito", IDS_BOOKMARK_MANAGER_MENU_OPEN_INCOGNITO},
       {"menuOpenIncognitoWithCount",
        IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_INCOGNITO_WITH_COUNT},
+      {"menuOpenNewTabGroup", IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB_GROUP},
+      {"menuOpenNewTabGroupWithCount",
+       IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_TAB_GROUP_WITH_COUNT},
       {"menuMoveToBookmarksBar", IDS_BOOKMARKS_MOVE_TO_BOOKMARKS_BAR},
       {"menuMoveToAllBookmarks", IDS_BOOKMARKS_MOVE_TO_ALL_BOOKMARKS},
       {"menuTrackPrice", IDS_SIDE_PANEL_TRACK_BUTTON},
diff --git a/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.cc b/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.cc
index 4e98c6c..dc89429 100644
--- a/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/ui/webui/side_panel/companion/companion_page_handler.h"
 
+#include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/webui/side_panel/companion/companion_side_panel_untrusted_ui.h"
@@ -13,6 +15,7 @@
 #include "chrome/browser/ui/webui/side_panel/companion/promo_handler.h"
 #include "chrome/browser/unified_consent/unified_consent_service_factory.h"
 #include "chrome/common/webui_url_constants.h"
+#include "components/lens/buildflags.h"
 #include "components/prefs/pref_service.h"
 #include "components/unified_consent/pref_names.h"
 #include "components/unified_consent/unified_consent_service.h"
@@ -32,6 +35,7 @@
           browser->tab_strip_model()->GetActiveWebContents()),
       receiver_(this, std::move(receiver)),
       page_(std::move(page)),
+      browser_(browser),
       companion_untrusted_ui_(companion_untrusted_ui),
       url_builder_(
           std::make_unique<CompanionUrlBuilder>(browser->profile()->GetPrefs(),
@@ -70,7 +74,21 @@
 }
 
 void CompanionPageHandler::OnRegionSearchClicked() {
-  // TODO(b/274618487): Start lens region search.
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+  // Start a region search here.
+  // TODO(shaktisahu): Pass a UI entry point for accurate metrics.
+  if (!lens_region_search_controller_) {
+    lens_region_search_controller_ =
+        std::make_unique<lens::LensRegionSearchController>(browser_);
+  }
+  auto* profile =
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+  bool is_google_default_search_provider =
+      search::DefaultSearchProviderIsGoogle(profile);
+  lens_region_search_controller_->Start(web_contents(),
+                                        /*use_fullscreen_capture=*/false,
+                                        is_google_default_search_provider);
+#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 }
 
 void CompanionPageHandler::EnableMsbb(bool enable_msbb) {
diff --git a/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.h b/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.h
index e90bdd5..b99cce30 100644
--- a/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.h
+++ b/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.h
@@ -9,12 +9,17 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/webui/side_panel/companion/companion.mojom.h"
 #include "chrome/browser/ui/webui/side_panel/companion/msbb_delegate.h"
+#include "components/lens/buildflags.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
+#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+#include "chrome/browser/lens/region_search/lens_region_search_controller.h"
+#endif
+
 class Browser;
 class CompanionSidePanelUntrustedUI;
 
@@ -55,8 +60,13 @@
 
   mojo::Receiver<side_panel::mojom::CompanionPageHandler> receiver_;
   mojo::Remote<side_panel::mojom::CompanionPage> page_;
+  raw_ptr<Browser> browser_;
   raw_ptr<CompanionSidePanelUntrustedUI> companion_untrusted_ui_ = nullptr;
   std::unique_ptr<CompanionUrlBuilder> url_builder_;
+#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+  std::unique_ptr<lens::LensRegionSearchController>
+      lens_region_search_controller_;
+#endif  // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
   std::unique_ptr<PromoHandler> promo_handler_;
 
   base::WeakPtrFactory<CompanionPageHandler> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/webui/side_panel/companion/companion_url_builder.cc b/chrome/browser/ui/webui/side_panel/companion/companion_url_builder.cc
index 10420eb..9e2c30e3 100644
--- a/chrome/browser/ui/webui/side_panel/companion/companion_url_builder.cc
+++ b/chrome/browser/ui/webui/side_panel/companion/companion_url_builder.cc
@@ -28,6 +28,31 @@
 // from the WebUI URL constant because it does not include the last '/'.
 inline constexpr char kOriginQueryParameterValue[] =
     "chrome-untrusted://companion-side-panel.top-chrome";
+
+// Checks to see if the page url is a valid one to be sent to companion.
+bool IsValidPageURLForCompanion(const GURL& url) {
+  if (!url.is_valid()) {
+    return false;
+  }
+
+  if (!url.has_host()) {
+    return false;
+  }
+  if (net::IsLocalhost(url)) {
+    return false;
+  }
+  if (url.HostIsIPAddress()) {
+    return false;
+  }
+  if (!url.SchemeIsHTTPOrHTTPS()) {
+    return false;
+  }
+  if (url.has_username() || url.has_password()) {
+    return false;
+  }
+  return true;
+}
+
 }  // namespace
 
 CompanionUrlBuilder::CompanionUrlBuilder(PrefService* pref_service,
@@ -40,10 +65,11 @@
   // Fill the protobuf with the required query params.
   companion::proto::QueryParams url_params;
   bool is_msbb_enabled = msbb_delegate_->IsMsbbEnabled();
-  if (is_msbb_enabled) {
+  url_params.set_has_msbb_enabled(is_msbb_enabled);
+
+  if (is_msbb_enabled && IsValidPageURLForCompanion(page_url)) {
     url_params.set_page_url(page_url.spec());
   }
-  url_params.set_has_msbb_enabled(is_msbb_enabled);
 
   companion::proto::PromoState* promo_state = url_params.mutable_promo_state();
   promo_state->set_signin_promo_denial_count(
@@ -65,7 +91,7 @@
       kOriginQueryParameterValue);
 
   // TODO(b/274714162): Remove URL param.
-  if (is_msbb_enabled) {
+  if (is_msbb_enabled && IsValidPageURLForCompanion(page_url)) {
     url_with_query_params = net::AppendOrReplaceQueryParameter(
         url_with_query_params, kUrlQueryParameterKey, page_url.spec());
   }
diff --git a/chrome/browser/ui/webui/side_panel/companion/companion_url_builder_unittest.cc b/chrome/browser/ui/webui/side_panel/companion/companion_url_builder_unittest.cc
index e005d36..40cc1f5 100644
--- a/chrome/browser/ui/webui/side_panel/companion/companion_url_builder_unittest.cc
+++ b/chrome/browser/ui/webui/side_panel/companion/companion_url_builder_unittest.cc
@@ -21,7 +21,8 @@
 
 namespace companion {
 namespace {
-constexpr char kUrl[] = "https://foo.com/";
+
+constexpr char kValidUrl[] = "https://foo.com/";
 constexpr char kOrigin[] = "chrome-untrusted://companion-side-panel.top-chrome";
 
 class MockMsbbDelegate : public MsbbDelegate {
@@ -48,6 +49,33 @@
   }
 
  protected:
+  void VerifyPageUrlSent(GURL page_url, bool expect_was_sent) {
+    GURL companion_url = url_builder_->BuildCompanionURL(page_url);
+
+    // Deserialize the query param into protobuf.
+    companion::proto::QueryParams proto =
+        DeserializeCompanionRequest(companion_url);
+
+    if (expect_was_sent) {
+      EXPECT_EQ(proto.page_url(), page_url.spec());
+    } else {
+      EXPECT_EQ(proto.page_url(), std::string());
+    }
+
+    EXPECT_TRUE(proto.has_msbb_enabled());
+  }
+  // Deserialize the query param into proto::QueryParams.
+  proto::QueryParams DeserializeCompanionRequest(GURL companion_url) {
+    companion::proto::QueryParams proto;
+    std::string url_param;
+    EXPECT_TRUE(net::GetValueForKeyInQuery(companion_url, "query", &url_param));
+    auto base64_decoded = base::Base64Decode(url_param);
+    auto serialized_proto = std::string(base64_decoded.value().begin(),
+                                        base64_decoded.value().end());
+    EXPECT_TRUE(proto.ParseFromString(serialized_proto));
+    return proto;
+  }
+
   TestingPrefServiceSimple pref_service_;
   MockMsbbDelegate msbb_delegate_;
   std::unique_ptr<CompanionUrlBuilder> url_builder_;
@@ -58,7 +86,7 @@
       .WillRepeatedly(testing::Return(false));
   pref_service_.SetUserPref(kSigninPromoDeclinedCountPref, base::Value(1));
 
-  GURL page_url(kUrl);
+  GURL page_url(kValidUrl);
   GURL companion_url = url_builder_->BuildCompanionURL(page_url);
 
   std::string value;
@@ -68,13 +96,8 @@
   EXPECT_EQ(value, kOrigin);
 
   // Deserialize the query param into protobuf.
-  companion::proto::QueryParams proto;
-  std::string url_param;
-  EXPECT_TRUE(net::GetValueForKeyInQuery(companion_url, "query", &url_param));
-  auto base64_decoded = base::Base64Decode(url_param);
-  auto serialized_proto =
-      std::string(base64_decoded.value().begin(), base64_decoded.value().end());
-  EXPECT_TRUE(proto.ParseFromString(serialized_proto));
+  companion::proto::QueryParams proto =
+      DeserializeCompanionRequest(companion_url);
 
   // URL shouldn't be sent when MSBB is off.
   EXPECT_EQ(proto.page_url(), std::string());
@@ -82,7 +105,7 @@
 }
 
 TEST_F(CompanionUrlBuilderTest, MsbbOn) {
-  GURL page_url(kUrl);
+  GURL page_url(kValidUrl);
   EXPECT_CALL(msbb_delegate_, IsMsbbEnabled())
       .WillRepeatedly(testing::Return(true));
   GURL companion_url = url_builder_->BuildCompanionURL(page_url);
@@ -95,13 +118,8 @@
   EXPECT_EQ(value, kOrigin);
 
   // Deserialize the query param into protobuf.
-  companion::proto::QueryParams proto;
-  std::string url_param;
-  EXPECT_TRUE(net::GetValueForKeyInQuery(companion_url, "query", &url_param));
-  auto base64_decoded = base::Base64Decode(url_param);
-  auto serialized_proto =
-      std::string(base64_decoded.value().begin(), base64_decoded.value().end());
-  EXPECT_TRUE(proto.ParseFromString(serialized_proto));
+  companion::proto::QueryParams proto =
+      DeserializeCompanionRequest(companion_url);
 
   // Verify fields inside protobuf.
   EXPECT_EQ(proto.page_url(), page_url.spec());
@@ -115,7 +133,7 @@
 }
 
 TEST_F(CompanionUrlBuilderTest, NonProtobufParams) {
-  GURL page_url(kUrl);
+  GURL page_url(kValidUrl);
   GURL companion_url = url_builder_->BuildCompanionURL(page_url);
 
   std::string value;
@@ -126,4 +144,13 @@
   EXPECT_EQ(value, kOrigin);
 }
 
+TEST_F(CompanionUrlBuilderTest, ValidPageUrls) {
+  EXPECT_CALL(msbb_delegate_, IsMsbbEnabled())
+      .WillRepeatedly(testing::Return(true));
+
+  VerifyPageUrlSent(GURL(kValidUrl), true);
+  VerifyPageUrlSent(GURL("chrome://new-tab"), false);
+  VerifyPageUrlSent(GURL("https://192.168.0.1"), false);
+  VerifyPageUrlSent(GURL("https://localhost:8888"), false);
+}
 }  // namespace companion
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc
index f405d90..32d82ed 100644
--- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
@@ -306,7 +307,8 @@
       mock_ntp_custom_background_service_;
   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
   // #addr-of
-  NtpCustomBackgroundServiceObserver* ntp_custom_background_service_observer_;
+  RAW_PTR_EXCLUSION NtpCustomBackgroundServiceObserver*
+      ntp_custom_background_service_observer_;
   network::TestURLLoaderFactory test_url_loader_factory_;
   raw_ptr<MockNtpBackgroundService> mock_ntp_background_service_;
   content::TestWebContentsFactory web_contents_factory_;
@@ -314,7 +316,8 @@
   testing::NiceMock<MockPage> mock_page_;
   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
   // #addr-of
-  NtpBackgroundServiceObserver* ntp_background_service_observer_;
+  RAW_PTR_EXCLUSION NtpBackgroundServiceObserver*
+      ntp_background_service_observer_;
   raw_ptr<MockThemeService> mock_theme_service_;
   std::unique_ptr<Browser> browser_;
   std::unique_ptr<TestBrowserWindow> browser_window_;
diff --git a/chrome/browser/ui/webui/signin/profile_picker_ui.cc b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
index 668eec8..9e17bdad 100644
--- a/chrome/browser/ui/webui/signin/profile_picker_ui.cc
+++ b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
@@ -41,6 +41,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/base/webui/web_ui_util.h"
 #include "ui/webui/mojo_web_ui_controller.h"
 #include "url/gurl.h"
@@ -237,6 +238,10 @@
   html_source->AddString("managedDeviceDisclaimer",
                          GetManagedDeviceDisclaimer());
 
+  html_source->AddString(
+      "chromeRefresh2023Attribute",
+      features::IsChromeRefresh2023() ? "chrome-refresh-2023" : "");
+
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   std::string remove_warning_profile = l10n_util::GetStringFUTF8(
       IDS_PROFILE_PICKER_REMOVE_WARNING_SIGNED_IN_PROFILE_LACROS,
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc
index 4c04327b..35e6c949 100644
--- a/chrome/browser/ui/webui/theme_source.cc
+++ b/chrome/browser/ui/webui/theme_source.cc
@@ -251,6 +251,13 @@
 
   std::string sets_param;
   std::vector<base::StringPiece> color_id_sets;
+  bool generate_rgb_vars = false;
+  std::string generate_rgb_vars_query_value;
+  if (net::GetValueForKeyInQuery(url, "generate_rgb_vars",
+                                 &generate_rgb_vars_query_value)) {
+    generate_rgb_vars =
+        base::ToLowerASCII(generate_rgb_vars_query_value) == "true";
+  }
   if (!net::GetValueForKeyInQuery(url, "sets", &sets_param)) {
     LOG(ERROR)
         << "colors.css requires a 'sets' query parameter to specify the color "
@@ -262,7 +269,8 @@
                                          base::SPLIT_WANT_ALL);
 
   using ColorIdCSSCallback = base::RepeatingCallback<std::string(ui::ColorId)>;
-  auto generate_color_mapping = [&color_id_sets, &color_provider](
+  auto generate_color_mapping = [&color_id_sets, &color_provider,
+                                 &generate_rgb_vars](
                                     std::string set_name, ui::ColorId start,
                                     ui::ColorId end,
                                     ColorIdCSSCallback color_css_name) {
@@ -279,6 +287,16 @@
           base::StringPrintf("%s:%s;", color_css_name.Run(id).c_str(),
                              ui::ConvertSkColorToCSSColor(color).c_str());
       base::StrAppend(&css_string, {css_id_to_color_mapping});
+      if (generate_rgb_vars) {
+        // Also generate a r,g,b string for each color so apps can construct
+        // colors with their own opacities in css.
+        const std::string css_rgb_color_str =
+            color_utils::SkColorToRgbaString(color);
+        const std::string css_id_to_rgb_color_mapping =
+            base::StringPrintf("%s-rgb:%s;", color_css_name.Run(id).c_str(),
+                               css_rgb_color_str.c_str());
+        base::StrAppend(&css_string, {css_id_to_rgb_color_mapping});
+      }
     }
     return css_string;
   };
diff --git a/chrome/browser/vr/elements/ui_element.cc b/chrome/browser/vr/elements/ui_element.cc
index b13ebfa..586d136f 100644
--- a/chrome/browser/vr/elements/ui_element.cc
+++ b/chrome/browser/vr/elements/ui_element.cc
@@ -869,11 +869,9 @@
     gfx::RectF outer_bounds(child->size());
     gfx::RectF inner_bounds(child->size());
     if (!child->bounds_contain_padding_) {
-      // TODO(crbug.com/1312352): The order of bottom_padding_ and top_padding_
-      // seems incorrect.
       inner_bounds.Inset(
-          gfx::InsetsF::TLBR(child->bottom_padding_, child->left_padding_,
-                             child->top_padding_, child->right_padding_));
+          gfx::InsetsF::TLBR(child->top_padding_, child->left_padding_,
+                             child->bottom_padding_, child->right_padding_));
     }
     gfx::SizeF size = inner_bounds.size();
     if (size.IsEmpty())
@@ -896,10 +894,8 @@
     bounds.Union(local_rect);
   }
 
-  // TODO(crbug.com/1312352): The order of bottom_padding_ and top_padding_
-  // seems incorrect.
-  bounds.Inset(gfx::InsetsF::TLBR(-bottom_padding_, -left_padding_,
-                                  -top_padding_, -right_padding_));
+  bounds.Inset(gfx::InsetsF::TLBR(-top_padding_, -left_padding_,
+                                  -bottom_padding_, -right_padding_));
   bounds.set_origin(bounds.CenterPoint());
   if (local_origin_ != bounds.origin()) {
     world_space_transform_dirty_ = true;
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index d5c3123..b82bfc7 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -645,7 +645,6 @@
     "web_app_icon_generator_unittest.cc",
     "web_app_icon_manager_unittest.cc",
     "web_app_install_finalizer_unittest.cc",
-    "web_app_install_task_unittest.cc",
     "web_app_install_utils_unittest.cc",
     "web_app_prefs_utils_unittest.cc",
     "web_app_proto_utils_unittest.cc",
diff --git a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h
index e05871a..4bc004a 100644
--- a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h
+++ b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h
@@ -10,6 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "chrome/browser/web_applications/commands/web_app_command.h"
+#include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
diff --git a/chrome/browser/web_applications/web_app_command_manager.cc b/chrome/browser/web_applications/web_app_command_manager.cc
index ef178971..aabd5ff 100644
--- a/chrome/browser/web_applications/web_app_command_manager.cc
+++ b/chrome/browser/web_applications/web_app_command_manager.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/web_applications/locks/lock.h"
 #include "chrome/browser/web_applications/locks/web_app_lock_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
+#include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_task.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
diff --git a/chrome/browser/web_applications/web_app_icon_manager.cc b/chrome/browser/web_applications/web_app_icon_manager.cc
index 485b080..c9f3c6c 100644
--- a/chrome/browser/web_applications/web_app_icon_manager.cc
+++ b/chrome/browser/web_applications/web_app_icon_manager.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/web_applications/file_utils_wrapper.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
+#include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/common/chrome_features.h"
diff --git a/chrome/browser/web_applications/web_app_icon_manager.h b/chrome/browser/web_applications/web_app_icon_manager.h
index c524b34..8949150 100644
--- a/chrome/browser/web_applications/web_app_icon_manager.h
+++ b/chrome/browser/web_applications/web_app_icon_manager.h
@@ -21,7 +21,6 @@
 #include "base/scoped_observation.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
-#include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -38,6 +37,7 @@
 namespace web_app {
 
 class FileUtilsWrapper;
+class WebAppInstallManager;
 class WebAppRegistrar;
 
 using HomeTabIconBitmaps = std::vector<SkBitmap>;
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc
index 573b143..7958f7a5 100644
--- a/chrome/browser/web_applications/web_app_install_manager.cc
+++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -12,50 +12,28 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/functional/callback_helpers.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/observer_list.h"
-#include "base/ranges/algorithm.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/web_applications/commands/install_from_sync_command.h"
-#include "chrome/browser/web_applications/commands/web_app_uninstall_command.h"
 #include "chrome/browser/web_applications/install_bounce_metric.h"
-#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
-#include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_install_finalizer.h"
-#include "chrome/browser/web_applications/web_app_install_info.h"
-#include "chrome/browser/web_applications/web_app_install_task.h"
+#include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "chrome/browser/web_applications/web_app_internals_utils.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
-#include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h"
 #include "chrome/common/chrome_features.h"
-#include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
-#include "components/webapps/browser/uninstall_result_code.h"
-#include "content/public/browser/web_contents.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
 
 namespace {
 
-bool TaskExpectsAppId(const WebAppInstallTask* task, const AppId& app_id) {
-  return task && task->app_id_to_expect().has_value() &&
-         task->app_id_to_expect().value() == app_id;
-}
-
 constexpr char kWebAppInstallManagerName[] = "WebAppInstallManager";
 
 }  // namespace
 
 WebAppInstallManager::WebAppInstallManager(Profile* profile)
-    : profile_(profile), url_loader_(std::make_unique<WebAppUrlLoader>()) {
-  data_retriever_factory_ = base::BindRepeating(
-      []() { return std::make_unique<WebAppDataRetriever>(); });
+    : profile_(profile) {
   if (base::FeatureList::IsEnabled(features::kRecordWebAppDebugInfo)) {
     error_log_ = std::make_unique<ErrorLog>();
     ReadErrorLog(GetWebAppsRootDirectory(profile_), kWebAppInstallManagerName,
@@ -71,122 +49,9 @@
   NotifyWebAppInstallManagerDestroyed();
 }
 
-void WebAppInstallManager::Start() {
-  DCHECK(!started_);
-  started_ = true;
-}
+void WebAppInstallManager::Start() {}
 
-void WebAppInstallManager::Shutdown() {
-  // Set the `started_` flag to false first so when we delete tasks below any
-  // task that re-enters or uses this manager instance will see we're (going)
-  // offline.
-  started_ = false;
-
-  tasks_.clear();
-  {
-    TaskQueue empty;
-    task_queue_.swap(empty);
-  }
-  url_loader_.reset();
-  web_contents_.reset();
-}
-
-bool WebAppInstallManager::IsInstallingForWebContents(
-    const content::WebContents* web_contents) const {
-  return base::ranges::any_of(
-      tasks_, [web_contents](const std::unique_ptr<WebAppInstallTask>& task) {
-        return task->GetInstallingWebContents() == web_contents;
-      });
-}
-
-void WebAppInstallManager::SetSubsystems(
-    WebAppRegistrar* registrar,
-    OsIntegrationManager* os_integration_manager,
-    WebAppCommandManager* command_manager,
-    WebAppInstallFinalizer* finalizer,
-    WebAppIconManager* icon_manager,
-    WebAppSyncBridge* sync_bridge,
-    WebAppTranslationManager* translation_manager) {
-  registrar_ = registrar;
-  os_integration_manager_ = os_integration_manager;
-  command_manager_ = command_manager;
-  finalizer_ = finalizer;
-  icon_manager_ = icon_manager;
-  sync_bridge_ = sync_bridge;
-  translation_manager_ = translation_manager;
-}
-
-base::WeakPtr<WebAppInstallManager> WebAppInstallManager::GetWeakPtr() {
-  return weak_ptr_factory_.GetWeakPtr();
-}
-
-std::set<AppId> WebAppInstallManager::GetEnqueuedInstallAppIdsForTesting() {
-  std::set<AppId> app_ids;
-  if (current_queued_task_ &&
-      current_queued_task_->app_id_to_expect().has_value()) {
-    app_ids.insert(current_queued_task_->app_id_to_expect().value());
-  }
-  for (const std::unique_ptr<WebAppInstallTask>& task : tasks_) {
-    if (task && task->app_id_to_expect().has_value())
-      app_ids.insert(task->app_id_to_expect().value());
-  }
-  return app_ids;
-}
-
-bool WebAppInstallManager::IsAppIdAlreadyEnqueued(const AppId& app_id) const {
-  if (TaskExpectsAppId(current_queued_task_, app_id))
-    return true;
-
-  for (const std::unique_ptr<WebAppInstallTask>& task : tasks_) {
-    if (TaskExpectsAppId(task.get(), app_id))
-      return true;
-  }
-
-  return false;
-}
-
-void WebAppInstallManager::EnqueueTask(std::unique_ptr<WebAppInstallTask> task,
-                                       base::OnceClosure start_task) {
-  DCHECK(web_contents_);
-
-  PendingTask pending_task;
-  pending_task.task = task.get();
-  pending_task.start = std::move(start_task);
-  task_queue_.push(std::move(pending_task));
-
-  tasks_.insert(std::move(task));
-
-  MaybeStartQueuedTask();
-}
-
-void WebAppInstallManager::MaybeStartQueuedTask() {
-  if (!started_)
-    return;
-
-  DCHECK(web_contents_);
-
-  if (current_queued_task_)
-    return;
-
-  DCHECK(!task_queue_.empty());
-  PendingTask pending_task = std::move(task_queue_.front());
-  task_queue_.pop();
-  current_queued_task_ = pending_task.task;
-
-  url_loader_->PrepareForLoad(
-      web_contents_.get(),
-      base::BindOnce(&WebAppInstallManager::OnWebContentsReadyRunTask,
-                     GetWeakPtr(), std::move(pending_task)));
-}
-
-void WebAppInstallManager::TakeTaskErrorLog(WebAppInstallTask* task) {
-  if (error_log_) {
-    base::Value::Dict task_error_dict = task->TakeErrorDict();
-    if (!task_error_dict.empty()) {
-      LogErrorObject(std::move(task_error_dict));
-    }
-  }
-}
+void WebAppInstallManager::Shutdown() {}
 
 void WebAppInstallManager::TakeCommandErrorLog(
     base::PassKey<WebAppCommandManager>,
@@ -195,84 +60,6 @@
     LogErrorObject(std::move(log));
 }
 
-void WebAppInstallManager::DeleteTask(WebAppInstallTask* task) {
-  TakeTaskErrorLog(task);
-  // If this happens after/during the call to Shutdown(), then ignore deletion
-  // as `tasks_` is emptied already.
-  if (started_) {
-    DCHECK(tasks_.contains(task));
-    tasks_.erase(task);
-  }
-}
-
-void WebAppInstallManager::OnInstallTaskCompleted(
-    WebAppInstallTask* task,
-    OnceInstallCallback callback,
-    const AppId& app_id,
-    webapps::InstallResultCode code) {
-  DeleteTask(task);
-  std::move(callback).Run(app_id, code);
-}
-
-void WebAppInstallManager::OnQueuedTaskCompleted(
-    WebAppInstallTask* task,
-    OnceInstallCallback callback,
-    const AppId& app_id,
-    webapps::InstallResultCode code) {
-  DCHECK(current_queued_task_);
-  DCHECK_EQ(current_queued_task_, task);
-  current_queued_task_ = nullptr;
-
-  OnInstallTaskCompleted(task, std::move(callback), app_id, code);
-  // |task| is now destroyed.
-  task = nullptr;
-
-  if (task_queue_.empty() && !current_queued_task_)
-    web_contents_.reset();
-  else
-    MaybeStartQueuedTask();
-}
-
-content::WebContents* WebAppInstallManager::EnsureWebContentsCreated() {
-  if (!web_contents_)
-    web_contents_ = WebAppInstallTask::CreateWebContents(profile_);
-  return web_contents_.get();
-}
-
-void WebAppInstallManager::OnWebContentsReadyRunTask(
-    PendingTask pending_task,
-    WebAppUrlLoader::Result result) {
-  if (!web_contents_) {
-    DCHECK(!started_);
-    return;
-  }
-
-  // about:blank must always be loaded.
-  DCHECK_EQ(WebAppUrlLoader::Result::kUrlLoaded, result);
-  if (result != WebAppUrlLoader::Result::kUrlLoaded)
-    LogUrlLoaderError("OnWebContentsReady", pending_task, result);
-
-  std::move(pending_task.start).Run();
-}
-
-void WebAppInstallManager::LogUrlLoaderError(const char* stage,
-                                             const PendingTask& pending_task,
-                                             WebAppUrlLoader::Result result) {
-  if (!error_log_)
-    return;
-
-  base::Value::Dict url_loader_error;
-  url_loader_error.Set("WebAppUrlLoader::Result",
-                       ConvertUrlLoaderResultToString(result));
-
-  if (pending_task.task->app_id_to_expect().has_value()) {
-    url_loader_error.Set("task.app_id_to_expect",
-                         pending_task.task->app_id_to_expect().value());
-  }
-
-  LogErrorObjectAtStage(stage, std::move(url_loader_error));
-}
-
 void WebAppInstallManager::MaybeWriteErrorLog() {
   DCHECK(error_log_);
   if (error_log_writing_in_progress_ || !error_log_updated_)
@@ -317,15 +104,6 @@
   MaybeWriteErrorLog();
 }
 
-void WebAppInstallManager::LogErrorObjectAtStage(const char* stage,
-                                                 base::Value::Dict object) {
-  if (!error_log_)
-    return;
-
-  object.Set("!stage", stage);
-  LogErrorObject(std::move(object));
-}
-
 void WebAppInstallManager::AddObserver(WebAppInstallManagerObserver* observer) {
   observers_.AddObserver(observer);
 }
@@ -377,11 +155,4 @@
   }
 }
 
-WebAppInstallManager::PendingTask::PendingTask() = default;
-
-WebAppInstallManager::PendingTask::PendingTask(PendingTask&&) noexcept =
-    default;
-
-WebAppInstallManager::PendingTask::~PendingTask() = default;
-
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_manager.h b/chrome/browser/web_applications/web_app_install_manager.h
index 095e458..a2c7e50 100644
--- a/chrome/browser/web_applications/web_app_install_manager.h
+++ b/chrome/browser/web_applications/web_app_install_manager.h
@@ -7,44 +7,21 @@
 
 #include <memory>
 
-#include "base/containers/flat_set.h"
-#include "base/containers/queue.h"
-#include "base/containers/unique_ptr_adapters.h"
 #include "base/functional/callback_forward.h"
-#include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/types/pass_key.h"
 #include "base/values.h"
-#include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
+#include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
-#include "chrome/browser/web_applications/web_app_install_manager_observer.h"
-#include "chrome/browser/web_applications/web_app_install_params.h"
-#include "chrome/browser/web_applications/web_app_install_utils.h"
-#include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
 
 class Profile;
 
-namespace content {
-class WebContents;
-}
-
-namespace webapps {
-enum class InstallResultCode;
-}
-
 namespace web_app {
 
 class WebAppCommandManager;
-class WebAppDataRetriever;
-class WebAppInstallFinalizer;
-class WebAppInstallTask;
-class WebAppRegistrar;
-class OsIntegrationManager;
-class WebAppSyncBridge;
-class WebAppTranslationManager;
-class WebAppIconManager;
+class WebAppInstallManagerObserver;
 
 class WebAppInstallManager {
  public:
@@ -56,19 +33,6 @@
   void Start();
   void Shutdown();
 
-  void SetSubsystems(WebAppRegistrar* registrar,
-                     OsIntegrationManager* os_integration_manager,
-                     WebAppCommandManager* command_manager,
-                     WebAppInstallFinalizer* finalizer,
-                     WebAppIconManager* icon_manager,
-                     WebAppSyncBridge* sync_bridge,
-                     WebAppTranslationManager* translation_manager);
-
-  // Returns whether the an installation is already running with the
-  // same web contents.
-  bool IsInstallingForWebContents(
-      const content::WebContents* web_contents) const;
-
   virtual void AddObserver(WebAppInstallManagerObserver* observer);
   virtual void RemoveObserver(WebAppInstallManagerObserver* observer);
 
@@ -85,93 +49,19 @@
   using ErrorLog = base::Value::List;
   const ErrorLog* error_log() const { return error_log_.get(); }
 
-  using DataRetrieverFactory =
-      base::RepeatingCallback<std::unique_ptr<WebAppDataRetriever>()>;
-
-  bool has_web_contents_for_testing() const { return web_contents_ != nullptr; }
-  std::set<AppId> GetEnqueuedInstallAppIdsForTesting();
-
   // TODO(crbug.com/1322974): migrate loggign to WebAppCommandManager after all
   // tasks are migrated to the command system.
   void TakeCommandErrorLog(base::PassKey<WebAppCommandManager>,
                            base::Value::Dict log);
 
  private:
-  FRIEND_TEST_ALL_PREFIXES(WebAppInstallManagerTest,
-                           TaskQueueWebContentsReadyRace);
-
-  base::WeakPtr<WebAppInstallManager> GetWeakPtr();
-
-  bool IsAppIdAlreadyEnqueued(const AppId& app_id) const;
-
-  void EnqueueTask(std::unique_ptr<WebAppInstallTask> task,
-                   base::OnceClosure start_task);
-  void MaybeStartQueuedTask();
-
-  void TakeTaskErrorLog(WebAppInstallTask* task);
-  void DeleteTask(WebAppInstallTask* task);
-  void OnInstallTaskCompleted(WebAppInstallTask* task,
-                              OnceInstallCallback callback,
-                              const AppId& app_id,
-                              webapps::InstallResultCode code);
-  void OnQueuedTaskCompleted(WebAppInstallTask* task,
-                             OnceInstallCallback callback,
-                             const AppId& app_id,
-                             webapps::InstallResultCode code);
-
-  content::WebContents* EnsureWebContentsCreated();
-
-  // Tasks can be queued for sequential completion (to be run one at a time).
-  // FIFO. This is a subset of |tasks_|.
-  struct PendingTask {
-    PendingTask();
-    PendingTask(PendingTask&&) noexcept;
-    ~PendingTask();
-
-    raw_ptr<const WebAppInstallTask> task = nullptr;
-    base::OnceClosure start;
-  };
-
-  void OnWebContentsReadyRunTask(PendingTask pending_task,
-                                 WebAppUrlLoader::Result result);
-
   void MaybeWriteErrorLog();
   void OnWriteErrorLog(Result result);
   void OnReadErrorLog(Result result, base::Value error_log);
 
   void LogErrorObject(base::Value::Dict object);
-  void LogErrorObjectAtStage(const char* stage, base::Value::Dict object);
-  void LogUrlLoaderError(const char* stage,
-                         const PendingTask& task,
-                         WebAppUrlLoader::Result result);
-
-  DataRetrieverFactory data_retriever_factory_;
 
   const raw_ptr<Profile> profile_;
-  std::unique_ptr<WebAppUrlLoader> url_loader_;
-
-  raw_ptr<WebAppRegistrar> registrar_ = nullptr;
-  raw_ptr<OsIntegrationManager, DanglingUntriaged> os_integration_manager_ =
-      nullptr;
-  raw_ptr<WebAppInstallFinalizer> finalizer_ = nullptr;
-  raw_ptr<WebAppCommandManager, DanglingUntriaged> command_manager_ = nullptr;
-  raw_ptr<WebAppSyncBridge> sync_bridge_ = nullptr;
-  raw_ptr<WebAppTranslationManager> translation_manager_ = nullptr;
-  raw_ptr<WebAppIconManager> icon_manager_ = nullptr;
-
-  // All owned tasks.
-  using Tasks = base::flat_set<std::unique_ptr<WebAppInstallTask>,
-                               base::UniquePtrComparator>;
-  Tasks tasks_;
-
-  using TaskQueue = base::queue<PendingTask>;
-  TaskQueue task_queue_;
-  raw_ptr<const WebAppInstallTask> current_queued_task_ = nullptr;
-
-  // A single WebContents, shared between tasks in |task_queue_|.
-  std::unique_ptr<content::WebContents> web_contents_;
-
-  bool started_ = false;
 
   std::unique_ptr<ErrorLog> error_log_;
   bool error_log_updated_ = false;
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc
index e9eb1ae..2c43b9da 100644
--- a/chrome/browser/web_applications/web_app_install_task.cc
+++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -2,305 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <string>
-#include <utility>
-
-#include "base/feature_list.h"
-#include "base/functional/bind.h"
-#include "base/functional/callback.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ssl/security_state_tab_helper.h"
-#include "chrome/browser/web_applications/install_bounce_metric.h"
-#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
-#include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_icon_generator.h"
-#include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_task.h"
+
+#include <memory>
+
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
-#include "chrome/browser/web_applications/web_app_registrar.h"
-#include "chrome/browser/web_applications/web_app_utils.h"
-#include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h"
-#include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
-#include "chrome/common/chrome_features.h"
-#include "components/webapps/browser/features.h"
-#include "components/webapps/browser/install_result_code.h"
-#include "components/webapps/browser/installable/installable_logging.h"
-#include "components/webapps/browser/installable/installable_metrics.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
-#include "net/http/http_status_code.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "url/gurl.h"
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "ash/components/arc/mojom/app.mojom.h"
-#include "ash/components/arc/mojom/intent_helper.mojom.h"
-#include "ash/components/arc/session/arc_bridge_service.h"
-#include "ash/components/arc/session/arc_service_manager.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ash/system_web_apps/types/system_web_app_data.h"
-#endif
-
-#if BUILDFLAG(IS_CHROMEOS)
-#include "net/base/url_util.h"
-#endif
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "chromeos/crosapi/mojom/arc.mojom.h"
-#include "chromeos/crosapi/mojom/web_app_service.mojom.h"
-#include "chromeos/lacros/lacros_service.h"
-#include "chromeos/startup/browser_params_proxy.h"
-#endif
 
 namespace web_app {
 
-namespace {
-
-#if BUILDFLAG(IS_CHROMEOS)
-const char kChromeOsPlayPlatform[] = "chromeos_play";
-const char kPlayIntentPrefix[] =
-    "https://play.google.com/store/apps/details?id=";
-const char kPlayStorePackage[] = "com.android.vending";
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-constexpr bool kAddAppsToQuickLaunchBarByDefault = false;
-
-#else
-constexpr bool kAddAppsToQuickLaunchBarByDefault = true;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
-#if BUILDFLAG(IS_CHROMEOS)
-struct PlayStoreIntent {
-  std::string app_id;
-  std::string intent;
-};
-
-// Find the first Chrome OS app in related_applications of |manifest| and return
-// the details necessary to redirect the user to the app's listing in the Play
-// Store.
-absl::optional<PlayStoreIntent> GetPlayStoreIntentFromManifest(
-    const blink::mojom::Manifest& manifest) {
-  for (const auto& app : manifest.related_applications) {
-    std::string id = base::UTF16ToUTF8(app.id.value_or(std::u16string()));
-    if (!base::EqualsASCII(app.platform.value_or(std::u16string()),
-                           kChromeOsPlayPlatform)) {
-      continue;
-    }
-
-    if (id.empty()) {
-      // Fallback to ID in the URL.
-      if (!net::GetValueForKeyInQuery(app.url, "id", &id) || id.empty()) {
-        continue;
-      }
-    }
-
-    std::string referrer;
-    if (net::GetValueForKeyInQuery(app.url, "referrer", &referrer) &&
-        !referrer.empty()) {
-      referrer = "&referrer=" + referrer;
-    }
-
-    std::string intent = kPlayIntentPrefix + id + referrer;
-    return PlayStoreIntent{id, intent};
-  }
-  return absl::nullopt;
-}
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-bool ShouldInteractWithArc() {
-  auto* lacros_service = chromeos::LacrosService::Get();
-  return lacros_service &&
-         // Check if the feature is enabled.
-         chromeos::BrowserParamsProxy::Get()->WebAppsEnabled() &&
-         // Only use ARC installation flow if we know that remote ash-chrome is
-         // capable of installing from Play Store in lacros-chrome, to avoid
-         // redirecting users to the Play Store if they cannot install
-         // anything.
-         lacros_service->IsAvailable<crosapi::mojom::WebAppService>();
-}
-
-mojo::Remote<crosapi::mojom::Arc>* GetArcRemoteWithMinVersion(
-    uint32_t minVersion) {
-  auto* lacros_service = chromeos::LacrosService::Get();
-  if (lacros_service && lacros_service->IsAvailable<crosapi::mojom::Arc>() &&
-      lacros_service->GetInterfaceVersion(crosapi::mojom::Arc::Uuid_) >=
-          static_cast<int>(minVersion)) {
-    return &lacros_service->GetRemote<crosapi::mojom::Arc>();
-  }
-  return nullptr;
-}
-#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
-
-}  // namespace
-
-WebAppInstallTask::WebAppInstallTask(
-    Profile* profile,
-    WebAppInstallFinalizer* install_finalizer,
-    std::unique_ptr<WebAppDataRetriever> data_retriever,
-    WebAppRegistrar* registrar,
-    webapps::WebappInstallSource install_surface)
-    : data_retriever_(std::move(data_retriever)),
-      install_finalizer_(install_finalizer),
-      profile_(profile),
-      registrar_(registrar),
-      install_surface_(install_surface),
-      log_entry_(/*background_installation=*/false, install_surface) {
-  DCHECK_NE(install_surface_, webapps::WebappInstallSource::SYNC);
-  // Note: background_installation in the log entry is updated later in the
-  // install method calls.
-}
-
-WebAppInstallTask::~WebAppInstallTask() {
-  // If this task is still observing a WebContents, then the callbacks haven't
-  // yet been run.  Run them before the task is destroyed.
-  if (web_contents())
-    CallInstallCallback(AppId(),
-                        webapps::InstallResultCode::kInstallTaskDestroyed);
-}
-
-void WebAppInstallTask::ExpectAppId(const AppId& expected_app_id) {
-  expected_app_id_ = expected_app_id;
-}
-
-void WebAppInstallTask::InstallWebAppFromManifest(
-    content::WebContents* contents,
-    bool bypass_service_worker_check,
-    WebAppInstallDialogCallback dialog_callback,
-    OnceInstallCallback install_callback) {
-  DCHECK(AreWebAppsUserInstallable(profile_));
-  CheckInstallPreconditions();
-
-  Observe(contents);
-  dialog_callback_ = std::move(dialog_callback);
-  install_callback_ = std::move(install_callback);
-
-  auto web_app_info = std::make_unique<WebAppInstallInfo>();
-
-  if (install_params_)
-    ApplyParamsToWebAppInstallInfo(*install_params_, *web_app_info);
-
-  data_retriever_->CheckInstallabilityAndRetrieveManifest(
-      web_contents(), bypass_service_worker_check,
-      base::BindOnce(&WebAppInstallTask::OnDidPerformInstallableCheck,
-                     GetWeakPtr(), std::move(web_app_info)));
-}
-
-void WebAppInstallTask::InstallWebAppFromManifestWithFallback(
-    content::WebContents* contents,
-    WebAppInstallFlow flow,
-    WebAppInstallDialogCallback dialog_callback,
-    OnceInstallCallback install_callback) {
-  DCHECK(AreWebAppsUserInstallable(profile_));
-  CheckInstallPreconditions();
-
-  Observe(contents);
-  dialog_callback_ = std::move(dialog_callback);
-  install_callback_ = std::move(install_callback);
-  flow_ = flow;
-
-  data_retriever_->GetWebAppInstallInfo(
-      web_contents(),
-      base::BindOnce(&WebAppInstallTask::OnGetWebAppInstallInfo, GetWeakPtr()));
-}
-
-// static
-void WebAppInstallTask::UpdateFinalizerClientData(
-    const absl::optional<WebAppInstallParams>& params,
-    WebAppInstallFinalizer::FinalizeOptions* options) {
-  if (params) {
-    if (IsChromeOsDataMandatory()) {
-      options->chromeos_data.emplace();
-      options->chromeos_data->show_in_launcher =
-          params->add_to_applications_menu;
-      options->chromeos_data->show_in_search = params->add_to_search;
-      options->chromeos_data->show_in_management = params->add_to_management;
-      options->chromeos_data->is_disabled = params->is_disabled;
-      options->chromeos_data->oem_installed = params->oem_installed;
-      options->chromeos_data->handles_file_open_intents =
-          params->handles_file_open_intents;
-    }
-    options->bypass_os_hooks = params->bypass_os_hooks;
-    options->add_to_applications_menu = params->add_to_applications_menu;
-    options->add_to_desktop = params->add_to_desktop;
-    options->add_to_quick_launch_bar = params->add_to_quick_launch_bar;
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-    if (params->system_app_type.has_value()) {
-      options->system_web_app_data.emplace();
-      options->system_web_app_data->system_app_type =
-          params->system_app_type.value();
-    }
-#endif
-  }
-}
-
-void WebAppInstallTask::InstallWebAppFromInfo(
-    std::unique_ptr<WebAppInstallInfo> web_app_install_info,
-    bool overwrite_existing_manifest_fields,
-    OnceInstallCallback callback) {
-  CheckInstallPreconditions();
-
-  PopulateProductIcons(web_app_install_info.get(),
-                       /*icons_map*/ nullptr);
-  // No IconsMap to populate shortcut item icons from.
-
-  if (install_params_)
-    ApplyParamsToWebAppInstallInfo(*install_params_, *web_app_install_info);
-
-  background_installation_ = true;
-  log_entry_.set_background_installation(true);
-  install_callback_ = std::move(callback);
-
-  RecordInstallEvent();
-
-  WebAppInstallFinalizer::FinalizeOptions options(install_surface_);
-  options.locally_installed = true;
-  options.overwrite_existing_manifest_fields =
-      overwrite_existing_manifest_fields;
-
-  if (install_params_) {
-    ApplyParamsToFinalizeOptions(*install_params_, options);
-  } else {
-    options.bypass_os_hooks = true;
-  }
-
-  install_finalizer_->FinalizeInstall(
-      *web_app_install_info, options,
-      base::BindOnce(&WebAppInstallTask::OnInstallFinalized, GetWeakPtr()));
-}
-
-void WebAppInstallTask::LoadAndRetrieveWebAppInstallInfoWithIcons(
-    const GURL& start_url,
-    WebAppUrlLoader* url_loader,
-    RetrieveWebAppInstallInfoWithIconsCallback callback) {
-  CheckInstallPreconditions();
-
-  retrieve_info_callback_ = std::move(callback);
-  background_installation_ = true;
-  log_entry_.set_background_installation(true);
-  only_retrieve_web_app_install_info_ = true;
-
-  web_contents_ = CreateWebContents(profile_);
-  Observe(web_contents_.get());
-
-  DCHECK(url_loader);
-  url_loader->LoadUrl(
-      start_url, web_contents(),
-      WebAppUrlLoader::UrlComparison::kIgnoreQueryParamsAndRef,
-      base::BindOnce(&WebAppInstallTask::OnWebAppUrlLoadedGetWebAppInstallInfo,
-                     GetWeakPtr(), start_url));
-}
-
 // static
 std::unique_ptr<content::WebContents> WebAppInstallTask::CreateWebContents(
     Profile* profile) {
@@ -312,482 +23,4 @@
   return web_contents;
 }
 
-content::WebContents* WebAppInstallTask::GetInstallingWebContents() {
-  return web_contents();
-}
-
-base::WeakPtr<WebAppInstallTask> WebAppInstallTask::GetWeakPtr() {
-  return weak_ptr_factory_.GetWeakPtr();
-}
-
-void WebAppInstallTask::WebContentsDestroyed() {
-  CallInstallCallback(AppId(),
-                      webapps::InstallResultCode::kWebContentsDestroyed);
-}
-
-base::Value::Dict WebAppInstallTask::TakeErrorDict() {
-  DCHECK(log_entry_.HasErrorDict());
-  return log_entry_.TakeErrorDict();
-}
-
-void WebAppInstallTask::CheckInstallPreconditions() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  DCHECK(!profile_->ShutdownStarted());
-
-  // Concurrent calls are not allowed.
-  DCHECK(!web_contents());
-  CHECK(!install_callback_);
-  CHECK(!retrieve_info_callback_);
-
-  DCHECK(!initiated_);
-  initiated_ = true;
-}
-
-void WebAppInstallTask::RecordInstallEvent() {
-  if (webapps::InstallableMetrics::IsReportableInstallSource(
-          install_surface_)) {
-    webapps::InstallableMetrics::TrackInstallEvent(install_surface_);
-  }
-}
-
-void WebAppInstallTask::CallInstallCallback(const AppId& app_id,
-                                            webapps::InstallResultCode code) {
-  Observe(nullptr);
-  dialog_callback_.Reset();
-
-  if (only_retrieve_web_app_install_info_) {
-    DCHECK(retrieve_info_callback_);
-    if (web_app_install_info_) {
-      std::move(retrieve_info_callback_).Run(std::move(*web_app_install_info_));
-      web_app_install_info_ = absl::nullopt;
-    } else {
-      std::move(retrieve_info_callback_).Run(code);
-    }
-    return;
-  }
-
-  DCHECK(install_callback_);
-  webapps::InstallableMetrics::TrackInstallResult(webapps::IsSuccess(code));
-  std::move(install_callback_).Run(app_id, code);
-}
-
-bool WebAppInstallTask::ShouldStopInstall() const {
-  // Install should stop early if WebContents is being destroyed.
-  // WebAppInstallTask::WebContentsDestroyed will get called eventually and
-  // the callback will be invoked at that point.
-  return !web_contents() || web_contents()->IsBeingDestroyed() ||
-         profile_->ShutdownStarted();
-}
-
-void WebAppInstallTask::OnWebAppUrlLoadedGetWebAppInstallInfo(
-    const GURL& url_to_load,
-    WebAppUrlLoader::Result result) {
-  if (ShouldStopInstall())
-    return;
-
-  if (result != WebAppUrlLoader::Result::kUrlLoaded) {
-    log_entry_.LogUrlLoaderError("OnWebAppUrlLoaded", url_to_load.spec(),
-                                 result);
-  }
-
-  if (result == WebAppUrlLoader::Result::kRedirectedUrlLoaded) {
-    CallInstallCallback(expected_app_id_.value_or(AppId()),
-                        webapps::InstallResultCode::kInstallURLRedirected);
-    return;
-  }
-
-  if (result == WebAppUrlLoader::Result::kFailedPageTookTooLong) {
-    CallInstallCallback(expected_app_id_.value_or(AppId()),
-                        webapps::InstallResultCode::kInstallURLLoadTimeOut);
-    return;
-  }
-
-  if (result != WebAppUrlLoader::Result::kUrlLoaded) {
-    CallInstallCallback(expected_app_id_.value_or(AppId()),
-                        webapps::InstallResultCode::kInstallURLLoadFailed);
-    return;
-  }
-
-  data_retriever_->GetWebAppInstallInfo(
-      web_contents(),
-      base::BindOnce(&WebAppInstallTask::OnGetWebAppInstallInfo, GetWeakPtr()));
-}
-
-void WebAppInstallTask::OnGetWebAppInstallInfo(
-    std::unique_ptr<WebAppInstallInfo> web_app_info) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (ShouldStopInstall())
-    return;
-
-  if (!web_app_info) {
-    CallInstallCallback(
-        AppId(), webapps::InstallResultCode::kGetWebAppInstallInfoFailed);
-    return;
-  }
-
-  bool bypass_service_worker_check = false;
-  if (install_params_) {
-    bypass_service_worker_check = install_params_->bypass_service_worker_check;
-
-    // Set start_url to fallback_start_url as web_contents may have been
-    // redirected. Will be overridden by manifest values if present.
-    DCHECK(install_params_->fallback_start_url.is_valid());
-    web_app_info->start_url = install_params_->fallback_start_url;
-
-    if (install_params_->fallback_app_name.has_value())
-      web_app_info->title = install_params_->fallback_app_name.value();
-
-    ApplyParamsToWebAppInstallInfo(*install_params_, *web_app_info);
-  }
-
-  data_retriever_->CheckInstallabilityAndRetrieveManifest(
-      web_contents(), bypass_service_worker_check,
-      base::BindOnce(&WebAppInstallTask::OnDidPerformInstallableCheck,
-                     GetWeakPtr(), std::move(web_app_info)));
-}
-
-void WebAppInstallTask::OnDidPerformInstallableCheck(
-    std::unique_ptr<WebAppInstallInfo> web_app_info,
-    blink::mojom::ManifestPtr opt_manifest,
-    const GURL& manifest_url,
-    bool valid_manifest_for_web_app,
-    webapps::InstallableStatusCode error_code) {
-  if (ShouldStopInstall())
-    return;
-
-  DCHECK(web_app_info);
-
-  if (install_params_ && install_params_->require_manifest &&
-      !valid_manifest_for_web_app) {
-    LOG(WARNING) << "Did not install " << web_app_info->start_url.spec()
-                 << " because it didn't have a manifest for web app";
-    CallInstallCallback(AppId(),
-                        webapps::InstallResultCode::kNotValidManifestForWebApp);
-    return;
-  }
-
-  if (opt_manifest)
-    UpdateWebAppInfoFromManifest(*opt_manifest, manifest_url,
-                                 web_app_info.get());
-
-  if (flow_ == WebAppInstallFlow::kCreateShortcut &&
-      base::FeatureList::IsEnabled(
-          webapps::features::kCreateShortcutIgnoresManifest)) {
-    // When creating a shortcut, the |manifest_id| is not part of the App's
-    // primary key. The only thing that identifies a shortcut is the start URL,
-    // which is always set to the current page.
-    *web_app_info = WebAppInstallInfo::CreateInstallInfoForCreateShortcut(
-        web_contents()->GetLastCommittedURL(), *web_app_info);
-  }
-
-  AppId app_id =
-      GenerateAppId(web_app_info->manifest_id, web_app_info->start_url);
-
-  // Does the app_id expectation check if requested.
-  if (expected_app_id_.has_value() && *expected_app_id_ != app_id) {
-    log_entry_.LogExpectedAppIdError("OnDidPerformInstallableCheck",
-                                     web_app_info->start_url.spec(), app_id,
-                                     expected_app_id_.value());
-    CallInstallCallback(*expected_app_id_,
-                        webapps::InstallResultCode::kExpectedAppIdCheckFailed);
-
-    return;
-  }
-
-  // Duplicate installation check for SUB_APP installs (done here since the
-  // AppId isn't available beforehand). It's possible that the app was already
-  // installed, but from a different source (eg. by the user manually). In that
-  // case we proceed with the installation which adds the SUB_APP install source
-  // as well.
-  if (install_surface_ == webapps::WebappInstallSource::SUB_APP) {
-    DCHECK(web_app_info->parent_app_id.has_value());
-    if (registrar_->WasInstalledBySubApp(app_id)) {
-      CallInstallCallback(std::move(app_id),
-                          webapps::InstallResultCode::kSuccessAlreadyInstalled);
-      return;
-    }
-  }
-
-  base::flat_set<GURL> icon_urls = GetValidIconUrlsToDownload(*web_app_info);
-
-  // A system app should always have a manifest icon.
-  if (install_surface_ == webapps::WebappInstallSource::SYSTEM_DEFAULT) {
-    DCHECK(opt_manifest);
-    DCHECK(!opt_manifest->icons.empty());
-  }
-
-  // If the manifest specified icons, don't use the page icons.
-  const bool skip_page_favicons = opt_manifest && !opt_manifest->icons.empty();
-
-  CheckForPlayStoreIntentOrGetIcons(std::move(opt_manifest),
-                                    std::move(web_app_info),
-                                    std::move(icon_urls), skip_page_favicons);
-}
-
-void WebAppInstallTask::CheckForPlayStoreIntentOrGetIcons(
-    blink::mojom::ManifestPtr opt_manifest,
-    std::unique_ptr<WebAppInstallInfo> web_app_info,
-    base::flat_set<GURL> icon_urls,
-    bool skip_page_favicons) {
-  bool is_create_shortcut = flow_ == WebAppInstallFlow::kCreateShortcut;
-  // Background installations are not a user-triggered installs, and thus
-  // cannot be sent to the store.
-  bool skip_store =
-      is_create_shortcut || background_installation_ || !opt_manifest;
-
-  if (!skip_store) {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-    absl::optional<PlayStoreIntent> intent =
-        GetPlayStoreIntentFromManifest(*opt_manifest);
-    if (intent) {
-      auto* arc_service_manager = arc::ArcServiceManager::Get();
-      if (arc_service_manager) {
-        auto* instance = ARC_GET_INSTANCE_FOR_METHOD(
-            arc_service_manager->arc_bridge_service()->app(), IsInstallable);
-        if (instance) {
-          instance->IsInstallable(
-              intent->app_id,
-              base::BindOnce(&WebAppInstallTask::OnDidCheckForIntentToPlayStore,
-                             GetWeakPtr(), std::move(web_app_info),
-                             std::move(icon_urls), skip_page_favicons,
-                             intent->intent));
-          return;
-        }
-      }
-    }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-    if (ShouldInteractWithArc()) {
-      absl::optional<PlayStoreIntent> intent =
-          GetPlayStoreIntentFromManifest(*opt_manifest);
-      mojo::Remote<crosapi::mojom::Arc>* opt_arc = GetArcRemoteWithMinVersion(
-          crosapi::mojom::Arc::MethodMinVersions::kIsInstallableMinVersion);
-      if (opt_arc && intent) {
-        mojo::Remote<crosapi::mojom::Arc>& arc = *opt_arc;
-        arc->IsInstallable(
-            intent->app_id,
-            base::BindOnce(
-                &WebAppInstallTask::OnDidCheckForIntentToPlayStoreLacros,
-                GetWeakPtr(), std::move(web_app_info), std::move(icon_urls),
-                skip_page_favicons, intent->intent));
-        return;
-      }
-    }
-#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
-  }
-  OnDidCheckForIntentToPlayStore(std::move(web_app_info), std::move(icon_urls),
-                                 skip_page_favicons,
-                                 /*intent=*/"",
-                                 /*should_intent_to_store=*/false);
-}
-
-void WebAppInstallTask::OnDidCheckForIntentToPlayStore(
-    std::unique_ptr<WebAppInstallInfo> web_app_info,
-    base::flat_set<GURL> icon_urls,
-    bool skip_page_favicons,
-    const std::string& intent,
-    bool should_intent_to_store) {
-  if (ShouldStopInstall())
-    return;
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  if (should_intent_to_store && !intent.empty()) {
-    auto* arc_service_manager = arc::ArcServiceManager::Get();
-    if (arc_service_manager) {
-      auto* instance = ARC_GET_INSTANCE_FOR_METHOD(
-          arc_service_manager->arc_bridge_service()->intent_helper(),
-          HandleUrl);
-      if (instance) {
-        instance->HandleUrl(intent, kPlayStorePackage);
-        CallInstallCallback(AppId(),
-                            webapps::InstallResultCode::kIntentToPlayStore);
-        return;
-      }
-    }
-  }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  if (ShouldInteractWithArc() && should_intent_to_store && !intent.empty()) {
-    mojo::Remote<crosapi::mojom::Arc>* opt_arc = GetArcRemoteWithMinVersion(
-        crosapi::mojom::Arc::MethodMinVersions::kHandleUrlMinVersion);
-    if (opt_arc) {
-      mojo::Remote<crosapi::mojom::Arc>& arc = *opt_arc;
-      arc->HandleUrl(intent, kPlayStorePackage);
-      CallInstallCallback(AppId(),
-                          webapps::InstallResultCode::kIntentToPlayStore);
-      return;
-    }
-  }
-#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
-
-  data_retriever_->GetIcons(
-      web_contents(), std::move(icon_urls), skip_page_favicons,
-      base::BindOnce(&WebAppInstallTask::OnIconsRetrievedShowDialog,
-                     GetWeakPtr(), std::move(web_app_info)));
-}
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-void WebAppInstallTask::OnDidCheckForIntentToPlayStoreLacros(
-    std::unique_ptr<WebAppInstallInfo> web_app_info,
-    base::flat_set<GURL> icon_urls,
-    bool skip_page_favicons,
-    const std::string& intent,
-    crosapi::mojom::IsInstallableResult result) {
-  OnDidCheckForIntentToPlayStore(
-      std::move(web_app_info), std::move(icon_urls), skip_page_favicons, intent,
-      result == crosapi::mojom::IsInstallableResult::kInstallable);
-}
-#endif
-
-void WebAppInstallTask::OnIconsRetrievedShowDialog(
-    std::unique_ptr<WebAppInstallInfo> web_app_info,
-    IconsDownloadedResult result,
-    IconsMap icons_map,
-    DownloadedIconsHttpResults icons_http_results) {
-  if (ShouldStopInstall())
-    return;
-
-  DCHECK(web_app_info);
-
-  PopulateProductIcons(web_app_info.get(), &icons_map);
-  PopulateOtherIcons(web_app_info.get(), icons_map);
-
-  RecordDownloadedIconsResultAndHttpStatusCodes(result, icons_http_results);
-  log_entry_.LogDownloadedIconsErrors(*web_app_info, result, icons_map,
-                                      icons_http_results);
-
-  if (background_installation_) {
-    DCHECK(!dialog_callback_);
-    OnDialogCompleted(/*user_accepted=*/true, std::move(web_app_info));
-  } else {
-    DCHECK(dialog_callback_);
-    std::move(dialog_callback_)
-        .Run(web_contents(), std::move(web_app_info),
-             base::BindOnce(&WebAppInstallTask::OnDialogCompleted,
-                            GetWeakPtr()));
-  }
-}
-
-void WebAppInstallTask::OnDialogCompleted(
-    bool user_accepted,
-    std::unique_ptr<WebAppInstallInfo> web_app_info) {
-  if (ShouldStopInstall())
-    return;
-
-  if (!user_accepted) {
-    CallInstallCallback(AppId(),
-                        webapps::InstallResultCode::kUserInstallDeclined);
-    return;
-  }
-
-  if (only_retrieve_web_app_install_info_) {
-    if (web_app_info) {
-      web_app_install_info_ = std::move(*web_app_info);
-      web_app_info.reset();
-    }
-    CallInstallCallback(AppId(),
-                        webapps::InstallResultCode::kSuccessNewInstall);
-    return;
-  }
-
-  WebAppInstallInfo web_app_info_copy = web_app_info->Clone();
-
-  // This metric is recorded regardless of the installation result.
-  RecordInstallEvent();
-
-  WebAppInstallFinalizer::FinalizeOptions finalize_options(install_surface_);
-
-  if (install_params_) {
-    finalize_options.locally_installed = install_params_->locally_installed;
-    finalize_options.overwrite_existing_manifest_fields =
-        install_params_->force_reinstall;
-
-    ApplyParamsToFinalizeOptions(*install_params_, finalize_options);
-
-    if (install_params_->user_display_mode.has_value())
-      web_app_info_copy.user_display_mode = install_params_->user_display_mode;
-    finalize_options.add_to_applications_menu =
-        install_params_->add_to_applications_menu;
-    finalize_options.add_to_desktop = install_params_->add_to_desktop;
-    finalize_options.add_to_quick_launch_bar =
-        install_params_->add_to_quick_launch_bar;
-  } else {
-    finalize_options.locally_installed = true;
-    finalize_options.overwrite_existing_manifest_fields = true;
-    finalize_options.add_to_applications_menu = true;
-    finalize_options.add_to_desktop = true;
-    finalize_options.add_to_quick_launch_bar =
-        kAddAppsToQuickLaunchBarByDefault;
-  }
-
-  install_finalizer_->FinalizeInstall(
-      web_app_info_copy, finalize_options,
-      base::BindOnce(&WebAppInstallTask::OnInstallFinalizedMaybeReparentTab,
-                     GetWeakPtr(), std::move(web_app_info)));
-
-  // Check that the finalizer hasn't called OnInstallFinalizedMaybeReparentTab
-  // synchronously:
-  DCHECK(install_callback_);
-}
-
-void WebAppInstallTask::OnInstallFinalized(const AppId& app_id,
-                                           webapps::InstallResultCode code,
-                                           OsHooksErrors os_hooks_errors) {
-  CallInstallCallback(app_id, code);
-}
-
-void WebAppInstallTask::OnInstallFinalizedMaybeReparentTab(
-    std::unique_ptr<WebAppInstallInfo> web_app_info,
-    const AppId& app_id,
-    webapps::InstallResultCode code,
-    OsHooksErrors os_hooks_errors) {
-  if (ShouldStopInstall())
-    return;
-
-  if (code != webapps::InstallResultCode::kSuccessNewInstall) {
-    CallInstallCallback(app_id, code);
-    return;
-  }
-
-  RecordWebAppInstallationTimestamp(profile_->GetPrefs(), app_id,
-                                    install_surface_);
-
-  if (install_params_ && !install_params_->locally_installed) {
-    DCHECK(background_installation_);
-  }
-
-  if (!install_params_ || install_params_->locally_installed) {
-    RecordAppBanner(web_contents(), web_app_info->start_url);
-  } else {
-    DCHECK(background_installation_);
-  }
-
-  if (!background_installation_ &&
-      install_surface_ != webapps::WebappInstallSource::SUB_APP) {
-    bool error = os_hooks_errors[OsHookType::kShortcuts];
-    const bool can_reparent_tab =
-        install_finalizer_->CanReparentTab(app_id, !error);
-
-    if (can_reparent_tab &&
-        (web_app_info->user_display_mode != mojom::UserDisplayMode::kBrowser)) {
-      install_finalizer_->ReparentTab(app_id, !error, web_contents());
-    }
-  }
-  CallInstallCallback(app_id, webapps::InstallResultCode::kSuccessNewInstall);
-}
-
-void WebAppInstallTask::RecordDownloadedIconsResultAndHttpStatusCodes(
-    IconsDownloadedResult result,
-    const DownloadedIconsHttpResults& icons_http_results) {
-  RecordDownloadedIconsHttpResultsCodeClass(
-      "WebApp.Icon.HttpStatusCodeClassOnCreate", result, icons_http_results);
-
-  UMA_HISTOGRAM_ENUMERATION("WebApp.Icon.DownloadedResultOnCreate", result);
-  RecordDownloadedIconHttpStatusCodes(
-      "WebApp.Icon.DownloadedHttpStatusCodeOnCreate", icons_http_results);
-}
-
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_task.h b/chrome/browser/web_applications/web_app_install_task.h
index f5a03718..fe558c09 100644
--- a/chrome/browser/web_applications/web_app_install_task.h
+++ b/chrome/browser/web_applications/web_app_install_task.h
@@ -6,37 +6,8 @@
 #define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_INSTALL_TASK_H_
 
 #include <memory>
-#include <string>
-#include <vector>
 
-#include "base/functional/callback.h"
-#include "base/memory/raw_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/values.h"
-#include "build/chromeos_buildflags.h"
-#include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
-#include "chrome/browser/web_applications/web_app_install_finalizer.h"
-#include "chrome/browser/web_applications/web_app_install_info.h"
-#include "chrome/browser/web_applications/web_app_install_manager.h"
-#include "chrome/browser/web_applications/web_app_install_params.h"
-#include "chrome/browser/web_applications/web_app_install_utils.h"
-#include "chrome/browser/web_applications/web_app_logging.h"
-#include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
-#include "components/webapps/browser/install_result_code.h"
-#include "components/webapps/browser/installable/installable_logging.h"
-#include "components/webapps/browser/installable/installable_metrics.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "chromeos/crosapi/mojom/arc.mojom-forward.h"
-#endif
-
-class GURL;
 class Profile;
-struct WebAppInstallInfo;
 
 namespace content {
 class WebContents;
@@ -44,211 +15,11 @@
 
 namespace web_app {
 
-class WebAppDataRetriever;
-class WebAppUrlLoader;
-class WebAppRegistrar;
-
-// Used to do a variety of tasks involving installing web applications. Only one
-// of the public Load*, Update*, or Install* methods can be called on a single
-// object. WebAppInstallManager is a queue of WebAppInstallTask jobs. Basically,
-// WebAppInstallTask is an implementation detail of WebAppInstallManager.
-class WebAppInstallTask : content::WebContentsObserver {
+// TODO(https://crbug.com/1427768): Delete this file.
+class WebAppInstallTask {
  public:
-  using WebAppInstallInfoOrErrorCode =
-      absl::variant<WebAppInstallInfo, webapps::InstallResultCode>;
-  using RetrieveWebAppInstallInfoWithIconsCallback =
-      base::OnceCallback<void(WebAppInstallInfoOrErrorCode)>;
-
-  WebAppInstallTask(Profile* profile,
-                    WebAppInstallFinalizer* install_finalizer,
-                    std::unique_ptr<WebAppDataRetriever> data_retriever,
-                    WebAppRegistrar* registrar,
-                    webapps::WebappInstallSource install_surface);
-  WebAppInstallTask(const WebAppInstallTask&) = delete;
-  WebAppInstallTask& operator=(const WebAppInstallTask&) = delete;
-  ~WebAppInstallTask() override;
-
-  // Request the app_id expectation check. Install fails with
-  // kExpectedAppIdCheckFailed if actual app_id doesn't match expected app_id.
-  // The actual resulting app_id is reported as a part of OnceInstallCallback.
-  void ExpectAppId(const AppId& expected_app_id);
-  const absl::optional<AppId>& app_id_to_expect() const {
-    return expected_app_id_;
-  }
-
-  // Checks a WebApp installability, retrieves manifest and icons and
-  // then performs the actual installation.
-  void InstallWebAppFromManifest(content::WebContents* web_contents,
-                                 bool bypass_service_worker_check,
-                                 WebAppInstallDialogCallback dialog_callback,
-                                 OnceInstallCallback callback);
-
-  // This method infers WebApp info from the blink renderer process
-  // and then retrieves a manifest in a way similar to
-  // |InstallWebAppFromManifest|. If manifest is incomplete or missing, the
-  // inferred info is used.
-  void InstallWebAppFromManifestWithFallback(
-      content::WebContents* web_contents,
-      WebAppInstallFlow flow,
-      WebAppInstallDialogCallback dialog_callback,
-      OnceInstallCallback callback);
-
-  // Starts a web app installation process using prefilled
-  // |web_app_install_info| which holds all the data needed for installation.
-  // WebAppInstallManager doesn't fetch a manifest.
-  void InstallWebAppFromInfo(
-      std::unique_ptr<WebAppInstallInfo> web_app_install_info,
-      bool overwrite_existing_manifest_fields,
-      OnceInstallCallback callback);
-
-  // Obtains WebAppInstallInfo about web app located at |start_url|, fallbacks
-  // to title/favicon if manifest is not present.
-  void LoadAndRetrieveWebAppInstallInfoWithIcons(
-      const GURL& start_url,
-      WebAppUrlLoader* url_loader,
-      RetrieveWebAppInstallInfoWithIconsCallback callback);
-
   static std::unique_ptr<content::WebContents> CreateWebContents(
       Profile* profile);
-
-  // Returns the pre-existing web contents the installation was initiated with,
-  // or the one created specifically for the install task.
-  content::WebContents* GetInstallingWebContents();
-
-  base::WeakPtr<WebAppInstallTask> GetWeakPtr();
-
-  // WebContentsObserver:
-  void WebContentsDestroyed() override;
-
-  // Collects install errors (unbounded) if the |kRecordWebAppDebugInfo|
-  // flag is enabled to be used by: chrome://web-app-internals
-  base::Value::Dict TakeErrorDict();
-
-  void SetInstallFinalizerForTesting(
-      WebAppInstallFinalizer* install_finalizer) {
-    install_finalizer_ = install_finalizer;
-  }
-
-  void SetFlowForTesting(WebAppInstallFlow flow) { flow_ = flow; }
-
-  static void UpdateFinalizerClientData(
-      const absl::optional<WebAppInstallParams>& params,
-      WebAppInstallFinalizer::FinalizeOptions* options);
-
- private:
-  void CheckInstallPreconditions();
-  void RecordInstallEvent();
-
-  // Calling the callback may destroy |this| task. Callers shouldn't work with
-  // any |this| class members after calling it.
-  void CallInstallCallback(const AppId& app_id,
-                           webapps::InstallResultCode code);
-
-  // Checks if any errors occurred while |this| was async awaiting. All On*
-  // completion handlers below must return early if this is true. Also, if
-  // ShouldStopInstall is true, install_callback_ is already invoked or may be
-  // invoked later: All On* completion handlers don't need to call
-  // install_callback_.
-  bool ShouldStopInstall() const;
-
-  void OnWebAppUrlLoadedGetWebAppInstallInfo(const GURL& url_to_load,
-                                             WebAppUrlLoader::Result result);
-
-  void OnGetWebAppInstallInfo(std::unique_ptr<WebAppInstallInfo> web_app_info);
-
-  void OnDidPerformInstallableCheck(
-      std::unique_ptr<WebAppInstallInfo> web_app_info,
-      blink::mojom::ManifestPtr opt_manifest,
-      const GURL& manifest_url,
-      bool valid_manifest_for_web_app,
-      webapps::InstallableStatusCode error_code);
-
-  // Either dispatches an asynchronous check for whether this installation
-  // should be stopped and an intent to the Play Store should be made, or
-  // synchronously calls OnDidCheckForIntentToPlayStore() implicitly failing the
-  // check if it cannot be made.
-  void CheckForPlayStoreIntentOrGetIcons(
-      blink::mojom::ManifestPtr opt_manifest,
-      std::unique_ptr<WebAppInstallInfo> web_app_info,
-      base::flat_set<GURL> icon_urls,
-      bool skip_page_favicons);
-
-  // Called when the asynchronous check for whether an intent to the Play Store
-  // should be made returns.
-  void OnDidCheckForIntentToPlayStore(
-      std::unique_ptr<WebAppInstallInfo> web_app_info,
-      base::flat_set<GURL> icon_urls,
-      bool skip_page_favicons,
-      const std::string& intent,
-      bool should_intent_to_store);
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  // Called when the asynchronous check for whether an intent to the Play Store
-  // should be made returns (Lacros adapter that calls
-  // |OnDidCheckForIntentToPlayStore| based on |result|).
-  void OnDidCheckForIntentToPlayStoreLacros(
-      std::unique_ptr<WebAppInstallInfo> web_app_info,
-      base::flat_set<GURL> icon_urls,
-      bool skip_page_favicons,
-      const std::string& intent,
-      crosapi::mojom::IsInstallableResult result);
-#endif
-
-  void OnIconsRetrievedShowDialog(
-      std::unique_ptr<WebAppInstallInfo> web_app_info,
-      IconsDownloadedResult result,
-      IconsMap icons_map,
-      DownloadedIconsHttpResults icons_http_results);
-  void OnDialogCompleted(bool user_accepted,
-                         std::unique_ptr<WebAppInstallInfo> web_app_info);
-  void OnInstallFinalized(const AppId& app_id,
-                          webapps::InstallResultCode code,
-                          OsHooksErrors os_hooks_errors);
-  void OnInstallFinalizedMaybeReparentTab(
-      std::unique_ptr<WebAppInstallInfo> web_app_info,
-      const AppId& app_id,
-      webapps::InstallResultCode code,
-      OsHooksErrors os_hooks_errors);
-  void OnOsHooksCreated(DisplayMode user_display_mode,
-                        const AppId& app_id,
-                        OsHooksErrors os_hook_errors);
-
-  void RecordDownloadedIconsResultAndHttpStatusCodes(
-      IconsDownloadedResult result,
-      const DownloadedIconsHttpResults& icons_http_results);
-
-  std::unique_ptr<WebAppDataRetriever> data_retriever_;
-  raw_ptr<WebAppInstallFinalizer> install_finalizer_;
-  const raw_ptr<Profile> profile_;
-  raw_ptr<WebAppRegistrar> registrar_;
-
-  webapps::WebappInstallSource install_surface_;
-
-  // Whether the install task has been 'initiated' by calling one of the public
-  // methods.
-  bool initiated_ = false;
-
-  // Whether we should just obtain WebAppInstallInfo instead of the actual
-  // installation.
-  bool only_retrieve_web_app_install_info_ = false;
-
-  WebAppInstallDialogCallback dialog_callback_;
-  OnceInstallCallback install_callback_;
-  RetrieveWebAppInstallInfoWithIconsCallback retrieve_info_callback_;
-  absl::optional<WebAppInstallParams> install_params_;
-  absl::optional<AppId> expected_app_id_;
-  bool background_installation_ = false;
-
-  absl::optional<WebAppInstallInfo> web_app_install_info_;
-  std::unique_ptr<content::WebContents> web_contents_;
-
-  InstallErrorLogEntry log_entry_;
-
-  // TODO(crbug.com/1216457): Make this enum const and set its value in the
-  // constructor.
-  WebAppInstallFlow flow_ = WebAppInstallFlow::kUnknown;
-
-  base::WeakPtrFactory<WebAppInstallTask> weak_ptr_factory_{this};
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc
deleted file mode 100644
index e21f3dc..0000000
--- a/chrome/browser/web_applications/web_app_install_task_unittest.cc
+++ /dev/null
@@ -1,1353 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/web_applications/web_app_install_task.h"
-
-#include <array>
-#include <memory>
-#include <utility>
-
-#include "base/files/file_path.h"
-#include "base/functional/bind.h"
-#include "base/functional/callback.h"
-#include "base/memory/raw_ptr.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/bind.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
-#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
-#include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
-#include "chrome/browser/web_applications/test/fake_data_retriever.h"
-#include "chrome/browser/web_applications/test/fake_install_finalizer.h"
-#include "chrome/browser/web_applications/test/fake_os_integration_manager.h"
-#include "chrome/browser/web_applications/test/fake_web_app_database_factory.h"
-#include "chrome/browser/web_applications/test/fake_web_app_provider.h"
-#include "chrome/browser/web_applications/test/fake_web_app_ui_manager.h"
-#include "chrome/browser/web_applications/test/test_web_app_url_loader.h"
-#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h"
-#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
-#include "chrome/browser/web_applications/test/web_app_test.h"
-#include "chrome/browser/web_applications/test/web_app_test_utils.h"
-#include "chrome/browser/web_applications/web_app.h"
-#include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_icon_generator.h"
-#include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_install_finalizer.h"
-#include "chrome/browser/web_applications/web_app_install_info.h"
-#include "chrome/browser/web_applications/web_app_install_manager.h"
-#include "chrome/browser/web_applications/web_app_install_params.h"
-#include "chrome/browser/web_applications/web_app_install_utils.h"
-#include "chrome/browser/web_applications/web_app_registrar.h"
-#include "chrome/browser/web_applications/web_app_registry_update.h"
-#include "chrome/browser/web_applications/web_app_sync_bridge.h"
-#include "chrome/browser/web_applications/web_app_utils.h"
-#include "chrome/common/chrome_features.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "chrome/test/base/testing_profile.h"
-#include "chrome/test/base/testing_profile_manager.h"
-#include "components/webapps/browser/features.h"
-#include "components/webapps/browser/install_result_code.h"
-#include "components/webapps/browser/installable/installable_data.h"
-#include "components/webapps/browser/installable/installable_logging.h"
-#include "components/webapps/browser/installable/installable_metrics.h"
-#include "net/http/http_status_code.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "url/gurl.h"
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "ash/components/arc/mojom/intent_helper.mojom.h"
-#include "ash/components/arc/session/arc_bridge_service.h"
-#include "ash/components/arc/session/arc_service_manager.h"
-#include "ash/components/arc/test/connection_holder_util.h"
-#include "ash/components/arc/test/fake_app_instance.h"
-#include "chrome/browser/ash/app_list/arc/arc_app_test.h"
-#include "components/arc/test/fake_intent_helper_host.h"
-#include "components/arc/test/fake_intent_helper_instance.h"
-#endif
-
-namespace web_app {
-
-class WebAppInstallTaskTest : public WebAppTest {
- public:
-  void SetUp() override {
-    WebAppTest::SetUp();
-
-    provider_ = web_app::FakeWebAppProvider::Get(profile());
-    auto install_manager = std::make_unique<WebAppInstallManager>(profile());
-    install_manager_ = install_manager.get();
-    provider_->SetInstallManager(std::move(install_manager));
-
-    auto install_finalizer =
-        std::make_unique<WebAppInstallFinalizer>(profile());
-    install_finalizer_ = install_finalizer.get();
-    provider_->SetInstallFinalizer(std::move(install_finalizer));
-
-    test::AwaitStartWebAppProviderAndSubsystems(profile());
-
-    url_loader_ = std::make_unique<TestWebAppUrlLoader>();
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-    arc_test_.SetUp(profile());
-
-    auto* arc_bridge_service =
-        arc_test_.arc_service_manager()->arc_bridge_service();
-    fake_intent_helper_host_ = std::make_unique<arc::FakeIntentHelperHost>(
-        arc_bridge_service->intent_helper());
-    fake_intent_helper_instance_ =
-        std::make_unique<arc::FakeIntentHelperInstance>();
-    arc_bridge_service->intent_helper()->SetInstance(
-        fake_intent_helper_instance_.get());
-    WaitForInstanceReady(arc_bridge_service->intent_helper());
-#endif
-  }
-
-  void TearDown() override {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-    arc_test_.arc_service_manager()
-        ->arc_bridge_service()
-        ->intent_helper()
-        ->CloseInstance(fake_intent_helper_instance_.get());
-    fake_intent_helper_instance_.reset();
-    fake_intent_helper_host_.reset();
-    arc_test_.TearDown();
-#endif
-    url_loader_.reset();
-    install_task_.reset();
-    fake_install_finalizer_.reset();
-    provider_->Shutdown();
-
-    WebAppTest::TearDown();
-  }
-
-  void CreateRendererAppInfo(const GURL& url,
-                             const std::string& name,
-                             const std::string& description,
-                             const GURL& scope,
-                             absl::optional<SkColor> theme_color,
-                             mojom::UserDisplayMode user_display_mode) {
-    auto web_app_info = std::make_unique<WebAppInstallInfo>();
-
-    web_app_info->start_url = url;
-    web_app_info->title = base::UTF8ToUTF16(name);
-    web_app_info->description = base::UTF8ToUTF16(description);
-    web_app_info->scope = scope;
-    web_app_info->theme_color = theme_color;
-    web_app_info->user_display_mode = user_display_mode;
-
-    data_retriever_->SetRendererWebAppInstallInfo(std::move(web_app_info));
-  }
-
-  void CreateRendererAppInfo(const GURL& url,
-                             const std::string& name,
-                             const std::string& description) {
-    CreateRendererAppInfo(
-        url, name, description, GURL(), absl::nullopt,
-        /*user_display_mode=*/mojom::UserDisplayMode::kStandalone);
-  }
-
-  void InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource install_surface) {
-    auto data_retriever = std::make_unique<FakeDataRetriever>();
-    data_retriever_ = static_cast<FakeDataRetriever*>(data_retriever.get());
-
-    install_task_ = std::make_unique<WebAppInstallTask>(
-        profile(), install_finalizer_.get(), std::move(data_retriever),
-        &registrar(), install_surface);
-  }
-
-  void SetInstallFinalizerForTesting() {
-    fake_install_finalizer_ = std::make_unique<FakeInstallFinalizer>();
-    install_finalizer_ = fake_install_finalizer_.get();
-    if (install_task_)
-      install_task_->SetInstallFinalizerForTesting(
-          fake_install_finalizer_.get());
-  }
-
-  void CreateDefaultDataToRetrieve(const GURL& url, const GURL& scope) {
-    DCHECK(data_retriever_);
-    data_retriever_->BuildDefaultDataToRetrieve(url, scope);
-  }
-
-  void CreateDefaultDataToRetrieve(const GURL& url) {
-    CreateDefaultDataToRetrieve(url, GURL{});
-  }
-
-  void CreateDataToRetrieve(const GURL& url,
-                            mojom::UserDisplayMode user_display_mode) {
-    DCHECK(data_retriever_);
-
-    auto renderer_web_app_info = std::make_unique<WebAppInstallInfo>();
-    renderer_web_app_info->user_display_mode = user_display_mode;
-    data_retriever_->SetRendererWebAppInstallInfo(
-        std::move(renderer_web_app_info));
-
-    auto manifest = blink::mojom::Manifest::New();
-    manifest->start_url = url;
-    manifest->short_name = u"Manifest Name";
-    data_retriever_->SetManifest(
-        std::move(manifest), webapps::InstallableStatusCode::NO_ERROR_DETECTED);
-
-    data_retriever_->SetIcons(IconsMap{});
-  }
-
-  FakeInstallFinalizer& fake_install_finalizer() {
-    DCHECK(fake_install_finalizer_);
-    return *fake_install_finalizer_;
-  }
-
-  // Sets IconsMap, IconsDownloadedResult and corresponding `http_status_codes`
-  // to populate DownloadedIconsHttpResults.
-  void SetIconsMapToRetrieve(IconsMap icons_map,
-                             IconsDownloadedResult result,
-                             const std::vector<int>& http_status_codes) {
-    DCHECK_EQ(icons_map.size(), http_status_codes.size());
-    DCHECK(data_retriever_);
-
-    data_retriever_->SetIconsDownloadedResult(result);
-
-    int icon_index = 0;
-    DownloadedIconsHttpResults http_results;
-    for (const auto& url_and_bitmap : icons_map) {
-      http_results[url_and_bitmap.first] = http_status_codes[icon_index];
-      ++icon_index;
-    }
-    data_retriever_->SetDownloadedIconsHttpResults(std::move(http_results));
-
-    // Moves `icons_map` last.
-    data_retriever_->SetIcons(std::move(icons_map));
-  }
-
-  struct InstallResult {
-    AppId app_id;
-    webapps::InstallResultCode code;
-    OsHooksErrors os_hooks_errors;
-  };
-
-  InstallResult InstallWebAppFromManifestWithFallbackAndGetResults() {
-    InstallResult result;
-    base::RunLoop run_loop;
-    if (!install_task_)
-      InitializeInstallTaskAndRetriever(
-          webapps::WebappInstallSource::MENU_BROWSER_TAB);
-    install_task_->InstallWebAppFromManifestWithFallback(
-        web_contents(), WebAppInstallFlow::kInstallSite,
-        base::BindOnce(test::TestAcceptDialogCallback),
-        base::BindLambdaForTesting([&](const AppId& installed_app_id,
-                                       webapps::InstallResultCode code) {
-          result.app_id = installed_app_id;
-          result.code = code;
-          run_loop.Quit();
-        }));
-    run_loop.Run();
-    return result;
-  }
-
-  WebAppInstallTask::WebAppInstallInfoOrErrorCode
-  LoadAndRetrieveWebAppInstallInfoWithIcons(const GURL& url) {
-    WebAppInstallTask::WebAppInstallInfoOrErrorCode result;
-    base::RunLoop run_loop;
-    if (!install_task_)
-      InitializeInstallTaskAndRetriever(
-          webapps::WebappInstallSource::MENU_BROWSER_TAB);
-    install_task_->LoadAndRetrieveWebAppInstallInfoWithIcons(
-        url, &url_loader(),
-        base::BindLambdaForTesting(
-            [&](WebAppInstallTask::WebAppInstallInfoOrErrorCode info_or_error) {
-              result = std::move(info_or_error);
-              run_loop.Quit();
-            }));
-    run_loop.Run();
-    return result;
-  }
-
-  AppId InstallWebAppFromManifestWithFallback() {
-    InstallResult result = InstallWebAppFromManifestWithFallbackAndGetResults();
-    DCHECK_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
-    return result.app_id;
-  }
-
-  void PrepareTestAppInstall(webapps::WebappInstallSource install_surface) {
-    const GURL url{"https://example.com/path"};
-    InitializeInstallTaskAndRetriever(install_surface);
-    CreateDefaultDataToRetrieve(url);
-    CreateRendererAppInfo(url, "Name", "Description");
-
-    SetInstallFinalizerForTesting();
-
-    data_retriever_->SetIconsDownloadedResult(
-        IconsDownloadedResult::kPrimaryPageChanged);
-    data_retriever_->SetDownloadedIconsHttpResults(
-        DownloadedIconsHttpResults{});
-    data_retriever_->SetIcons(IconsMap{});
-  }
-
- protected:
-  WebAppInstallTask& install_task() { return *install_task_; }
-  FakeWebAppProvider& provider() { return *provider_; }
-
-  WebAppRegistrar& registrar() { return provider().registrar_unsafe(); }
-  FakeOsIntegrationManager& fake_os_integration_manager() {
-    return static_cast<FakeOsIntegrationManager&>(
-        provider().os_integration_manager());
-  }
-  TestWebAppUrlLoader& url_loader() { return *url_loader_; }
-  FakeDataRetriever& data_retriever() {
-    DCHECK(data_retriever_);
-    return *data_retriever_;
-  }
-
-  WebAppInstallManager& install_manager() const { return *install_manager_; }
-
-  std::unique_ptr<WebAppInstallTask> install_task_;
-
-  // Owned by install_task_:
-  raw_ptr<WebAppInstallFinalizer> install_finalizer_;
-  raw_ptr<FakeDataRetriever> data_retriever_ = nullptr;
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  ArcAppTest arc_test_;
-  std::unique_ptr<arc::FakeIntentHelperHost> fake_intent_helper_host_;
-  std::unique_ptr<arc::FakeIntentHelperInstance> fake_intent_helper_instance_;
-#endif
-
-  const base::HistogramTester& histogram_tester() const {
-    return histogram_tester_;
-  }
-
- private:
-  raw_ptr<FakeWebAppProvider> provider_;
-  raw_ptr<WebAppInstallManager> install_manager_;
-
-  std::unique_ptr<TestWebAppUrlLoader> url_loader_;
-  std::unique_ptr<FakeInstallFinalizer> fake_install_finalizer_;
-  base::HistogramTester histogram_tester_;
-};
-
-class WebAppInstallTaskWithRunOnOsLoginTest : public WebAppInstallTaskTest {
- public:
-  WebAppInstallTaskWithRunOnOsLoginTest() {
-    scoped_feature_list_.InitWithFeatures({features::kDesktopPWAsRunOnOsLogin},
-                                          {});
-  }
-
-  ~WebAppInstallTaskWithRunOnOsLoginTest() override = default;
-
-  void CreateRendererAppInfo(const GURL& url,
-                             const std::string& name,
-                             const std::string& description,
-                             const GURL& scope,
-                             absl::optional<SkColor> theme_color,
-                             mojom::UserDisplayMode user_display_mode) {
-    auto web_app_info = std::make_unique<WebAppInstallInfo>();
-
-    web_app_info->start_url = url;
-    web_app_info->title = base::UTF8ToUTF16(name);
-    web_app_info->description = base::UTF8ToUTF16(description);
-    web_app_info->scope = scope;
-    web_app_info->theme_color = theme_color;
-    web_app_info->user_display_mode = user_display_mode;
-
-    data_retriever_->SetRendererWebAppInstallInfo(std::move(web_app_info));
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_F(WebAppInstallTaskTest, InstallFromWebContents) {
-  EXPECT_TRUE(AreWebAppsUserInstallable(profile()));
-
-  const GURL url = GURL("https://example.com/scope/path");
-  const std::string manifest_name = "Manifest Name";
-  const std::string description = "Description";
-  const GURL scope = GURL("https://example.com/scope");
-  const absl::optional<SkColor> theme_color = 0xFFAABBCC;
-
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  CreateRendererAppInfo(
-      url, "Renderer Name", description, /*scope*/ GURL{}, theme_color,
-      /*user_display_mode=*/mojom::UserDisplayMode::kStandalone);
-  {
-    auto manifest = blink::mojom::Manifest::New();
-    manifest->start_url = url;
-    manifest->scope = scope;
-    manifest->short_name = base::ASCIIToUTF16(manifest_name);
-
-    data_retriever().SetManifest(
-        std::move(manifest), webapps::InstallableStatusCode::NO_ERROR_DETECTED);
-  }
-
-  base::RunLoop run_loop;
-  bool callback_called = false;
-
-  install_task_->InstallWebAppFromManifestWithFallback(
-      web_contents(), WebAppInstallFlow::kInstallSite,
-      base::BindOnce(test::TestAcceptDialogCallback),
-      base::BindLambdaForTesting(
-          [&](const AppId& installed_app_id, webapps::InstallResultCode code) {
-            EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
-            EXPECT_EQ(app_id, installed_app_id);
-            callback_called = true;
-            run_loop.Quit();
-          }));
-  run_loop.Run();
-
-  EXPECT_TRUE(callback_called);
-
-  const WebApp* web_app = registrar().GetAppById(app_id);
-  EXPECT_NE(nullptr, web_app);
-
-  EXPECT_EQ(app_id, web_app->app_id());
-  EXPECT_EQ(manifest_name, web_app->untranslated_name());
-  EXPECT_EQ(description, web_app->untranslated_description());
-  EXPECT_EQ(url, web_app->start_url());
-  EXPECT_EQ(scope, web_app->scope());
-  EXPECT_EQ(theme_color, web_app->theme_color());
-  EXPECT_EQ(0u,
-            fake_os_integration_manager().num_register_run_on_os_login_calls());
-}
-
-TEST_F(WebAppInstallTaskTest, ForceReinstall) {
-  const GURL url = GURL("https://example.com/path");
-
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  CreateDefaultDataToRetrieve(url);
-  CreateRendererAppInfo(url, "Renderer Name", "Renderer Description");
-
-  const AppId installed_web_app = InstallWebAppFromManifestWithFallback();
-  EXPECT_EQ(app_id, installed_web_app);
-
-  // Force reinstall:
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  CreateRendererAppInfo(url, "Renderer Name2", "Renderer Description2");
-  {
-    auto manifest = blink::mojom::Manifest::New();
-    manifest->start_url = url;
-    manifest->scope = url;
-    manifest->short_name = u"Manifest Name2";
-
-    data_retriever().SetManifest(
-        std::move(manifest), webapps::InstallableStatusCode::NO_ERROR_DETECTED);
-  }
-
-  base::RunLoop run_loop;
-  bool callback_called = false;
-
-  install_task_->InstallWebAppFromManifestWithFallback(
-      web_contents(), WebAppInstallFlow::kInstallSite,
-      base::BindOnce(test::TestAcceptDialogCallback),
-      base::BindLambdaForTesting([&](const AppId& force_installed_app_id,
-                                     webapps::InstallResultCode code) {
-        EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
-        EXPECT_EQ(app_id, force_installed_app_id);
-        const WebApp* web_app = registrar().GetAppById(app_id);
-        EXPECT_EQ(web_app->untranslated_name(), "Manifest Name2");
-        EXPECT_EQ(web_app->untranslated_description(), "Renderer Description2");
-        callback_called = true;
-        run_loop.Quit();
-      }));
-  run_loop.Run();
-
-  EXPECT_TRUE(callback_called);
-}
-
-TEST_F(WebAppInstallTaskTest, GetWebAppInstallInfoFailed) {
-  // data_retriever_ with empty info means an error.
-
-  base::RunLoop run_loop;
-  bool callback_called = false;
-
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  install_task_->InstallWebAppFromManifestWithFallback(
-      web_contents(), WebAppInstallFlow::kInstallSite,
-      base::BindOnce(test::TestAcceptDialogCallback),
-      base::BindLambdaForTesting(
-          [&](const AppId& installed_app_id, webapps::InstallResultCode code) {
-            EXPECT_EQ(webapps::InstallResultCode::kGetWebAppInstallInfoFailed,
-                      code);
-            EXPECT_EQ(AppId(), installed_app_id);
-            callback_called = true;
-            run_loop.Quit();
-          }));
-  run_loop.Run();
-
-  EXPECT_TRUE(callback_called);
-}
-
-TEST_F(WebAppInstallTaskTest, WebContentsDestroyed) {
-  const GURL url = GURL("https://example.com/path");
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  CreateDefaultDataToRetrieve(url);
-  CreateRendererAppInfo(url, "Name", "Description");
-
-  base::RunLoop run_loop;
-  bool callback_called = false;
-
-  install_task_->InstallWebAppFromManifestWithFallback(
-      web_contents(), WebAppInstallFlow::kInstallSite,
-      base::BindOnce(test::TestAcceptDialogCallback),
-      base::BindLambdaForTesting(
-          [&](const AppId& installed_app_id, webapps::InstallResultCode code) {
-            EXPECT_EQ(webapps::InstallResultCode::kWebContentsDestroyed, code);
-            EXPECT_EQ(AppId(), installed_app_id);
-            callback_called = true;
-            run_loop.Quit();
-          }));
-
-  // Destroy WebContents.
-  DeleteContents();
-  EXPECT_EQ(nullptr, web_contents());
-
-  run_loop.Run();
-
-  EXPECT_TRUE(callback_called);
-}
-
-TEST_F(WebAppInstallTaskTest, InstallTaskDestroyed) {
-  const GURL url = GURL("https://example.com/path");
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  CreateDefaultDataToRetrieve(url);
-  CreateRendererAppInfo(url, "Name", "Description");
-
-  base::RunLoop run_loop;
-  bool callback_called = false;
-
-  install_task_->InstallWebAppFromManifestWithFallback(
-      web_contents(), WebAppInstallFlow::kInstallSite,
-      base::BindOnce(test::TestAcceptDialogCallback),
-      base::BindLambdaForTesting(
-          [&](const AppId& installed_app_id, webapps::InstallResultCode code) {
-            EXPECT_EQ(webapps::InstallResultCode::kInstallTaskDestroyed, code);
-            EXPECT_EQ(AppId(), installed_app_id);
-            callback_called = true;
-            run_loop.Quit();
-          }));
-
-  // Destroy install task.
-  install_task_.reset();
-
-  run_loop.Run();
-
-  EXPECT_TRUE(callback_called);
-}
-
-TEST_F(WebAppInstallTaskTest, InstallableCheck) {
-  const std::string renderer_description = "RendererDescription";
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  CreateRendererAppInfo(
-      GURL("https://renderer.com/path"), "RendererName", renderer_description,
-      GURL("https://renderer.com/scope"), 0x00,
-      /*user_display_mode=*/mojom::UserDisplayMode::kStandalone);
-
-  const GURL manifest_start_url = GURL("https://example.com/start");
-  const AppId app_id =
-      GenerateAppId(/*manifest_id=*/absl::nullopt, manifest_start_url);
-  const std::string manifest_name = "Name from Manifest";
-  const GURL manifest_scope = GURL("https://example.com/scope");
-  const SkColor manifest_theme_color = 0xAABBCCDD;
-  const absl::optional<SkColor> expected_theme_color = 0xFFBBCCDD;  // Opaque.
-  const auto display_mode = DisplayMode::kMinimalUi;
-
-  {
-    auto manifest = blink::mojom::Manifest::New();
-    manifest->short_name = u"Short Name from Manifest";
-    manifest->name = base::ASCIIToUTF16(manifest_name);
-    manifest->start_url = manifest_start_url;
-    manifest->scope = manifest_scope;
-    manifest->has_theme_color = true;
-    manifest->theme_color = manifest_theme_color;
-    manifest->display = display_mode;
-
-    data_retriever_->SetManifest(
-        std::move(manifest), webapps::InstallableStatusCode::NO_ERROR_DETECTED);
-  }
-
-  base::RunLoop run_loop;
-  bool callback_called = false;
-
-  install_task_->InstallWebAppFromManifestWithFallback(
-      web_contents(), WebAppInstallFlow::kInstallSite,
-      base::BindOnce(test::TestAcceptDialogCallback),
-      base::BindLambdaForTesting(
-          [&](const AppId& installed_app_id, webapps::InstallResultCode code) {
-            EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
-            EXPECT_EQ(app_id, installed_app_id);
-            callback_called = true;
-            run_loop.Quit();
-          }));
-  run_loop.Run();
-
-  EXPECT_TRUE(callback_called);
-
-  const WebApp* web_app = registrar().GetAppById(app_id);
-  EXPECT_NE(nullptr, web_app);
-
-  // Manifest data overrides Renderer data, except |description|.
-  EXPECT_EQ(app_id, web_app->app_id());
-  EXPECT_EQ(manifest_name, web_app->untranslated_name());
-  EXPECT_EQ(manifest_start_url, web_app->start_url());
-  EXPECT_EQ(renderer_description, web_app->untranslated_description());
-  EXPECT_EQ(manifest_scope, web_app->scope());
-  EXPECT_EQ(expected_theme_color, web_app->theme_color());
-  EXPECT_EQ(display_mode, web_app->display_mode());
-}
-
-TEST_F(WebAppInstallTaskTest, InstallWebAppFromInfo_Success) {
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  SetInstallFinalizerForTesting();
-
-  const GURL url = GURL("https://example.com/path");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  auto web_app_info = std::make_unique<WebAppInstallInfo>();
-  web_app_info->start_url = url;
-  web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone;
-  web_app_info->title = u"App Name";
-
-  base::RunLoop run_loop;
-
-  install_task_->SetFlowForTesting(WebAppInstallFlow::kInstallSite);
-  install_task_->InstallWebAppFromInfo(
-      std::move(web_app_info), /*overwrite_existing_manifest_fields=*/false,
-      base::BindLambdaForTesting(
-          [&](const AppId& installed_app_id, webapps::InstallResultCode code) {
-            EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
-            EXPECT_EQ(app_id, installed_app_id);
-
-            std::unique_ptr<WebAppInstallInfo> final_web_app_info =
-                fake_install_finalizer().web_app_info();
-            EXPECT_EQ(final_web_app_info->user_display_mode,
-                      mojom::UserDisplayMode::kStandalone);
-
-            run_loop.Quit();
-          }));
-
-  run_loop.Run();
-}
-
-TEST_F(WebAppInstallTaskTest, InstallWebAppFromInfo_GenerateIcons) {
-  InitializeInstallTaskAndRetriever(webapps::WebappInstallSource::ARC);
-  SetInstallFinalizerForTesting();
-
-  auto web_app_info = std::make_unique<WebAppInstallInfo>();
-  web_app_info->start_url = GURL("https://example.com/path");
-  web_app_info->user_display_mode = mojom::UserDisplayMode::kBrowser;
-  web_app_info->title = u"App Name";
-
-  // Add square yellow icon.
-  AddGeneratedIcon(&web_app_info->icon_bitmaps.any, icon_size::k256,
-                   SK_ColorYELLOW);
-
-  base::RunLoop run_loop;
-
-  install_task_->SetFlowForTesting(WebAppInstallFlow::kInstallSite);
-  install_task_->InstallWebAppFromInfo(
-      std::move(web_app_info), /*overwrite_existing_manifest_fields=*/false,
-      base::BindLambdaForTesting([&](const AppId& installed_app_id,
-                                     webapps::InstallResultCode code) {
-        std::unique_ptr<WebAppInstallInfo> final_web_app_info =
-            fake_install_finalizer().web_app_info();
-
-        // Make sure that icons have been generated for all sub sizes.
-        EXPECT_TRUE(
-            ContainsOneIconOfEachSize(final_web_app_info->icon_bitmaps.any));
-
-        // Make sure they're all derived from the yellow icon.
-        for (const std::pair<const SquareSizePx, SkBitmap>& icon :
-             final_web_app_info->icon_bitmaps.any) {
-          EXPECT_FALSE(icon.second.drawsNothing());
-          EXPECT_EQ(SK_ColorYELLOW, icon.second.getColor(0, 0));
-        }
-
-        EXPECT_EQ(final_web_app_info->user_display_mode,
-                  mojom::UserDisplayMode::kBrowser);
-
-        run_loop.Quit();
-      }));
-
-  run_loop.Run();
-}
-
-TEST_F(WebAppInstallTaskTest, InstallWebAppFromManifestWithFallback_NoIcons) {
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  SetInstallFinalizerForTesting();
-  const GURL url{"https://example.com/path"};
-  CreateDefaultDataToRetrieve(url);
-
-  base::RunLoop run_loop;
-  install_task_->InstallWebAppFromManifestWithFallback(
-      web_contents(), WebAppInstallFlow::kCreateShortcut,
-      base::BindOnce(test::TestAcceptDialogCallback),
-      base::BindLambdaForTesting([&](const AppId& installed_app_id,
-                                     webapps::InstallResultCode code) {
-        EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
-
-        std::unique_ptr<WebAppInstallInfo> final_web_app_info =
-            fake_install_finalizer().web_app_info();
-        // Make sure that icons have been generated for all sub sizes.
-        EXPECT_TRUE(
-            ContainsOneIconOfEachSize(final_web_app_info->icon_bitmaps.any));
-        for (const std::pair<const SquareSizePx, SkBitmap>& icon :
-             final_web_app_info->icon_bitmaps.any) {
-          EXPECT_FALSE(icon.second.drawsNothing());
-        }
-
-        EXPECT_TRUE(final_web_app_info->manifest_icons.empty());
-
-        run_loop.Quit();
-      }));
-
-  run_loop.Run();
-}
-
-class WebAppInstallTaskWithShortcutFeatureTest : public WebAppInstallTaskTest {
- private:
-  base::test::ScopedFeatureList scoped_feature_list_{
-      webapps::features::kCreateShortcutIgnoresManifest};
-};
-
-TEST_F(WebAppInstallTaskWithShortcutFeatureTest,
-       CreateShortcutUsesDocumentURL) {
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  SetInstallFinalizerForTesting();
-
-  const GURL manifest_start_url{"https://example.com/?pwa=true"};
-  const std::string title = "App Name";
-  const std::string description = "Description";
-  const GURL manifest_scope{"https://example.com/"};
-  const absl::optional<SkColor> theme_color = 0xAABBCCDD;
-
-  CreateRendererAppInfo(
-      manifest_start_url, title, description, manifest_scope, theme_color,
-      /*user_display_mode=*/mojom::UserDisplayMode::kStandalone);
-
-  base::RunLoop run_loop;
-
-  const GURL document_url{"https://example.com/my/special/document/"};
-  NavigateAndCommit(document_url);
-
-  install_task_->InstallWebAppFromManifestWithFallback(
-      web_contents(), WebAppInstallFlow::kCreateShortcut,
-      base::BindOnce(test::TestAcceptDialogCallback),
-      base::BindLambdaForTesting(
-          [&](const AppId& installed_app_id, webapps::InstallResultCode code) {
-            EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
-
-            std::unique_ptr<WebAppInstallInfo> final_web_app_info =
-                fake_install_finalizer().web_app_info();
-            EXPECT_EQ(document_url, final_web_app_info->start_url);
-            EXPECT_EQ(absl::nullopt, final_web_app_info->manifest_id);
-            EXPECT_EQ(GURL{}, final_web_app_info->scope);
-            EXPECT_EQ(theme_color, final_web_app_info->theme_color);
-            EXPECT_EQ(title, base::UTF16ToUTF8(final_web_app_info->title));
-
-            run_loop.Quit();
-          }));
-
-  run_loop.Run();
-}
-
-TEST_F(WebAppInstallTaskTest, InstallWebAppFromManifest_ExpectAppId) {
-  const auto url1 = GURL("https://example.com/");
-  const auto url2 = GURL("https://example.org/");
-  const AppId app_id1 = GenerateAppId(/*manifest_id=*/absl::nullopt, url1);
-  const AppId app_id2 = GenerateAppId(/*manifest_id=*/absl::nullopt, url2);
-  ASSERT_NE(app_id1, app_id2);
-  {
-    InitializeInstallTaskAndRetriever(
-        webapps::WebappInstallSource::MENU_BROWSER_TAB);
-    CreateDefaultDataToRetrieve(url1);
-    install_task().ExpectAppId(app_id1);
-    InstallResult result = InstallWebAppFromManifestWithFallbackAndGetResults();
-    EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
-    EXPECT_EQ(app_id1, result.app_id);
-    EXPECT_TRUE(registrar().GetAppById(app_id1));
-  }
-  {
-    InitializeInstallTaskAndRetriever(
-        webapps::WebappInstallSource::MENU_BROWSER_TAB);
-    CreateDefaultDataToRetrieve(url2);
-    install_task().ExpectAppId(app_id1);
-    InstallResult result = InstallWebAppFromManifestWithFallbackAndGetResults();
-    EXPECT_EQ(webapps::InstallResultCode::kExpectedAppIdCheckFailed,
-              result.code);
-    EXPECT_EQ(app_id1, result.app_id);
-    EXPECT_FALSE(registrar().GetAppById(app_id2));
-  }
-}
-
-TEST_F(WebAppInstallTaskTest, LoadAndRetrieveWebAppInstallInfoWithIcons) {
-  const GURL url = GURL("https://example.com/path");
-  const GURL start_url = GURL("https://example.com/start");
-  const std::string name = "Name";
-  const std::string description = "Description";
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-  {
-    InitializeInstallTaskAndRetriever(
-        webapps::WebappInstallSource::MENU_BROWSER_TAB);
-    CreateDefaultDataToRetrieve(url);
-    url_loader().SetNextLoadUrlResult(
-        url, WebAppUrlLoader::Result::kRedirectedUrlLoaded);
-
-    WebAppInstallTask::WebAppInstallInfoOrErrorCode result =
-        LoadAndRetrieveWebAppInstallInfoWithIcons(url);
-    ASSERT_TRUE(absl::holds_alternative<webapps::InstallResultCode>(result));
-    EXPECT_EQ(absl::get<webapps::InstallResultCode>(result),
-              webapps::InstallResultCode::kInstallURLRedirected);
-  }
-  {
-    InitializeInstallTaskAndRetriever(
-        webapps::WebappInstallSource::MENU_BROWSER_TAB);
-    CreateDefaultDataToRetrieve(url);
-    url_loader().SetNextLoadUrlResult(
-        url, WebAppUrlLoader::Result::kFailedPageTookTooLong);
-
-    WebAppInstallTask::WebAppInstallInfoOrErrorCode result =
-        LoadAndRetrieveWebAppInstallInfoWithIcons(url);
-    ASSERT_TRUE(absl::holds_alternative<webapps::InstallResultCode>(result));
-    EXPECT_EQ(absl::get<webapps::InstallResultCode>(result),
-              webapps::InstallResultCode::kInstallURLLoadTimeOut);
-  }
-  {
-    InitializeInstallTaskAndRetriever(
-        webapps::WebappInstallSource::MENU_BROWSER_TAB);
-    CreateDefaultDataToRetrieve(start_url);
-    CreateRendererAppInfo(url, name, description);
-    url_loader().SetNextLoadUrlResult(url, WebAppUrlLoader::Result::kUrlLoaded);
-
-    WebAppInstallTask::WebAppInstallInfoOrErrorCode result =
-        LoadAndRetrieveWebAppInstallInfoWithIcons(url);
-    ASSERT_TRUE(absl::holds_alternative<WebAppInstallInfo>(result));
-    const auto& info = absl::get<WebAppInstallInfo>(result);
-    EXPECT_EQ(info.start_url, start_url);
-    EXPECT_TRUE(info.manifest_icons.empty());
-    EXPECT_FALSE(info.icon_bitmaps.any.empty());
-  }
-  {
-    // Verify the callback is always called.
-    base::RunLoop run_loop;
-    auto data_retriever = std::make_unique<FakeDataRetriever>();
-    data_retriever->BuildDefaultDataToRetrieve(url, GURL{});
-    url_loader().SetNextLoadUrlResult(url, WebAppUrlLoader::Result::kUrlLoaded);
-
-    auto task = std::make_unique<WebAppInstallTask>(
-        profile(), install_finalizer_.get(), std::move(data_retriever),
-        &registrar(), webapps::WebappInstallSource::MENU_BROWSER_TAB);
-
-    task->LoadAndRetrieveWebAppInstallInfoWithIcons(
-        url, &url_loader(),
-        base::BindLambdaForTesting(
-            [&](WebAppInstallTask::WebAppInstallInfoOrErrorCode info_or_error) {
-              run_loop.Quit();
-            }));
-    task.reset();
-    run_loop.Run();
-  }
-}
-
-TEST_F(WebAppInstallTaskWithRunOnOsLoginTest,
-       InstallFromWebContentsRunOnOsLoginByPolicy) {
-  EXPECT_TRUE(AreWebAppsUserInstallable(profile()));
-
-  const GURL url = GURL("https://example.com/scope/path");
-  const std::string name = "Name";
-  const std::string description = "Description";
-  const GURL scope = GURL("https://example.com/scope");
-  const absl::optional<SkColor> theme_color = 0xFFAABBCC;
-
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  InitializeInstallTaskAndRetriever(
-      webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  CreateDefaultDataToRetrieve(url, scope);
-  CreateRendererAppInfo(
-      url, name, description, /*scope=*/GURL{}, theme_color,
-      /*user_display_mode=*/mojom::UserDisplayMode::kStandalone);
-
-  const char kWebAppSettingWithDefaultConfiguration[] = R"([
-    {
-      "manifest_id": "https://example.com/scope/path",
-      "run_on_os_login": "run_windowed"
-    },
-    {
-      "manifest_id": "*",
-      "run_on_os_login": "blocked"
-    }
-  ])";
-
-  test::SetWebAppSettingsListPref(profile(),
-                                  kWebAppSettingWithDefaultConfiguration);
-  provider().policy_manager().RefreshPolicySettingsForTesting();
-
-  base::RunLoop run_loop;
-  bool callback_called = false;
-
-  install_task_->InstallWebAppFromManifestWithFallback(
-      web_contents(), WebAppInstallFlow::kInstallSite,
-      base::BindOnce(test::TestAcceptDialogCallback),
-      base::BindLambdaForTesting(
-          [&](const AppId& installed_app_id, webapps::InstallResultCode code) {
-            EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
-            EXPECT_EQ(app_id, installed_app_id);
-            callback_called = true;
-            run_loop.Quit();
-          }));
-  run_loop.Run();
-
-  EXPECT_TRUE(callback_called);
-
-  const WebApp* web_app = registrar().GetAppById(app_id);
-  EXPECT_NE(nullptr, web_app);
-
-  EXPECT_EQ(app_id, web_app->app_id());
-  EXPECT_EQ(description, web_app->untranslated_description());
-  EXPECT_EQ(url, web_app->start_url());
-  EXPECT_EQ(scope, web_app->scope());
-  EXPECT_EQ(theme_color, web_app->theme_color());
-  EXPECT_EQ(RunOnOsLoginMode::kNotRun, web_app->run_on_os_login_mode());
-  EXPECT_EQ(1u,
-            fake_os_integration_manager().num_register_run_on_os_login_calls());
-}
-
-// TODO(https://crbug.com/1096953): Move these tests out into a dedicated
-// unittest file.
-class WebAppInstallTaskTestWithShortcutsMenu : public WebAppInstallTaskTest {
- public:
-  GURL ShortcutIconUrl() {
-    return GURL("https://example.com/icons/shortcut_icon.png");
-  }
-
-  GURL ShortcutItemUrl() { return GURL("https://example.com/path/item"); }
-
-  // Installs the app and validates |final_web_app_info| matches the args passed
-  // in.
-  InstallResult InstallWebAppWithShortcutsMenuValidateAndGetResults(
-      const GURL& start_url,
-      SkColor theme_color,
-      const std::string& shortcut_name,
-      const GURL& shortcut_url,
-      SquareSizePx icon_size,
-      const GURL& icon_src) {
-    InitializeInstallTaskAndRetriever(
-        webapps::WebappInstallSource::MENU_BROWSER_TAB);
-    {
-      auto manifest = blink::mojom::Manifest::New();
-      manifest->start_url = start_url;
-      manifest->has_theme_color = true;
-      manifest->theme_color = theme_color;
-      manifest->name = u"Manifest Name";
-
-      // Add shortcuts to manifest.
-      blink::Manifest::ShortcutItem shortcut_item;
-      shortcut_item.name = base::UTF8ToUTF16(shortcut_name);
-      shortcut_item.url = shortcut_url;
-      blink::Manifest::ImageResource icon;
-      icon.src = icon_src;
-      icon.sizes.emplace_back(icon_size, icon_size);
-      icon.purpose.push_back(IconPurpose::ANY);
-      shortcut_item.icons.push_back(std::move(icon));
-      manifest->shortcuts.push_back(std::move(shortcut_item));
-
-      data_retriever_->SetManifest(
-          std::move(manifest),
-          webapps::InstallableStatusCode::NO_ERROR_DETECTED);
-    }
-
-    base::RunLoop run_loop;
-    bool callback_called = false;
-
-    SetInstallFinalizerForTesting();
-
-    InstallResult result;
-    install_task_->InstallWebAppFromManifest(
-        web_contents(), /*bypass_service_worker_check=*/false,
-        base::BindOnce(test::TestAcceptDialogCallback),
-        base::BindLambdaForTesting([&](const AppId& installed_app_id,
-                                       webapps::InstallResultCode code) {
-          result.app_id = installed_app_id;
-          result.code = code;
-          std::unique_ptr<WebAppInstallInfo> final_web_app_info =
-              fake_install_finalizer().web_app_info();
-          EXPECT_EQ(theme_color, final_web_app_info->theme_color);
-          EXPECT_EQ(1u, final_web_app_info->shortcuts_menu_item_infos.size());
-          EXPECT_EQ(base::UTF8ToUTF16(shortcut_name),
-                    final_web_app_info->shortcuts_menu_item_infos[0].name);
-          EXPECT_EQ(shortcut_url,
-                    final_web_app_info->shortcuts_menu_item_infos[0].url);
-          EXPECT_EQ(1u, final_web_app_info->shortcuts_menu_item_infos[0]
-                            .GetShortcutIconInfosForPurpose(IconPurpose::ANY)
-                            .size());
-          EXPECT_EQ(icon_size,
-                    final_web_app_info->shortcuts_menu_item_infos[0]
-                        .GetShortcutIconInfosForPurpose(IconPurpose::ANY)[0]
-                        .square_size_px);
-          EXPECT_EQ(icon_src,
-                    final_web_app_info->shortcuts_menu_item_infos[0]
-                        .GetShortcutIconInfosForPurpose(IconPurpose::ANY)[0]
-                        .url);
-          EXPECT_EQ(0u,
-                    final_web_app_info->shortcuts_menu_item_infos[0]
-                        .GetShortcutIconInfosForPurpose(IconPurpose::MASKABLE)
-                        .size());
-
-          callback_called = true;
-          run_loop.Quit();
-        }));
-
-    run_loop.Run();
-
-    EXPECT_TRUE(callback_called);
-
-    return result;
-  }
-
-  // Updates the app and validates |final_web_app_info| matches the args passed
-  // in.
-  InstallResult UpdateWebAppWithShortcutsMenuValidateAndGetResults(
-      const GURL& url,
-      SkColor theme_color,
-      const std::string& shortcut_name,
-      const GURL& shortcut_url,
-      SquareSizePx icon_size,
-      const GURL& icon_src) {
-    InstallResult result;
-    const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-    auto web_app_info = std::make_unique<WebAppInstallInfo>();
-    web_app_info->start_url = url;
-    web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone;
-    web_app_info->theme_color = theme_color;
-    web_app_info->title = u"App Name";
-
-    WebAppShortcutsMenuItemInfo shortcut_item;
-    WebAppShortcutsMenuItemInfo::Icon icon;
-    shortcut_item.name = base::UTF8ToUTF16(shortcut_name);
-    shortcut_item.url = shortcut_url;
-
-    icon.url = icon_src;
-    icon.square_size_px = icon_size;
-    shortcut_item.SetShortcutIconInfosForPurpose(IconPurpose::MASKABLE,
-                                                 {std::move(icon)});
-    web_app_info->shortcuts_menu_item_infos.push_back(std::move(shortcut_item));
-
-    base::RunLoop run_loop;
-    bool callback_called = false;
-
-    SetInstallFinalizerForTesting();
-
-    fake_install_finalizer().FinalizeUpdate(
-        *web_app_info,
-        base::BindLambdaForTesting([&](const AppId& installed_app_id,
-                                       webapps::InstallResultCode code,
-                                       OsHooksErrors os_hooks_errors) {
-          result.app_id = installed_app_id;
-          result.code = code;
-          std::unique_ptr<WebAppInstallInfo> final_web_app_info =
-              fake_install_finalizer().web_app_info();
-          EXPECT_EQ(theme_color, final_web_app_info->theme_color);
-          EXPECT_EQ(1u, final_web_app_info->shortcuts_menu_item_infos.size());
-          EXPECT_EQ(base::UTF8ToUTF16(shortcut_name),
-                    final_web_app_info->shortcuts_menu_item_infos[0].name);
-          EXPECT_EQ(shortcut_url,
-                    final_web_app_info->shortcuts_menu_item_infos[0].url);
-          EXPECT_EQ(0u, final_web_app_info->shortcuts_menu_item_infos[0]
-                            .GetShortcutIconInfosForPurpose(IconPurpose::ANY)
-                            .size());
-          EXPECT_EQ(1u,
-                    final_web_app_info->shortcuts_menu_item_infos[0]
-                        .GetShortcutIconInfosForPurpose(IconPurpose::MASKABLE)
-                        .size());
-          EXPECT_EQ(icon_size, final_web_app_info->shortcuts_menu_item_infos[0]
-                                   .GetShortcutIconInfosForPurpose(
-                                       IconPurpose::MASKABLE)[0]
-                                   .square_size_px);
-          EXPECT_EQ(icon_src, final_web_app_info->shortcuts_menu_item_infos[0]
-                                  .GetShortcutIconInfosForPurpose(
-                                      IconPurpose::MASKABLE)[0]
-                                  .url);
-
-          callback_called = true;
-          run_loop.Quit();
-        }));
-
-    run_loop.Run();
-
-    EXPECT_TRUE(callback_called);
-
-    return result;
-  }
-
-  static constexpr char kShortcutItemName[] = "shortcut item";
-  static constexpr SquareSizePx kIconSize = 128;
-  static constexpr SkColor kInitialThemeColor = 0xFF000000;
-  static constexpr SkColor kFinalThemeColor = 0xFFFFFFFF;
-};
-
-// Declare constants needed by tests.
-constexpr char WebAppInstallTaskTestWithShortcutsMenu::kShortcutItemName[];
-constexpr SquareSizePx WebAppInstallTaskTestWithShortcutsMenu::kIconSize;
-constexpr SkColor WebAppInstallTaskTestWithShortcutsMenu::kInitialThemeColor;
-constexpr SkColor WebAppInstallTaskTestWithShortcutsMenu::kFinalThemeColor;
-
-TEST_F(WebAppInstallTaskTestWithShortcutsMenu,
-       InstallWebAppFromManifest_Success) {
-  const GURL url = GURL("https://example.com/path");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  InstallResult result = InstallWebAppWithShortcutsMenuValidateAndGetResults(
-      url, kInitialThemeColor, "shortcut",
-      GURL("https://example.com/path/page"), kIconSize,
-      GURL("https://example.com/icons/shortcut.png"));
-  EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
-  EXPECT_EQ(app_id, result.app_id);
-}
-
-TEST_F(WebAppInstallTaskTestWithShortcutsMenu,
-       UpdateWebAppFromInfo_AddShortcutsMenu) {
-  const GURL url = GURL("https://example.com/path");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  // Install the app without a shortcuts menu.
-  {
-    InitializeInstallTaskAndRetriever(
-        webapps::WebappInstallSource::MENU_BROWSER_TAB);
-    CreateDefaultDataToRetrieve(url);
-    install_task().ExpectAppId(app_id);
-    InstallResult result = InstallWebAppFromManifestWithFallbackAndGetResults();
-    EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
-    EXPECT_EQ(app_id, result.app_id);
-  }
-
-  // Update the installed app, adding a Shortcuts Menu in the process.
-  {
-    InstallResult result = UpdateWebAppWithShortcutsMenuValidateAndGetResults(
-        url, kInitialThemeColor, "shortcut",
-        GURL("https://example.com/path/page"), kIconSize, ShortcutIconUrl());
-    EXPECT_EQ(webapps::InstallResultCode::kSuccessAlreadyInstalled,
-              result.code);
-    EXPECT_EQ(app_id, result.app_id);
-  }
-}
-
-TEST_F(WebAppInstallTaskTestWithShortcutsMenu,
-       UpdateWebAppFromInfo_UpdateShortcutsMenu) {
-  const GURL url = GURL("https://example.com/path");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  // Install the app.
-  {
-    InstallResult result = InstallWebAppWithShortcutsMenuValidateAndGetResults(
-        url, kInitialThemeColor, "shortcut",
-        GURL("https://example.com/path/page"), 2 * kIconSize,
-        GURL("https://example.com/icons/shortcut.png"));
-    EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
-    EXPECT_EQ(app_id, result.app_id);
-  }
-
-  // Update the installed app, Shortcuts Menu has changed.
-  {
-    InstallResult result = UpdateWebAppWithShortcutsMenuValidateAndGetResults(
-        url, kInitialThemeColor, kShortcutItemName, ShortcutItemUrl(),
-        kIconSize, ShortcutIconUrl());
-    EXPECT_EQ(webapps::InstallResultCode::kSuccessAlreadyInstalled,
-              result.code);
-    EXPECT_EQ(app_id, result.app_id);
-  }
-}
-
-TEST_F(WebAppInstallTaskTestWithShortcutsMenu,
-       UpdateWebAppFromInfo_ShortcutsMenuNotChanged) {
-  const GURL url = GURL("https://example.com/path");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  // Install the app.
-  {
-    InstallResult result = InstallWebAppWithShortcutsMenuValidateAndGetResults(
-        url, kInitialThemeColor, kShortcutItemName, ShortcutItemUrl(),
-        kIconSize, ShortcutIconUrl());
-    EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
-    EXPECT_EQ(app_id, result.app_id);
-  }
-
-  // Update the installed app. Only theme color changed, so Shortcuts Menu
-  // should stay the same.
-  {
-    InstallResult result = UpdateWebAppWithShortcutsMenuValidateAndGetResults(
-        url, kFinalThemeColor, kShortcutItemName, ShortcutItemUrl(), kIconSize,
-        ShortcutIconUrl());
-    EXPECT_EQ(webapps::InstallResultCode::kSuccessAlreadyInstalled,
-              result.code);
-    EXPECT_EQ(app_id, result.app_id);
-  }
-}
-
-class WebAppInstallTaskTestWithFileHandlers : public WebAppInstallTaskTest {
- public:
-  blink::mojom::ManifestPtr CreateManifest(const GURL& url) {
-    auto manifest = blink::mojom::Manifest::New();
-    manifest->start_url = url;
-    manifest->name = u"Manifest Name";
-    return manifest;
-  }
-
-  std::unique_ptr<WebAppInstallInfo> CreateWebAppInstallInfo(const GURL& url) {
-    auto app_info = std::make_unique<WebAppInstallInfo>();
-    app_info->title = u"Test App";
-    app_info->start_url = url;
-    app_info->scope = url;
-    return app_info;
-  }
-
-  void AddFileHandler(
-      std::vector<blink::mojom::ManifestFileHandlerPtr>* file_handlers) {
-    auto file_handler = blink::mojom::ManifestFileHandler::New();
-    file_handler->action = GURL("https://example.com/action");
-    file_handler->name = u"Test handler";
-    file_handler->accept[u"application/pdf"].emplace_back(u".pdf");
-    file_handlers->push_back(std::move(file_handler));
-  }
-
-  InstallResult InstallWebAppFromManifest(
-      blink::mojom::ManifestPtr manifest,
-      webapps::WebappInstallSource surface) {
-    InitializeInstallTaskAndRetriever(surface);
-    data_retriever_->SetManifest(
-        std::move(manifest), webapps::InstallableStatusCode::NO_ERROR_DETECTED);
-
-    base::RunLoop run_loop;
-    bool callback_called = false;
-    InstallResult result;
-
-    install_task_->InstallWebAppFromManifest(
-        web_contents(), /*bypass_service_worker_check=*/false,
-        base::BindOnce(test::TestAcceptDialogCallback),
-        base::BindLambdaForTesting([&](const AppId& installed_app_id,
-                                       webapps::InstallResultCode code) {
-          result.app_id = installed_app_id;
-          result.code = code;
-
-          callback_called = true;
-          run_loop.Quit();
-        }));
-
-    run_loop.Run();
-    EXPECT_TRUE(callback_called);
-    return result;
-  }
-
-  InstallResult UpdateWebAppFromInfo(
-      const AppId& app_id,
-      std::unique_ptr<WebAppInstallInfo> app_info) {
-    base::RunLoop run_loop;
-    bool callback_called = false;
-    InstallResult result;
-
-    install_finalizer_->FinalizeUpdate(
-        *app_info,
-        base::BindLambdaForTesting([&](const AppId& installed_app_id,
-                                       webapps::InstallResultCode code,
-                                       OsHooksErrors os_hooks_errors) {
-          result.app_id = installed_app_id;
-          result.code = code;
-          result.os_hooks_errors = os_hooks_errors;
-
-          callback_called = true;
-          run_loop.Quit();
-        }));
-
-    run_loop.Run();
-    EXPECT_TRUE(callback_called);
-    return result;
-  }
-};
-
-TEST_F(WebAppInstallTaskTestWithFileHandlers,
-       UpdateWebAppFromInfo_OsIntegrationEnabledForUserInstalledApps) {
-  const GURL url = GURL("https://example.com/path");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  // Install the app.
-  InstallResult install_result = InstallWebAppFromManifest(
-      CreateManifest(url), webapps::WebappInstallSource::MENU_BROWSER_TAB);
-  EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
-            install_result.code);
-  EXPECT_EQ(app_id, install_result.app_id);
-  EXPECT_EQ(1u, fake_os_integration_manager().num_create_file_handlers_calls());
-
-  // Update the app, adding a file handler.
-  auto app_info = CreateWebAppInstallInfo(url);
-  std::vector<blink::mojom::ManifestFileHandlerPtr> file_handlers;
-  AddFileHandler(&file_handlers);
-  app_info->file_handlers = CreateFileHandlersFromManifest(file_handlers, url);
-
-  InstallResult update_result =
-      UpdateWebAppFromInfo(app_id, std::move(app_info));
-  EXPECT_EQ(webapps::InstallResultCode::kSuccessAlreadyInstalled,
-            update_result.code);
-  EXPECT_EQ(app_id, update_result.app_id);
-  EXPECT_EQ(1u, fake_os_integration_manager().num_update_file_handlers_calls());
-}
-
-TEST_F(WebAppInstallTaskTestWithFileHandlers,
-       UpdateWebAppFromInfo_OsIntegrationDisabledForDefaultApps) {
-  const GURL url = GURL("https://example.com/path");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
-
-  // Install the app.
-
-  InstallResult install_result = InstallWebAppFromManifest(
-      CreateManifest(url), webapps::WebappInstallSource::EXTERNAL_DEFAULT);
-  EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
-            install_result.code);
-  EXPECT_EQ(app_id, install_result.app_id);
-#if BUILDFLAG(IS_CHROMEOS)
-  // OS integration is always enabled in ChromeOS
-  EXPECT_EQ(1u, fake_os_integration_manager().num_create_file_handlers_calls());
-#else
-  EXPECT_EQ(0u, fake_os_integration_manager().num_create_file_handlers_calls());
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
-  // Update the app, adding a file handler.
-  auto app_info = CreateWebAppInstallInfo(url);
-  std::vector<blink::mojom::ManifestFileHandlerPtr> file_handlers;
-  AddFileHandler(&file_handlers);
-  app_info->file_handlers = CreateFileHandlersFromManifest(file_handlers, url);
-
-  InstallResult update_result =
-      UpdateWebAppFromInfo(app_id, std::move(app_info));
-  EXPECT_EQ(webapps::InstallResultCode::kSuccessAlreadyInstalled,
-            update_result.code);
-  EXPECT_EQ(app_id, update_result.app_id);
-#if BUILDFLAG(IS_CHROMEOS)
-  // OS integration is always enabled in ChromeOS
-  EXPECT_EQ(1u, fake_os_integration_manager().num_update_file_handlers_calls());
-#else
-  EXPECT_EQ(0u, fake_os_integration_manager().num_update_file_handlers_calls());
-#endif  // BUILDFLAG(IS_CHROMEOS)
-}
-
-}  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc
index 208d965..8fb870c 100644
--- a/chrome/browser/web_applications/web_app_provider.cc
+++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -311,10 +311,6 @@
       sync_bridge_.get(), os_integration_manager_.get(), icon_manager_.get(),
       web_app_policy_manager_.get(), translation_manager_.get(),
       command_manager_.get());
-  install_manager_->SetSubsystems(
-      registrar_.get(), os_integration_manager_.get(), command_manager_.get(),
-      install_finalizer_.get(), icon_manager_.get(), sync_bridge_.get(),
-      translation_manager_.get());
   manifest_update_manager_->SetSubsystems(install_manager_.get(),
                                           registrar_.get(), ui_manager_.get(),
                                           command_scheduler_.get());
diff --git a/chrome/browser/web_applications/web_contents/web_app_data_retriever.h b/chrome/browser/web_applications/web_contents/web_app_data_retriever.h
index 21664e5..69ef802 100644
--- a/chrome/browser/web_applications/web_contents/web_app_data_retriever.h
+++ b/chrome/browser/web_applications/web_contents/web_app_data_retriever.h
@@ -37,7 +37,7 @@
 
 enum class IconsDownloadedResult;
 
-// Class used by WebAppInstallTask to retrieve the necessary information to
+// Class used by the WebApp system to retrieve the necessary information to
 // install an app. Should only be called from the UI thread.
 class WebAppDataRetriever : content::WebContentsObserver {
  public:
diff --git a/chrome/browser/webauthn/passkey_model_factory.cc b/chrome/browser/webauthn/passkey_model_factory.cc
new file mode 100644
index 0000000..d752b1d6
--- /dev/null
+++ b/chrome/browser/webauthn/passkey_model_factory.cc
@@ -0,0 +1,42 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/webauthn/passkey_model_factory.h"
+
+#include "base/check.h"
+#include "base/feature_list.h"
+#include "base/no_destructor.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/model_type_store_service_factory.h"
+#include "components/sync/base/features.h"
+#include "components/sync/model/model_type_store.h"
+#include "components/sync/model/model_type_store_service.h"
+#include "components/webauthn/core/browser/passkey_sync_bridge.h"
+
+PasskeyModelFactory* PasskeyModelFactory::GetInstance() {
+  static base::NoDestructor<PasskeyModelFactory> instance;
+  return instance.get();
+}
+
+PasskeyModel* PasskeyModelFactory::GetForProfile(Profile* profile) {
+  return static_cast<PasskeyModel*>(
+      GetInstance()->GetServiceForBrowserContext(profile, true));
+}
+
+PasskeyModelFactory::PasskeyModelFactory()
+    : ProfileKeyedServiceFactory(
+          "PasskeyModel",
+          ProfileSelections::BuildRedirectedToOriginal()) {
+  DependsOn(ModelTypeStoreServiceFactory::GetInstance());
+}
+
+PasskeyModelFactory::~PasskeyModelFactory() = default;
+
+KeyedService* PasskeyModelFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  DCHECK(base::FeatureList::IsEnabled(syncer::kSyncWebauthnCredentials));
+  return new PasskeySyncBridge(ModelTypeStoreServiceFactory::GetForProfile(
+                                   Profile::FromBrowserContext(context))
+                                   ->GetStoreFactory());
+}
diff --git a/chrome/browser/webauthn/passkey_model_factory.h b/chrome/browser/webauthn/passkey_model_factory.h
new file mode 100644
index 0000000..91fa34e
--- /dev/null
+++ b/chrome/browser/webauthn/passkey_model_factory.h
@@ -0,0 +1,33 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEBAUTHN_PASSKEY_MODEL_FACTORY_H_
+#define CHROME_BROWSER_WEBAUTHN_PASSKEY_MODEL_FACTORY_H_
+
+#include "base/no_destructor.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
+#include "components/webauthn/core/browser/passkey_model.h"
+
+namespace content {
+class BrowserContext;
+}
+// class PasskeyModel;
+
+class PasskeyModelFactory : public ProfileKeyedServiceFactory {
+ public:
+  static PasskeyModelFactory* GetInstance();
+  static PasskeyModel* GetForProfile(Profile* profile);
+
+ private:
+  friend class base::NoDestructor<PasskeyModelFactory>;
+
+  PasskeyModelFactory();
+  ~PasskeyModelFactory() override;
+
+  // BrowserContextKeyedServiceFactory:
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
+};
+
+#endif  // CHROME_BROWSER_WEBAUTHN_PASSKEY_MODEL_FACTORY_H_
diff --git a/chrome/browser/xsurface/BUILD.gn b/chrome/browser/xsurface/BUILD.gn
index e829675..8911520 100644
--- a/chrome/browser/xsurface/BUILD.gn
+++ b/chrome/browser/xsurface/BUILD.gn
@@ -9,6 +9,7 @@
     "android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/FeedLaunchReliabilityLogger.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/FeedNetworkRequestReliabilityLogger.java",
+    "android/java/src/org/chromium/chrome/browser/xsurface/FeedUserInteractionReliabilityLogger.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/ImageCacheHelper.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java",
@@ -20,6 +21,7 @@
     "android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/ReliabilityLoggingTestUtil.java",
+    "android/java/src/org/chromium/chrome/browser/xsurface/StreamType.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/SurfaceHeaderOffsetObserver.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java",
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedUserInteractionReliabilityLogger.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedUserInteractionReliabilityLogger.java
new file mode 100644
index 0000000..60f733cc
--- /dev/null
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedUserInteractionReliabilityLogger.java
@@ -0,0 +1,90 @@
+// Copyright 2023 The Chromium Authors
+// 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.xsurface;
+
+import android.view.View;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Interface for capturing the reliability for every change in the collection of items presented to
+ * the user during the interaction. One instance exists per feed surface and lasts for the surface's
+ * lifetime.
+ */
+public interface FeedUserInteractionReliabilityLogger {
+    /**
+     * Called when the stream has been opened. This should be called before reporting any event.
+     */
+    default void onStreamOpened(@StreamType int streamType) {}
+
+    /**
+     * Describes how the stream is closed.
+     */
+    @IntDef({ClosedReason.OPEN_CARD, ClosedReason.SUSPEND_APP, ClosedReason.LEAVE_FEED,
+            ClosedReason.SWITCH_STREAM})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ClosedReason {
+        /** The user taps on a card. */
+        int OPEN_CARD = 0;
+        /** The user leaves the app. */
+        int SUSPEND_APP = 1;
+        /** The user leaves the feed but still stays in the app, like switching to other tab. */
+        int LEAVE_FEED = 2;
+        /** The user switches to other stream. */
+        int SWITCH_STREAM = 3;
+    }
+
+    /**
+     * Called when the stream has been closed.
+     */
+    default void onStreamClosed(ClosedReason reason) {}
+
+    /**
+     * Called when the view has entered the visible part of the screen for the first time. If the
+     * view is then off screen and become visible again, it will not be reported again.
+     */
+    default void onViewFirstVisible(View view) {}
+
+    /**
+     * Called when the view has been rendered for the first time. Note that this doesn't include the
+     * child images. If the view is then off screen and become visible again, it will not be
+     * reported again.
+     */
+    default void onViewFirstRendered(View view) {}
+
+    /**
+     * Called when the pagination process has started.
+     */
+    default void onPaginationStarted() {}
+
+    /**
+     * Called when the waiting indicator is shown. This will happen after the pagination process
+     * has started.
+     */
+    default void onPaginationIndicatorShown() {}
+
+    /**
+     * Describes the end state of the pagination process.
+     */
+    @IntDef({PaginationResult.SUCCESS_WITH_MORE_FEED, PaginationResult.SUCCESS_WITH_NO_FEED,
+            PaginationResult.FAILURE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PaginationResult {
+        /** More feed content is retrieved. */
+        int SUCCESS_WITH_MORE_FEED = 0;
+        /** No feed content is retrieved. This means that the end of the feed is reached. */
+        int SUCCESS_WITH_NO_FEED = 1;
+        /** The pagination request has failed. */
+        int FAILURE = 2;
+    }
+
+    /**
+     * Called when the pagination process has ended.
+     */
+    default void onPaginationEnded(@PaginationResult int result) {}
+}
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/StreamType.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/StreamType.java
new file mode 100644
index 0000000..6beb99b
--- /dev/null
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/StreamType.java
@@ -0,0 +1,21 @@
+// Copyright 2023 The Chromium Authors
+// 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.xsurface;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Type of stream being launched (the "For you","Following", or "SingleWebFeed" feed). */
+@IntDef({StreamType.UNSPECIFIED, StreamType.FOR_YOU, StreamType.WEB_FEED,
+        StreamType.SINGLE_WEB_FEED})
+@Retention(RetentionPolicy.SOURCE)
+@interface StreamType {
+    int UNSPECIFIED = 0;
+    int FOR_YOU = 1;
+    int WEB_FEED = 2;
+    int SINGLE_WEB_FEED = 3;
+}
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScope.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScope.java
index 4ab24b2..34d7108 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScope.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScope.java
@@ -34,4 +34,8 @@
     default FeedLaunchReliabilityLogger getFeedLaunchReliabilityLogger() {
         return new FeedLaunchReliabilityLogger() {};
     }
+
+    default FeedUserInteractionReliabilityLogger getFeedUserInteractionReliabilityLogger() {
+        return new FeedUserInteractionReliabilityLogger() {};
+    }
 }
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 9b68323..38380db 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1680019182-1624754bb24ed33544e337718ef7b831861b4eae.profdata
+chrome-mac-arm-main-1680076486-ef72ad9ae989bfab48abf40e8a0f8d08e505f08b.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 3827ec24..0cbcbdb 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1680004532-90e04c41f7bca85fe8fe34c3f5054276df63ca80.profdata
+chrome-mac-main-1680069585-122bafd1a0623f0ef55a1abb0aaa320ffefd6458.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 08eb79b..90d4d88 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1680004532-455a96a02030b8f9258042aa32e41fa20615ec53.profdata
+chrome-win32-main-1680058725-4101aa64dacbc7ecc27436acd54998fb3bcf9e57.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 78f81f1..4af284b 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1680004532-7a30bf807df7595e0150660312b3bd8cd51fd36b.profdata
+chrome-win64-main-1680069585-37551ea5d7bba358dce704bf7f5e109ca65e050e.profdata
diff --git a/chrome/common/safe_browsing/rar_analyzer.h b/chrome/common/safe_browsing/rar_analyzer.h
index 6bb81b6..c80a2295 100644
--- a/chrome/common/safe_browsing/rar_analyzer.h
+++ b/chrome/common/safe_browsing/rar_analyzer.h
@@ -23,6 +23,7 @@
 
 #include "base/files/file.h"
 #include "base/functional/callback.h"
+#include "base/memory/raw_ptr.h"
 #include "components/safe_browsing/content/common/proto/download_file_types.pb.h"
 #include "third_party/unrar/google/unrar_wrapper.h"
 
@@ -82,7 +83,7 @@
   base::File rar_file_;
   base::File temp_file_;
   third_party_unrar::RarReader reader_;
-  ArchiveAnalyzerResults* results_;
+  raw_ptr<ArchiveAnalyzerResults> results_;
 
   FinishedAnalysisCallback finished_analysis_callback_;
   GetTempFileCallback get_temp_file_callback_;
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc
index 6c5902a..f451416 100644
--- a/chrome/renderer/accessibility/read_anything_app_controller.cc
+++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -10,7 +10,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/containers/contains.h"
 #include "base/notreached.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -315,6 +314,17 @@
     const std::vector<ui::AXTreeUpdate>& updates,
     const std::vector<ui::AXEvent>& events) {
   model_.AccessibilityEventReceived(tree_id, updates, this);
+
+  if (model_.loading() || tree_id != model_.active_tree_id()) {
+    return;
+  }
+
+  for (auto& event : events) {
+    if (event.event_type == ax::mojom::Event::kDocumentSelectionChanged &&
+        event.event_from == ax::mojom::EventFrom::kUser) {
+      PostProcessSelection();
+    }
+  }
 }
 
 void ReadAnythingAppController::OnActiveAXTreeIDChanged(
@@ -334,6 +344,8 @@
   // replace this function call with firing an event.
   std::string script = "chrome.readAnything.showLoading();";
   render_frame_->ExecuteJavaScript(base::ASCIIToUTF16(script));
+  model_.SetLoading(true);
+
   // When the UI first constructs, this function may be called before tree_id
   // has been added to the tree list in AccessibilityEventReceived. In that
   // case, do not distill.
@@ -428,31 +440,69 @@
   }
   if (!model_.content_node_ids().empty()) {
     // If there are content_node_ids, this means the AXTree was successfully
-    // distilled. Post-process in preparation to display the distilled content.
-    PostProcessDistillableAXTree();
-  } else if (model_.has_selection()) {
-    // Otherwise, if there is a selection, post-process the AXTree to display
-    // the selected content.
-    PostProcessAXTreeWithSelection();
-  } else {
-    // TODO(crbug.com/1266555): Display a UI giving user instructions if the
-    // tree was not distillable.
+    // distilled.
+    ComputeDisplayNodeIdsForDistilledTree();
   }
 
-  Draw();
+  // Draw selection (if one exists) and the content.
+  PostProcessSelection();
+
+  // TODO(crbug.com/1266555): If no content nodes were identified, the
+  // controller should handle drawing the empty state (like how it handles the
+  // loading state) instead of the JS.
+
   // Once drawing is complete, unserialize all of the pending updates on the
   // active tree and send out a new distillation request.
   model_.UnserializePendingUpdates(tree_id);
 }
 
+void ReadAnythingAppController::PostProcessSelection() {
+  DCHECK_NE(model_.active_tree_id(), ui::AXTreeIDUnknown());
+  DCHECK(model_.ContainsTree(model_.active_tree_id()));
+
+  // If the previous selection was inside the distilled content, that means we
+  // are currently displaying the distilled content in Read Anything. We may not
+  // need to redraw the distilled content if the user's new selection is inside
+  // the distilled content.
+  // If the previous selection was outside the distilled content, we will always
+  // redraw either a) the new selected content or b) the original distilled
+  // content if the new selection is inside that or if the selection was
+  // cleared.
+  bool need_to_draw = !model_.SelectionInsideDisplayNodes();
+
+  // Save the current selection
+  model_.UpdateSelection();
+
+  // If the main panel selection contains content outside of the distilled
+  // content, we need to find the selected nodes to display instead of the
+  // distilled content.
+  if (model_.has_selection() && !model_.SelectionInsideDisplayNodes()) {
+    need_to_draw = true;
+    ComputeSelectionNodeIds();
+  }
+
+  if (need_to_draw) {
+    Draw();
+  }
+  DrawSelection();
+}
+
 void ReadAnythingAppController::Draw() {
   // TODO(abigailbklein): Use v8::Function rather than javascript. If possible,
   // replace this function call with firing an event.
   std::string script = "chrome.readAnything.updateContent();";
   render_frame_->ExecuteJavaScript(base::ASCIIToUTF16(script));
+  model_.SetLoading(false);
 }
 
-void ReadAnythingAppController::PostProcessAXTreeWithSelection() {
+void ReadAnythingAppController::DrawSelection() {
+  // TODO(abigailbklein): Use v8::Function rather than javascript. If possible,
+  // replace this function call with firing an event.
+  std::string script = "chrome.readAnything.updateSelection();";
+  render_frame_->ExecuteJavaScript(base::ASCIIToUTF16(script));
+}
+
+void ReadAnythingAppController::ComputeSelectionNodeIds() {
   DCHECK(model_.has_selection());
   DCHECK_NE(model_.active_tree_id(), ui::AXTreeIDUnknown());
   DCHECK(model_.ContainsTree(model_.active_tree_id()));
@@ -464,20 +514,14 @@
   ui::AXNode* end_node = model_.GetAXNode(model_.end_node_id());
   DCHECK(end_node);
 
-  // If start node or end node is ignored, go to the nearest unignored node
-  // within the selection.
-  if (start_node->IsIgnored()) {
-    start_node = start_node->GetNextUnignoredInTreeOrder();
-    DCHECK(start_node);
-    model_.SetStart(start_node->id(), 0);
-  }
-  if (end_node->IsIgnored()) {
-    end_node = end_node->GetPreviousUnignoredInTreeOrder();
-    model_.SetEnd(end_node->id(), end_node->GetTextContentLengthUTF8());
+  // If start node or end node is ignored, the selection was invalid.
+  if (start_node->IsIgnored() || end_node->IsIgnored()) {
+    return;
   }
 
-  // Display nodes are the nodes which will be displayed by the rendering
-  // algorithm of Read Anything app.ts. We wish to create a subtree which
+  // Selection nodes are the nodes which will be displayed by the rendering
+  // algorithm of Read Anything app.ts if there is a selection that contains
+  // content outside of the distilled content. We wish to create a subtree which
   // stretches from start node to end node with tree root as the root.
 
   // Add all ancestor ids of start node, including the start node itself. This
@@ -486,22 +530,29 @@
       start_node->GetAncestorsCrossingTreeBoundaryAsQueue();
   while (!ancestors.empty()) {
     ui::AXNodeID ancestor_id = ancestors.front()->id();
-    model_.InsertDisplayNode(ancestor_id);
     ancestors.pop();
+    if (!model_.IsNodeIgnoredForReadAnything(ancestor_id)) {
+      model_.InsertSelectionNode(ancestor_id);
+    }
   }
 
   // Do a pre-order walk of the tree from the start node to the end node and add
-  // all nodes to the list of display node ids.
-  ui::AXNode* next_node = start_node;
-  DCHECK(!start_node->IsIgnored());
-  DCHECK(!end_node->IsIgnored());
-  while (next_node != end_node) {
+  // all nodes to the list.
+  // TODO(crbug.com/1266555): Right now, we are going from start node to an
+  // unignored node that is before or equal to the end node. This condition was
+  // changed from next_node != end node because when a paragraph is selected
+  // with a triple click, we sometimes pass the end node, causing a SEGV_ACCERR.
+  // We need to investigate this case in more depth.
+  ui::AXNode* next_node = start_node->GetNextUnignoredInTreeOrder();
+  while (next_node && next_node->CompareTo(*end_node) <= 0) {
+    if (!model_.IsNodeIgnoredForReadAnything(next_node->id())) {
+      model_.InsertSelectionNode(next_node->id());
+    }
     next_node = next_node->GetNextUnignoredInTreeOrder();
-    model_.InsertDisplayNode(next_node->id());
   }
 }
 
-void ReadAnythingAppController::PostProcessDistillableAXTree() {
+void ReadAnythingAppController::ComputeDisplayNodeIdsForDistilledTree() {
   DCHECK(!model_.content_node_ids().empty());
 
   // Display nodes are the nodes which will be displayed by the rendering
@@ -660,9 +711,12 @@
   std::vector<ui::AXNodeID> child_ids;
   ui::AXNode* ax_node = model_.GetAXNode(ax_node_id);
   DCHECK(ax_node);
+  const std::set<ui::AXNodeID>* node_ids = model_.selection_node_ids().empty()
+                                               ? &model_.display_node_ids()
+                                               : &model_.selection_node_ids();
   for (auto it = ax_node->UnignoredChildrenBegin();
        it != ax_node->UnignoredChildrenEnd(); ++it) {
-    if (base::Contains(model_.display_node_ids(), it->id())) {
+    if (base::Contains(*node_ids, it->id())) {
       child_ids.push_back(it->id());
     }
   }
@@ -822,9 +876,16 @@
   v8::Isolate* isolate = blink::MainThreadIsolate();
   ui::AXTreeUpdate snapshot =
       GetSnapshotFromV8SnapshotLite(isolate, v8_snapshot_lite);
+  ui::AXEvent selectionEvent;
+  selectionEvent.event_type = ax::mojom::Event::kDocumentSelectionChanged;
+  selectionEvent.event_from = ax::mojom::EventFrom::kUser;
   AccessibilityEventReceived(snapshot.tree_data.tree_id, {snapshot}, {});
   OnActiveAXTreeIDChanged(snapshot.tree_data.tree_id, ukm::kInvalidSourceId);
   OnAXTreeDistilled(snapshot.tree_data.tree_id, content_node_ids);
+
+  // Trigger a selection event (for testing selections).
+  AccessibilityEventReceived(snapshot.tree_data.tree_id, {snapshot},
+                             {selectionEvent});
 }
 
 AXTreeDistiller* ReadAnythingAppController::SetDistillerForTesting(
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.h b/chrome/renderer/accessibility/read_anything_app_controller.h
index 4f9d5cd..72b5906 100644
--- a/chrome/renderer/accessibility/read_anything_app_controller.h
+++ b/chrome/renderer/accessibility/read_anything_app_controller.h
@@ -131,6 +131,7 @@
 
   void Distill();
   void Draw();
+  void DrawSelection();
 
   void UnserializeUpdates(std::vector<ui::AXTreeUpdate> updates,
                           const ui::AXTreeID& tree_id);
@@ -141,13 +142,20 @@
 
   // Helper functions for the rendering algorithm. Post-process the AXTree and
   // cache values before sending an `updateContent` notification to the Read
-  // Anything app.ts. These functions:
-  // 1. Save state related to selection (start_node_, end_node_, start_offset_,
-  //    end_offset_).
-  // 2. Save the display_node_ids_, which is a set of all nodes to be displayed
-  //    in Read Anything app.ts.
-  void PostProcessAXTreeWithSelection();
-  void PostProcessDistillableAXTree();
+  // Anything app.ts.
+  // ComputeDisplayNodeIdsForDistilledTree computes display nodes from the
+  // content nodes. These display nodes will be displayed in Read Anything
+  // app.ts by default.
+  // ComputeSelectionNodeIds computes selection nodes from
+  // the user's selection. The selection nodes list is only populated when the
+  // user's selection contains nodes outside of the display nodes list. By
+  // keeping two separate lists of nodes, we can switch back to displaying the
+  // default distilled content without recomputing the nodes when the user
+  // clears their selection or selects content inside the distilled content.
+  void ComputeDisplayNodeIdsForDistilledTree();
+  void ComputeSelectionNodeIds();
+
+  void PostProcessSelection();
 
   // The following methods are used for testing ReadAnythingAppTest.
   // Snapshot_lite is a data structure which resembles an AXTreeUpdate. E.g.:
diff --git a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
index 253bf33..a2f03c24 100644
--- a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
+++ b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
@@ -131,6 +131,15 @@
     controller_->AccessibilityEventReceived(tree_id, updates, {});
   }
 
+  void AccessibilityEventReceivedWithUserSelection(
+      const std::vector<ui::AXTreeUpdate>& updates) {
+    ui::AXEvent event;
+    event.event_type = ax::mojom::Event::kDocumentSelectionChanged;
+    event.event_from = ax::mojom::EventFrom::kUser;
+    controller_->AccessibilityEventReceived(updates[0].tree_data.tree_id,
+                                            updates, {event});
+  }
+
   // Since a11y events happen asynchronously, they can come between the time
   // distillation finishes and pending updates are unserialized in
   // OnAXTreeDistilled. Thus we need to be able to set distillation progress
@@ -172,6 +181,10 @@
     return base::Contains(controller_->model_.display_node_ids(), ax_node_id);
   }
 
+  bool SelectionNodeIdsContains(ui::AXNodeID ax_node_id) {
+    return base::Contains(controller_->model_.selection_node_ids(), ax_node_id);
+  }
+
   std::string FontName() { return controller_->FontName(); }
 
   float FontSize() { return controller_->FontSize(); }
@@ -224,33 +237,11 @@
     return controller_->model_.IsNodeIgnoredForReadAnything(ax_node_id);
   }
 
-  size_t GetNumTrees() { return controller_->model_.trees_.size(); }
-
   bool HasTree(ui::AXTreeID tree_id) {
     return controller_->model_.ContainsTree(tree_id);
   }
 
-  void EraseTree(ui::AXTreeID tree_id) {
-    controller_->model_.EraseTree(tree_id);
-  }
-
-  void AddTree(ui::AXTreeID tree_id,
-               std::unique_ptr<ui::AXSerializableTree> tree) {
-    controller_->model_.AddTree(tree_id, std::move(tree));
-  }
-
-  bool AreAllPendingUpdatesEmpty() {
-    size_t count = 0;
-    for (auto const& [tree_id, updates] :
-         controller_->model_.pending_updates_map_) {
-      count += updates.size();
-    }
-    return count == 0;
-  }
-
-  size_t GetNumPendingUpdates(ui::AXTreeID tree_id) {
-    return controller_->model_.pending_updates_map_[tree_id].size();
-  }
+  ui::AXTreeID ActiveTreeId() { return controller_->model_.active_tree_id(); }
 
   ui::AXTreeID tree_id_;
   MockAXTreeDistiller* distiller_ = nullptr;
@@ -334,8 +325,7 @@
   update.tree_data.sel_anchor_offset = 0;
   update.tree_data.sel_focus_offset = 0;
   update.tree_data.sel_is_backward = false;
-  AccessibilityEventReceived({update});
-  OnAXTreeDistilled({});
+  AccessibilityEventReceivedWithUserSelection({update});
   EXPECT_EQ(2u, GetChildren(1).size());
   EXPECT_EQ(0u, GetChildren(2).size());
   EXPECT_EQ(0u, GetChildren(3).size());
@@ -354,8 +344,7 @@
   update.tree_data.sel_anchor_offset = 0;
   update.tree_data.sel_focus_offset = 0;
   update.tree_data.sel_is_backward = true;
-  AccessibilityEventReceived({update});
-  OnAXTreeDistilled({});
+  AccessibilityEventReceivedWithUserSelection({update});
   EXPECT_EQ(2u, GetChildren(1).size());
   EXPECT_EQ(0u, GetChildren(2).size());
   EXPECT_EQ(0u, GetChildren(3).size());
@@ -516,7 +505,9 @@
   EXPECT_EQ(true, IsNodeIgnoredForReadAnything(4));
 }
 
-TEST_F(ReadAnythingAppControllerTest, DisplayNodeIdsContains_Selection) {
+// TODO(b/1266555) Move tests using DisplayNodeIdsContains to the tests for the
+// model once logic around selection has been pulled into the model.
+TEST_F(ReadAnythingAppControllerTest, SelectionNodeIdsContains_Selection) {
   ui::AXTreeUpdate update;
   SetUpdateTreeID(&update);
   update.tree_data.sel_anchor_object_id = 2;
@@ -524,12 +515,12 @@
   update.tree_data.sel_anchor_offset = 0;
   update.tree_data.sel_focus_offset = 0;
   update.tree_data.sel_is_backward = false;
-  AccessibilityEventReceived({update});
-  OnAXTreeDistilled({});
-  EXPECT_TRUE(DisplayNodeIdsContains(1));
-  EXPECT_TRUE(DisplayNodeIdsContains(2));
-  EXPECT_TRUE(DisplayNodeIdsContains(3));
-  EXPECT_FALSE(DisplayNodeIdsContains(4));
+
+  AccessibilityEventReceivedWithUserSelection({update});
+  EXPECT_TRUE(SelectionNodeIdsContains(1));
+  EXPECT_TRUE(SelectionNodeIdsContains(2));
+  EXPECT_TRUE(SelectionNodeIdsContains(3));
+  EXPECT_FALSE(SelectionNodeIdsContains(4));
 }
 
 TEST_F(ReadAnythingAppControllerTest,
@@ -541,12 +532,11 @@
   update.tree_data.sel_anchor_offset = 0;
   update.tree_data.sel_focus_offset = 0;
   update.tree_data.sel_is_backward = true;
-  AccessibilityEventReceived({update});
-  OnAXTreeDistilled({});
-  EXPECT_TRUE(DisplayNodeIdsContains(1));
-  EXPECT_TRUE(DisplayNodeIdsContains(2));
-  EXPECT_TRUE(DisplayNodeIdsContains(3));
-  EXPECT_FALSE(DisplayNodeIdsContains(4));
+  AccessibilityEventReceivedWithUserSelection({update});
+  EXPECT_TRUE(SelectionNodeIdsContains(1));
+  EXPECT_TRUE(SelectionNodeIdsContains(2));
+  EXPECT_TRUE(SelectionNodeIdsContains(3));
+  EXPECT_FALSE(SelectionNodeIdsContains(4));
 }
 
 TEST_F(ReadAnythingAppControllerTest, DisplayNodeIdsContains_ContentNodes) {
@@ -726,41 +716,6 @@
   OnActiveAXTreeIDChanged(tree_ids[2]);
 }
 
-TEST_F(ReadAnythingAppControllerTest, ModelUpdatesTreeState) {
-  // Set up trees.
-  ui::AXTreeID tree_id_2 = ui::AXTreeID::CreateNewAXTreeID();
-  ui::AXTreeID tree_id_3 = ui::AXTreeID::CreateNewAXTreeID();
-
-  AddTree(tree_id_2, std::make_unique<ui::AXSerializableTree>());
-  AddTree(tree_id_3, std::make_unique<ui::AXSerializableTree>());
-
-  ASSERT_EQ(3u, GetNumTrees());
-  ASSERT_TRUE(HasTree(tree_id_2));
-  ASSERT_TRUE(HasTree(tree_id_3));
-  ASSERT_TRUE(HasTree(tree_id_));
-
-  // Remove one tree.
-  EraseTree(tree_id_2);
-  ASSERT_EQ(2u, GetNumTrees());
-  ASSERT_TRUE(HasTree(tree_id_3));
-  ASSERT_FALSE(HasTree(tree_id_2));
-  ASSERT_TRUE(HasTree(tree_id_));
-
-  // Remove the second tree.
-  EraseTree(tree_id_);
-  ASSERT_EQ(1u, GetNumTrees());
-  ASSERT_TRUE(HasTree(tree_id_3));
-  ASSERT_FALSE(HasTree(tree_id_2));
-  ASSERT_FALSE(HasTree(tree_id_));
-
-  // Remove the last tree.
-  EraseTree(tree_id_3);
-  ASSERT_EQ(0u, GetNumTrees());
-  ASSERT_FALSE(HasTree(tree_id_3));
-  ASSERT_FALSE(HasTree(tree_id_2));
-  ASSERT_FALSE(HasTree(tree_id_));
-}
-
 TEST_F(ReadAnythingAppControllerTest, DoesNotCrashIfActiveAXTreeIDUnknown) {
   EXPECT_CALL(*distiller_, Distill).Times(0);
   ui::AXTreeID tree_id = ui::AXTreeIDUnknown();
@@ -790,33 +745,30 @@
   }
 
   // Start with 1 tree (the tree created in SetUp).
-  ASSERT_EQ(1u, GetNumTrees());
   ASSERT_TRUE(HasTree(tree_id_));
 
   // Add the two trees.
   AccessibilityEventReceived({updates[0]});
-  ASSERT_EQ(2u, GetNumTrees());
   ASSERT_TRUE(HasTree(tree_id_));
   ASSERT_TRUE(HasTree(tree_ids[0]));
   AccessibilityEventReceived({updates[1]});
-  ASSERT_EQ(3u, GetNumTrees());
   ASSERT_TRUE(HasTree(tree_id_));
   ASSERT_TRUE(HasTree(tree_ids[0]));
   ASSERT_TRUE(HasTree(tree_ids[1]));
 
   // Remove all of the trees.
   OnAXTreeDestroyed(tree_id_);
-  ASSERT_EQ(2u, GetNumTrees());
+  ASSERT_FALSE(HasTree(tree_id_));
   ASSERT_TRUE(HasTree(tree_ids[0]));
   ASSERT_TRUE(HasTree(tree_ids[1]));
   OnAXTreeDestroyed(tree_ids[0]);
-  ASSERT_EQ(1u, GetNumTrees());
+  ASSERT_FALSE(HasTree(tree_ids[0]));
   ASSERT_TRUE(HasTree(tree_ids[1]));
   OnAXTreeDestroyed(tree_ids[1]);
-  ASSERT_EQ(0u, GetNumTrees());
+  ASSERT_FALSE(HasTree(tree_ids[1]));
 }
 
-TEST_F(ReadAnythingAppControllerTest, OnAXTreeDestroyed_ClearsPendingUpdates) {
+TEST_F(ReadAnythingAppControllerTest, OnAXTreeDestroyed_EraseTreeCalled) {
   // Set the name of each node to be its id.
   ui::AXTreeUpdate initial_update;
   SetUpdateTreeID(&initial_update);
@@ -860,19 +812,17 @@
   EXPECT_CALL(*distiller_, Distill).Times(1);
   AccessibilityEventReceived({updates[0]});
   EXPECT_EQ("2345", GetTextContent(1));
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
-  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
 
   // Send update 1. Since distillation is in progress, this will not be
   // unserialized yet.
   EXPECT_CALL(*distiller_, Distill).Times(0);
   AccessibilityEventReceived({updates[1]});
   EXPECT_EQ("2345", GetTextContent(1));
-  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
 
   // Destroy the tree.
+  ASSERT_TRUE(HasTree(tree_id_));
   OnAXTreeDestroyed(tree_id_);
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+  ASSERT_FALSE(HasTree(tree_id_));
 }
 
 TEST_F(ReadAnythingAppControllerTest,
@@ -920,33 +870,27 @@
   EXPECT_CALL(*distiller_, Distill).Times(1);
   AccessibilityEventReceived({updates[0]});
   EXPECT_EQ("2345", GetTextContent(1));
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
-  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
 
   // Send update 1. Since distillation is in progress, this will not be
   // unserialized yet.
   EXPECT_CALL(*distiller_, Distill).Times(0);
   AccessibilityEventReceived({updates[1]});
   EXPECT_EQ("2345", GetTextContent(1));
-  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
 
   // Send update 2. This is still not unserialized yet.
   EXPECT_CALL(*distiller_, Distill).Times(0);
   AccessibilityEventReceived({updates[2]});
   EXPECT_EQ("2345", GetTextContent(1));
-  EXPECT_EQ(2u, GetNumPendingUpdates(tree_id_));
 
   // Complete distillation which unserializes the pending updates and distills
   // them.
   EXPECT_CALL(*distiller_, Distill).Times(2);
   OnAXTreeDistilled({1});
   EXPECT_EQ("234567", GetTextContent(1));
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
-  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
 }
 
 TEST_F(ReadAnythingAppControllerTest,
-       AddPendingUpdatesAfterUnserializingOnSameTree_DoesNotCrash) {
+       AccessibilityReceivedAfterDistillingOnSameTree_DoesNotCrash) {
   // Set the name of each node to be its id.
   ui::AXTreeUpdate initial_update;
   SetUpdateTreeID(&initial_update);
@@ -989,14 +933,11 @@
   // Send update 0, which starts distillation.
   EXPECT_CALL(*distiller_, Distill).Times(1);
   AccessibilityEventReceived({updates[0]});
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
-  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
 
   // Send update 1. Since distillation is in progress, this will not be
   // unserialized yet.
   EXPECT_CALL(*distiller_, Distill).Times(0);
   AccessibilityEventReceived({updates[1]});
-  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
 
   // Ensure that there are no crashes after an accessibility event is received
   // immediately after distilling.
@@ -1004,32 +945,10 @@
   OnAXTreeDistilled({1});
   SetDistillationInProgress(true);
   AccessibilityEventReceived({updates[2]});
-  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
-  ASSERT_FALSE(AreAllPendingUpdatesEmpty());
-}
-
-TEST_F(ReadAnythingAppControllerTest,
-       DistillationInProgress_TreeUpdateReceivedOnInactiveTree) {
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
-
-  // Create a new tree.
-  ui::AXTreeID tree_id_2 = ui::AXTreeID::CreateNewAXTreeID();
-  ui::AXTreeUpdate update_2;
-  SetUpdateTreeID(&update_2, tree_id_2);
-  update_2.root_id = 1;
-  update_2.nodes.resize(1);
-  update_2.nodes[0].id = 1;
-
-  // Updates on inactive trees are processed immediately and are not marked as
-  // pending.
-  AccessibilityEventReceived({update_2});
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
 }
 
 TEST_F(ReadAnythingAppControllerTest,
        DistillationInProgress_ActiveTreeIDChanges) {
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
-
   // Create a couple of updates which add additional nodes to the tree.
   std::vector<ui::AXTreeUpdate> updates;
   std::vector<int> child_ids = {2, 3, 4};
@@ -1052,20 +971,18 @@
 
   EXPECT_CALL(*distiller_, Distill).Times(1);
   AccessibilityEventReceived({updates[0]});
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
   EXPECT_CALL(*distiller_, Distill).Times(0);
   AccessibilityEventReceived({updates[1]});
-  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
   EXPECT_CALL(*distiller_, Distill).Times(0);
   AccessibilityEventReceived({updates[2]});
-  EXPECT_EQ(2u, GetNumPendingUpdates(tree_id_));
   EXPECT_EQ("5", GetTextContent(1));
 
-  // Switching the active AXTreeID deletes the pending updates.
+  // Calling OnActiveAXTreeID updates the active AXTreeID.
   ui::AXTreeID tree_id_2 = ui::AXTreeID::CreateNewAXTreeID();
   EXPECT_CALL(*distiller_, Distill).Times(0);
+  ASSERT_EQ(tree_id_, ActiveTreeId());
   OnActiveAXTreeIDChanged(tree_id_2);
-  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
+  ASSERT_EQ(tree_id_2, ActiveTreeId());
 }
 
 TEST_F(ReadAnythingAppControllerTest,
@@ -1097,9 +1014,6 @@
 
 TEST_F(ReadAnythingAppControllerTest,
        ChangeActiveTreeWithPendingUpdates_UnknownID) {
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
-  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
-
   // Create a couple of updates which add additional nodes to the tree.
   std::vector<ui::AXTreeUpdate> updates;
   std::vector<int> child_ids = {2, 3, 4};
@@ -1130,10 +1044,7 @@
   // Add the three updates.
   EXPECT_CALL(*distiller_, Distill).Times(1);
   AccessibilityEventReceived({updates[0]});
-  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
-  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
   AccessibilityEventReceived(tree_id_, {updates[1], updates[2]});
-  EXPECT_EQ(2u, GetNumPendingUpdates(tree_id_));
 
   // Switch to a new active tree. Should not crash.
   EXPECT_CALL(*distiller_, Distill).Times(0);
@@ -1217,8 +1128,7 @@
   update.tree_data.sel_anchor_offset = 0;
   update.tree_data.sel_focus_offset = 1;
   update.tree_data.sel_is_backward = false;
-  AccessibilityEventReceived({update});
-  OnAXTreeDistilled({});
+  AccessibilityEventReceivedWithUserSelection({update});
   EXPECT_EQ(3, StartNodeId());
   EXPECT_EQ(4, EndNodeId());
   EXPECT_EQ(0, StartOffset());
@@ -1234,8 +1144,7 @@
   update.tree_data.sel_anchor_offset = 1;
   update.tree_data.sel_focus_offset = 0;
   update.tree_data.sel_is_backward = true;
-  AccessibilityEventReceived({update});
-  OnAXTreeDistilled({});
+  AccessibilityEventReceivedWithUserSelection({update});
   EXPECT_EQ(3, StartNodeId());
   EXPECT_EQ(4, EndNodeId());
   EXPECT_EQ(0, StartOffset());
@@ -1268,10 +1177,15 @@
   AccessibilityEventReceived({update_2});
   OnAXTreeDistilled({});
 
+  // We want to check that no crash occurs in this case. These node ids and
+  // offset are incorrect, they should be 2, 3, 0, and 5 (5 is the length of the
+  // world "Hello"). But because we don't have an AXTreeManager in the test,
+  // AXSelection::ToUnignoredSelection() exits early without calculating the
+  // actual ignored selection.
   EXPECT_EQ(2, StartNodeId());
-  EXPECT_EQ(3, EndNodeId());
+  EXPECT_EQ(4, EndNodeId());
   EXPECT_EQ(0, StartOffset());
-  EXPECT_EQ(5, EndOffset());  // The length of the word 'Hello'.
+  EXPECT_EQ(0, EndOffset());
 }
 
 TEST_F(ReadAnythingAppControllerTest, Selection_IsCollapsed) {
@@ -1281,8 +1195,7 @@
   update.tree_data.sel_focus_object_id = 2;
   update.tree_data.sel_anchor_offset = 3;
   update.tree_data.sel_focus_offset = 3;
-  AccessibilityEventReceived({update});
-  OnAXTreeDistilled({});
+  AccessibilityEventReceivedWithUserSelection({update});
   EXPECT_EQ(ui::kInvalidAXNodeID, StartNodeId());
   EXPECT_EQ(ui::kInvalidAXNodeID, EndNodeId());
   EXPECT_EQ(-1, StartOffset());
diff --git a/chrome/renderer/accessibility/read_anything_app_model.cc b/chrome/renderer/accessibility/read_anything_app_model.cc
index 07824070..c2ab81a 100644
--- a/chrome/renderer/accessibility/read_anything_app_model.cc
+++ b/chrome/renderer/accessibility/read_anything_app_model.cc
@@ -27,32 +27,42 @@
   display_node_ids_.insert(node);
 }
 
+void ReadAnythingAppModel::InsertSelectionNode(ui::AXNodeID node) {
+  selection_node_ids_.insert(node);
+}
+
 void ReadAnythingAppModel::Reset(
     const std::vector<ui::AXNodeID>& content_node_ids) {
   content_node_ids_ = content_node_ids;
   display_node_ids_.clear();
   distillation_in_progress_ = false;
+  ResetSelection();
+}
 
-  if (active_tree_id_ == ui::AXTreeIDUnknown() ||
-      !ContainsTree(active_tree_id_)) {
-    return;
-  }
+void ReadAnythingAppModel::ResetSelection() {
+  selection_node_ids_.clear();
+  start_node_id_ = ui::kInvalidAXNodeID;
+  end_node_id_ = ui::kInvalidAXNodeID;
+  start_offset_ = -1;
+  end_offset_ = -1;
+  has_selection_ = false;
+}
 
+void ReadAnythingAppModel::UpdateSelection() {
+  ResetSelection();
   ui::AXSelection selection =
       GetTreeFromId(active_tree_id_)->GetUnignoredSelection();
   has_selection_ = selection.anchor_object_id != ui::kInvalidAXNodeID &&
                    selection.focus_object_id != ui::kInvalidAXNodeID &&
                    !selection.IsCollapsed();
   if (!has_selection_) {
-    start_node_id_ = ui::kInvalidAXNodeID;
-    end_node_id_ = ui::kInvalidAXNodeID;
-    start_offset_ = -1;
-    end_offset_ = -1;
     return;
   }
 
   // Identify the start and end node ids and offsets. The start node comes
-  // earlier than end node in the tree order.
+  // earlier than end node in the tree order. We need to send the selection to
+  // JS in forward order. If they are sent as backward selections, JS will
+  // collapse the selection so no selection will be rendered in Read Anything.
   start_node_id_ = selection.is_backward ? selection.focus_object_id
                                          : selection.anchor_object_id;
   end_node_id_ = selection.is_backward ? selection.anchor_object_id
@@ -63,15 +73,9 @@
       selection.is_backward ? selection.anchor_offset : selection.focus_offset;
 }
 
-void ReadAnythingAppModel::SetStart(ui::AXNodeID start_node_id,
-                                    int32_t start_offset) {
-  start_node_id_ = start_node_id;
-  start_offset_ = start_offset;
-}
-void ReadAnythingAppModel::SetEnd(ui::AXNodeID end_node_id,
-                                  int32_t end_offset) {
-  end_node_id_ = end_node_id;
-  end_offset_ = end_offset;
+bool ReadAnythingAppModel::SelectionInsideDisplayNodes() {
+  return base::Contains(display_node_ids_, start_node_id_) &&
+         base::Contains(display_node_ids_, end_node_id_);
 }
 
 const std::unique_ptr<ui::AXSerializableTree>&
@@ -235,3 +239,13 @@
       return 2.0;
   }
 }
+
+std::map<ui::AXTreeID, std::vector<ui::AXTreeUpdate>>&
+ReadAnythingAppModel::GetPendingUpdatesForTesting() {
+  return pending_updates_map_;
+}
+
+std::map<ui::AXTreeID, std::unique_ptr<ui::AXSerializableTree>>*
+ReadAnythingAppModel::GetTreesForTesting() {
+  return &trees_;
+}
diff --git a/chrome/renderer/accessibility/read_anything_app_model.h b/chrome/renderer/accessibility/read_anything_app_model.h
index ab71d705..08c3889c0 100644
--- a/chrome/renderer/accessibility/read_anything_app_model.h
+++ b/chrome/renderer/accessibility/read_anything_app_model.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_RENDERER_ACCESSIBILITY_READ_ANYTHING_APP_MODEL_H_
 #define CHROME_RENDERER_ACCESSIBILITY_READ_ANYTHING_APP_MODEL_H_
 
+#include "base/containers/contains.h"
 #include "chrome/common/accessibility/read_anything.mojom.h"
 #include "chrome/common/accessibility/read_anything_constants.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -16,7 +17,6 @@
 class AXTreeObserver;
 }  // namespace ui
 
-class ReadAnythingAppControllerTest;
 // A class that holds state for the ReadAnythingAppController for the Read
 // Anything WebUI app.
 class ReadAnythingAppModel {
@@ -26,6 +26,7 @@
   ReadAnythingAppModel(const ReadAnythingAppModel& other) = delete;
   ReadAnythingAppModel& operator=(const ReadAnythingAppModel&) = delete;
 
+  // TODO(b/1266555): Ensure there is proper test coverage for all methods.
   // Theme
   const std::string& font_name() const { return font_name_; }
   float font_size() const { return font_size_; }
@@ -42,6 +43,7 @@
   int32_t end_offset() const { return end_offset_; }
 
   bool distillation_in_progress() const { return distillation_in_progress_; }
+  bool loading() const { return loading_; }
   const ukm::SourceId& active_ukm_source_id() const {
     return active_ukm_source_id_;
   }
@@ -50,20 +52,21 @@
   void SetDistillationInProgress(bool distillation) {
     distillation_in_progress_ = distillation;
   }
+  void SetLoading(bool loading) { loading_ = loading; }
   void SetActiveUkmSourceId(ukm::SourceId source_id) {
     active_ukm_source_id_ = source_id;
   }
   void SetActiveTreeId(ui::AXTreeID tree_id) { active_tree_id_ = tree_id; }
 
-  void SetStart(ui::AXNodeID start_node_id, int32_t start_offset);
-  void SetEnd(ui::AXNodeID end_node_id, int32_t end_offset);
-
   const std::vector<ui::AXNodeID>& content_node_ids() const {
     return content_node_ids_;
   }
   const std::set<ui::AXNodeID>& display_node_ids() const {
     return display_node_ids_;
   }
+  const std::set<ui::AXNodeID>& selection_node_ids() const {
+    return selection_node_ids_;
+  }
 
   ui::AXNode* GetAXNode(ui::AXNodeID ax_node_id) const;
   bool IsNodeIgnoredForReadAnything(ui::AXNodeID ax_node_id) const;
@@ -71,7 +74,10 @@
   void OnThemeChanged(read_anything::mojom::ReadAnythingThemePtr new_theme);
 
   void InsertDisplayNode(ui::AXNodeID node);
+  void InsertSelectionNode(ui::AXNodeID node);
   void Reset(const std::vector<ui::AXNodeID>& content_node_ids);
+  void UpdateSelection();
+  bool SelectionInsideDisplayNodes();
 
   const std::unique_ptr<ui::AXSerializableTree>& GetTreeFromId(
       ui::AXTreeID tree_id) const;
@@ -90,12 +96,20 @@
                                   const std::vector<ui::AXTreeUpdate>& updates,
                                   ui::AXTreeObserver* tree_observer);
 
+  std::map<ui::AXTreeID, std::vector<ui::AXTreeUpdate>>&
+  GetPendingUpdatesForTesting();
+
+  std::map<ui::AXTreeID, std::unique_ptr<ui::AXSerializableTree>>*
+  GetTreesForTesting();
+
  private:
-  friend ReadAnythingAppControllerTest;
   double GetLetterSpacingValue(
       read_anything::mojom::LetterSpacing letter_spacing) const;
   double GetLineSpacingValue(
       read_anything::mojom::LineSpacing line_spacing) const;
+
+  void ResetSelection();
+
   void AddPendingUpdates(const ui::AXTreeID tree_id,
                          const std::vector<ui::AXTreeUpdate>& updates);
 
@@ -121,6 +135,10 @@
   // new distillation requests during that time.
   bool distillation_in_progress_ = false;
 
+  // Loading should be set to true if we are in the process of distilling the
+  // active tree for the first time.
+  bool loading_ = false;
+
   // A mapping of a tree ID to a queue of pending updates on the active AXTree,
   // which will be unserialized once distillation completes.
   std::map<ui::AXTreeID, std::vector<ui::AXTreeUpdate>> pending_updates_map_;
@@ -130,12 +148,15 @@
   // distiller, these are heading or paragraph subtrees.
   std::vector<ui::AXNodeID> content_node_ids_;
 
-  // The node IDs that are displayed in the Read Anything app. This contains
-  // all ancestors and descendants of each content node. Or, if no content
-  // nodes were identified, this contains all nodes between the start and end
-  // nodes of the selection.
+  // This contains all ancestors and descendants of each content node. These
+  // nodes will be displayed in the Read Anything app if there is no user
+  // selection or if the users selection is contained within these nodes.
   std::set<ui::AXNodeID> display_node_ids_;
 
+  // If the user's selection contains nodes outside of display_node_ids, this
+  // contains all nodes between the start and end nodes of the selection.
+  std::set<ui::AXNodeID> selection_node_ids_;
+
   // Theme information.
   std::string font_name_ = string_constants::kReadAnythingDefaultFontName;
   float font_size_ = kReadAnythingDefaultFontScale;
diff --git a/chrome/renderer/accessibility/read_anything_app_model_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_model_browsertest.cc
new file mode 100644
index 0000000..17eda336
--- /dev/null
+++ b/chrome/renderer/accessibility/read_anything_app_model_browsertest.cc
@@ -0,0 +1,519 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/accessibility/read_anything_app_model.h"
+
+#include "chrome/test/base/chrome_render_view_test.h"
+#include "ui/accessibility/ax_serializable_tree.h"
+#include "ui/accessibility/ax_tree_observer.h"
+
+class ReadAnythingAppModelTest : public ChromeRenderViewTest {
+ public:
+  ReadAnythingAppModelTest() = default;
+  ~ReadAnythingAppModelTest() override = default;
+  ReadAnythingAppModelTest(const ReadAnythingAppModelTest&) = delete;
+  ReadAnythingAppModelTest& operator=(const ReadAnythingAppModelTest&) = delete;
+
+  void SetUp() override {
+    ChromeRenderViewTest::SetUp();
+    model_ = new ReadAnythingAppModel();
+
+    // Create a tree id.
+    tree_id_ = ui::AXTreeID::CreateNewAXTreeID();
+
+    // Create simple AXTreeUpdate with a root node and 3 children.
+    ui::AXTreeUpdate snapshot;
+    snapshot.root_id = 1;
+    snapshot.nodes.resize(4);
+    snapshot.nodes[0].id = 1;
+    snapshot.nodes[0].child_ids = {2, 3, 4};
+    snapshot.nodes[1].id = 2;
+    snapshot.nodes[2].id = 3;
+    snapshot.nodes[3].id = 4;
+    SetUpdateTreeID(&snapshot);
+
+    AccessibilityEventReceived({snapshot});
+    SetActiveTreeId(tree_id_);
+    Reset({});
+  }
+
+  void SetUpdateTreeID(ui::AXTreeUpdate* update) {
+    SetUpdateTreeID(update, tree_id_);
+  }
+
+  void SetDistillationInProgress(bool distillation) {
+    model_->SetDistillationInProgress(distillation);
+  }
+
+  bool AreAllPendingUpdatesEmpty() {
+    size_t count = 0;
+    for (auto const& [tree_id, updates] :
+         model_->GetPendingUpdatesForTesting()) {
+      count += updates.size();
+    }
+    return count == 0;
+  }
+
+  void SetUpdateTreeID(ui::AXTreeUpdate* update, ui::AXTreeID tree_id) {
+    ui::AXTreeData tree_data;
+    tree_data.tree_id = tree_id;
+    update->has_tree_data = true;
+    update->tree_data = tree_data;
+  }
+
+  void SetThemeForTesting(const std::string& font_name,
+                          float font_size,
+                          SkColor foreground_color,
+                          SkColor background_color,
+                          int line_spacing,
+                          int letter_spacing) {
+    auto line_spacing_enum =
+        static_cast<read_anything::mojom::LineSpacing>(line_spacing);
+    auto letter_spacing_enum =
+        static_cast<read_anything::mojom::LetterSpacing>(letter_spacing);
+    model_->OnThemeChanged(read_anything::mojom::ReadAnythingTheme::New(
+        font_name, font_size, foreground_color, background_color,
+        line_spacing_enum, letter_spacing_enum));
+  }
+
+  void AccessibilityEventReceived(
+      const std::vector<ui::AXTreeUpdate>& updates) {
+    AccessibilityEventReceived(updates[0].tree_data.tree_id, updates);
+  }
+
+  void AccessibilityEventReceived(
+      const ui::AXTreeID& tree_id,
+      const std::vector<ui::AXTreeUpdate>& updates) {
+    model_->AccessibilityEventReceived(tree_id, updates, ax_tree_observer);
+  }
+
+  void SetActiveTreeId(ui::AXTreeID tree_id) {
+    model_->SetActiveTreeId(tree_id);
+  }
+
+  void UnserializePendingUpdates(ui::AXTreeID tree_id) {
+    model_->UnserializePendingUpdates(tree_id);
+  }
+
+  void ClearPendingUpdates() { model_->ClearPendingUpdates(); }
+
+  std::string FontName() { return model_->font_name(); }
+
+  float FontSize() { return model_->font_size(); }
+
+  SkColor ForegroundColor() { return model_->foreground_color(); }
+
+  SkColor BackgroundColor() { return model_->background_color(); }
+
+  float LineSpacing() { return model_->line_spacing(); }
+
+  float LetterSpacing() { return model_->letter_spacing(); }
+
+  bool IsNodeIgnoredForReadAnything(ui::AXNodeID ax_node_id) {
+    return model_->IsNodeIgnoredForReadAnything(ax_node_id);
+  }
+
+  size_t GetNumTrees() { return model_->GetTreesForTesting()->size(); }
+
+  bool HasTree(ui::AXTreeID tree_id) { return model_->ContainsTree(tree_id); }
+
+  void EraseTree(ui::AXTreeID tree_id) { model_->EraseTree(tree_id); }
+
+  void AddTree(ui::AXTreeID tree_id,
+               std::unique_ptr<ui::AXSerializableTree> tree) {
+    model_->AddTree(tree_id, std::move(tree));
+  }
+
+  size_t GetNumPendingUpdates(ui::AXTreeID tree_id) {
+    return model_->GetPendingUpdatesForTesting()[tree_id].size();
+  }
+
+  void Reset(const std::vector<ui::AXNodeID>& content_node_ids) {
+    model_->Reset(content_node_ids);
+  }
+
+  ui::AXTreeID tree_id_;
+
+ private:
+  ui::AXTreeObserver* ax_tree_observer = new ui::AXTreeObserver();
+
+  // ReadAnythingAppModel constructor and destructor are private so it's
+  // not accessible by std::make_unique.
+  ReadAnythingAppModel* model_ = nullptr;
+};
+
+TEST_F(ReadAnythingAppModelTest, Theme) {
+  std::string font_name = "Roboto";
+  float font_size = 18.0;
+  SkColor foreground = SkColorSetRGB(0x33, 0x36, 0x39);
+  SkColor background = SkColorSetRGB(0xFD, 0xE2, 0x93);
+  int letter_spacing =
+      static_cast<int>(read_anything::mojom::LetterSpacing::kDefaultValue);
+  float letter_spacing_value = 0.0;
+  int line_spacing =
+      static_cast<int>(read_anything::mojom::LineSpacing::kDefaultValue);
+  float line_spacing_value = 1.5;
+  SetThemeForTesting(font_name, font_size, foreground, background, line_spacing,
+                     letter_spacing);
+  EXPECT_EQ(font_name, FontName());
+  EXPECT_EQ(font_size, FontSize());
+  EXPECT_EQ(foreground, ForegroundColor());
+  EXPECT_EQ(background, BackgroundColor());
+  EXPECT_EQ(line_spacing_value, LineSpacing());
+  EXPECT_EQ(letter_spacing_value, LetterSpacing());
+}
+
+TEST_F(ReadAnythingAppModelTest, IsNodeIgnoredForReadAnything) {
+  ui::AXTreeUpdate update;
+  SetUpdateTreeID(&update);
+  update.nodes.resize(3);
+  update.nodes[0].id = 2;
+  update.nodes[1].id = 3;
+  update.nodes[2].id = 4;
+  update.nodes[0].role = ax::mojom::Role::kStaticText;
+  update.nodes[1].role = ax::mojom::Role::kComboBoxGrouping;
+  update.nodes[2].role = ax::mojom::Role::kButton;
+  AccessibilityEventReceived({update});
+  EXPECT_EQ(false, IsNodeIgnoredForReadAnything(2));
+  EXPECT_EQ(true, IsNodeIgnoredForReadAnything(3));
+  EXPECT_EQ(true, IsNodeIgnoredForReadAnything(4));
+}
+
+TEST_F(ReadAnythingAppModelTest, ModelUpdatesTreeState) {
+  // Set up trees.
+  ui::AXTreeID tree_id_2 = ui::AXTreeID::CreateNewAXTreeID();
+  ui::AXTreeID tree_id_3 = ui::AXTreeID::CreateNewAXTreeID();
+
+  AddTree(tree_id_2, std::make_unique<ui::AXSerializableTree>());
+  AddTree(tree_id_3, std::make_unique<ui::AXSerializableTree>());
+
+  ASSERT_EQ(3u, GetNumTrees());
+  ASSERT_TRUE(HasTree(tree_id_2));
+  ASSERT_TRUE(HasTree(tree_id_3));
+  ASSERT_TRUE(HasTree(tree_id_));
+
+  // Remove one tree.
+  EraseTree(tree_id_2);
+  ASSERT_EQ(2u, GetNumTrees());
+  ASSERT_TRUE(HasTree(tree_id_3));
+  ASSERT_FALSE(HasTree(tree_id_2));
+  ASSERT_TRUE(HasTree(tree_id_));
+
+  // Remove the second tree.
+  EraseTree(tree_id_);
+  ASSERT_EQ(1u, GetNumTrees());
+  ASSERT_TRUE(HasTree(tree_id_3));
+  ASSERT_FALSE(HasTree(tree_id_2));
+  ASSERT_FALSE(HasTree(tree_id_));
+
+  // Remove the last tree.
+  EraseTree(tree_id_3);
+  ASSERT_EQ(0u, GetNumTrees());
+  ASSERT_FALSE(HasTree(tree_id_3));
+  ASSERT_FALSE(HasTree(tree_id_2));
+  ASSERT_FALSE(HasTree(tree_id_));
+}
+
+TEST_F(ReadAnythingAppModelTest, AddAndRemoveTrees) {
+  // Create two new trees with new tree IDs.
+  std::vector<ui::AXTreeID> tree_ids = {ui::AXTreeID::CreateNewAXTreeID(),
+                                        ui::AXTreeID::CreateNewAXTreeID()};
+  std::vector<ui::AXTreeUpdate> updates;
+  for (int i = 0; i < 2; i++) {
+    ui::AXTreeUpdate update;
+    SetUpdateTreeID(&update, tree_ids[i]);
+    update.root_id = 1;
+    update.nodes.resize(1);
+    update.nodes[0].id = 1;
+    updates.push_back(update);
+  }
+
+  // Start with 1 tree (the tree created in SetUp).
+  ASSERT_EQ(1u, GetNumTrees());
+  ASSERT_TRUE(HasTree(tree_id_));
+
+  // Add the two trees.
+  AccessibilityEventReceived({updates[0]});
+  ASSERT_EQ(2u, GetNumTrees());
+  ASSERT_TRUE(HasTree(tree_id_));
+  ASSERT_TRUE(HasTree(tree_ids[0]));
+  AccessibilityEventReceived({updates[1]});
+  ASSERT_EQ(3u, GetNumTrees());
+  ASSERT_TRUE(HasTree(tree_id_));
+  ASSERT_TRUE(HasTree(tree_ids[0]));
+  ASSERT_TRUE(HasTree(tree_ids[1]));
+
+  // Remove all of the trees.
+  EraseTree(tree_id_);
+  ASSERT_EQ(2u, GetNumTrees());
+  ASSERT_TRUE(HasTree(tree_ids[0]));
+  ASSERT_TRUE(HasTree(tree_ids[1]));
+  EraseTree(tree_ids[0]);
+  ASSERT_EQ(1u, GetNumTrees());
+  ASSERT_TRUE(HasTree(tree_ids[1]));
+  EraseTree(tree_ids[1]);
+  ASSERT_EQ(0u, GetNumTrees());
+}
+
+TEST_F(ReadAnythingAppModelTest,
+       DistillationInProgress_TreeUpdateReceivedOnInactiveTree) {
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+
+  // Create a new tree.
+  ui::AXTreeID tree_id_2 = ui::AXTreeID::CreateNewAXTreeID();
+  ui::AXTreeUpdate update_2;
+  SetUpdateTreeID(&update_2, tree_id_2);
+  update_2.root_id = 1;
+  update_2.nodes.resize(1);
+  update_2.nodes[0].id = 1;
+
+  // Updates on inactive trees are processed immediately and are not marked as
+  // pending.
+  AccessibilityEventReceived({update_2});
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+}
+
+TEST_F(ReadAnythingAppModelTest,
+       AddPendingUpdatesAfterUnserializingOnSameTree_DoesNotCrash) {
+  // Set the name of each node to be its id.
+  ui::AXTreeUpdate initial_update;
+  SetUpdateTreeID(&initial_update);
+  initial_update.root_id = 1;
+  initial_update.nodes.resize(3);
+  std::vector<int> child_ids;
+  for (int i = 0; i < 3; i++) {
+    int id = i + 2;
+    child_ids.push_back(id);
+    initial_update.nodes[i].id = id;
+    initial_update.nodes[i].role = ax::mojom::Role::kStaticText;
+    initial_update.nodes[i].SetName(base::NumberToString(id));
+    initial_update.nodes[i].SetNameFrom(ax::mojom::NameFrom::kContents);
+  }
+  AccessibilityEventReceived({initial_update});
+
+  std::vector<ui::AXTreeUpdate> updates;
+  for (int i = 0; i < 3; i++) {
+    int id = i + 5;
+    child_ids.push_back(id);
+
+    ui::AXTreeUpdate update;
+    SetUpdateTreeID(&update);
+    update.root_id = 1;
+    update.nodes.resize(2);
+    update.nodes[0].id = 1;
+    update.nodes[0].child_ids = child_ids;
+    update.nodes[1].id = id;
+    update.nodes[1].role = ax::mojom::Role::kStaticText;
+    update.nodes[1].SetName(base::NumberToString(id));
+    update.nodes[1].SetNameFrom(ax::mojom::NameFrom::kContents);
+    updates.push_back(update);
+  }
+
+  // Send update 0, which starts distillation.
+  AccessibilityEventReceived({updates[0]});
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
+
+  // Send update 1. Since distillation is in progress, this will not be
+  // unserialized yet.
+  SetDistillationInProgress(true);
+  AccessibilityEventReceived({updates[1]});
+  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
+
+  // Ensure that there are no crashes after an accessibility event is received
+  // immediately after unserializing.
+  UnserializePendingUpdates(tree_id_);
+  SetDistillationInProgress(true);
+  AccessibilityEventReceived({updates[2]});
+  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
+  ASSERT_FALSE(AreAllPendingUpdatesEmpty());
+}
+
+TEST_F(ReadAnythingAppModelTest, OnTreeErased_ClearsPendingUpdates) {
+  // Set the name of each node to be its id.
+  ui::AXTreeUpdate initial_update;
+  SetUpdateTreeID(&initial_update);
+  initial_update.root_id = 1;
+  initial_update.nodes.resize(3);
+  std::vector<int> child_ids;
+  for (int i = 0; i < 3; i++) {
+    int id = i + 2;
+    child_ids.push_back(id);
+    initial_update.nodes[i].id = id;
+    initial_update.nodes[i].role = ax::mojom::Role::kStaticText;
+    initial_update.nodes[i].SetName(base::NumberToString(id));
+    initial_update.nodes[i].SetNameFrom(ax::mojom::NameFrom::kContents);
+  }
+  AccessibilityEventReceived({initial_update});
+
+  std::vector<ui::AXTreeUpdate> updates;
+  for (int i = 0; i < 3; i++) {
+    int id = i + 5;
+    child_ids.push_back(id);
+
+    ui::AXTreeUpdate update;
+    SetUpdateTreeID(&update);
+    update.root_id = 1;
+    update.nodes.resize(2);
+    update.nodes[0].id = 1;
+    update.nodes[0].child_ids = child_ids;
+    update.nodes[1].id = id;
+    update.nodes[1].role = ax::mojom::Role::kStaticText;
+    update.nodes[1].SetName(base::NumberToString(id));
+    update.nodes[1].SetNameFrom(ax::mojom::NameFrom::kContents);
+    updates.push_back(update);
+  }
+
+  // Send update 0, which starts distillation.
+  AccessibilityEventReceived({updates[0]});
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
+
+  // Send update 1. Since distillation is in progress, this will not be
+  // unserialized yet.
+  SetDistillationInProgress(true);
+  AccessibilityEventReceived({updates[1]});
+  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
+
+  // Destroy the tree.
+  EraseTree(tree_id_);
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+}
+
+TEST_F(ReadAnythingAppModelTest,
+       DistillationInProgress_TreeUpdateReceivedOnActiveTree) {
+  // Set the name of each node to be its id.
+  ui::AXTreeUpdate initial_update;
+  SetUpdateTreeID(&initial_update);
+  initial_update.root_id = 1;
+  initial_update.nodes.resize(3);
+  std::vector<int> child_ids;
+  for (int i = 0; i < 3; i++) {
+    int id = i + 2;
+    child_ids.push_back(id);
+    initial_update.nodes[i].id = id;
+    initial_update.nodes[i].role = ax::mojom::Role::kStaticText;
+    initial_update.nodes[i].SetName(base::NumberToString(id));
+    initial_update.nodes[i].SetNameFrom(ax::mojom::NameFrom::kContents);
+  }
+  AccessibilityEventReceived({initial_update});
+
+  std::vector<ui::AXTreeUpdate> updates;
+  for (int i = 0; i < 3; i++) {
+    int id = i + 5;
+    child_ids.push_back(id);
+
+    ui::AXTreeUpdate update;
+    SetUpdateTreeID(&update);
+    update.root_id = 1;
+    update.nodes.resize(2);
+    update.nodes[0].id = 1;
+    update.nodes[0].child_ids = child_ids;
+    update.nodes[1].id = id;
+    update.nodes[1].role = ax::mojom::Role::kStaticText;
+    update.nodes[1].SetName(base::NumberToString(id));
+    update.nodes[1].SetNameFrom(ax::mojom::NameFrom::kContents);
+    updates.push_back(update);
+  }
+
+  // Send update 0, which starts distillation.
+  AccessibilityEventReceived({updates[0]});
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
+
+  // Send update 1. Since distillation is in progress, this will not be
+  // unserialized yet.
+  SetDistillationInProgress(true);
+  AccessibilityEventReceived({updates[1]});
+  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
+
+  // Send update 2. This is still not unserialized yet.
+  AccessibilityEventReceived({updates[2]});
+  EXPECT_EQ(2u, GetNumPendingUpdates(tree_id_));
+
+  // Complete distillation which unserializes the pending updates and distills
+  // them.
+  UnserializePendingUpdates(tree_id_);
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
+}
+
+TEST_F(ReadAnythingAppModelTest, ClearPendingUpdates_DeletesPendingUpdates) {
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+
+  // Create a couple of updates which add additional nodes to the tree.
+  std::vector<ui::AXTreeUpdate> updates;
+  std::vector<int> child_ids = {2, 3, 4};
+  for (int i = 0; i < 3; i++) {
+    int id = i + 5;
+    child_ids.push_back(id);
+
+    ui::AXTreeUpdate update;
+    SetUpdateTreeID(&update);
+    update.root_id = 1;
+    update.nodes.resize(2);
+    update.nodes[0].id = 1;
+    update.nodes[0].child_ids = child_ids;
+    update.nodes[1].id = id;
+    update.nodes[1].role = ax::mojom::Role::kStaticText;
+    update.nodes[1].SetName(base::NumberToString(id));
+    update.nodes[1].SetNameFrom(ax::mojom::NameFrom::kContents);
+    updates.push_back(update);
+  }
+
+  AccessibilityEventReceived({updates[0]});
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+  SetDistillationInProgress(true);
+  AccessibilityEventReceived({updates[1]});
+  EXPECT_EQ(1u, GetNumPendingUpdates(tree_id_));
+  AccessibilityEventReceived({updates[2]});
+  EXPECT_EQ(2u, GetNumPendingUpdates(tree_id_));
+
+  // Clearing the pending updates correctly deletes the pending updates.
+  ClearPendingUpdates();
+  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
+}
+
+TEST_F(ReadAnythingAppModelTest, ChangeActiveTreeWithPendingUpdates_UnknownID) {
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
+
+  // Create a couple of updates which add additional nodes to the tree.
+  std::vector<ui::AXTreeUpdate> updates;
+  std::vector<int> child_ids = {2, 3, 4};
+  for (int i = 0; i < 2; i++) {
+    int id = i + 5;
+    child_ids.push_back(id);
+
+    ui::AXTreeUpdate update;
+    SetUpdateTreeID(&update);
+    update.root_id = 1;
+    update.nodes.resize(2);
+    update.nodes[0].id = 1;
+    update.nodes[0].child_ids = child_ids;
+    update.nodes[1].id = id;
+    update.nodes[1].role = ax::mojom::Role::kStaticText;
+    update.nodes[1].SetName(base::NumberToString(id));
+    update.nodes[1].SetNameFrom(ax::mojom::NameFrom::kContents);
+    updates.push_back(update);
+  }
+
+  // Create an update which has no tree id.
+  ui::AXTreeUpdate update;
+  update.nodes.resize(1);
+  update.nodes[0].id = 1;
+  update.nodes[0].role = ax::mojom::Role::kGenericContainer;
+  updates.push_back(update);
+
+  // Add the three updates.
+  AccessibilityEventReceived({updates[0]});
+  EXPECT_EQ(0u, GetNumPendingUpdates(tree_id_));
+  ASSERT_TRUE(AreAllPendingUpdatesEmpty());
+  SetDistillationInProgress(true);
+  AccessibilityEventReceived(tree_id_, {updates[1], updates[2]});
+  EXPECT_EQ(2u, GetNumPendingUpdates(tree_id_));
+
+  // Switch to a new active tree. Should not crash.
+  SetActiveTreeId(ui::AXTreeIDUnknown());
+}
diff --git a/chrome/services/mac_notifications/mac_notification_service_un_unittest.mm b/chrome/services/mac_notifications/mac_notification_service_un_unittest.mm
index c0b7721..89fbb2d 100644
--- a/chrome/services/mac_notifications/mac_notification_service_un_unittest.mm
+++ b/chrome/services/mac_notifications/mac_notification_service_un_unittest.mm
@@ -122,19 +122,19 @@
             notification_id,
             mojom::ProfileIdentifier::New(profile_id, incognito))));
 
-    UNMutableNotificationContent* content =
-        [[UNMutableNotificationContent alloc] init];
-    content.userInfo = @{
+    base::scoped_nsobject<UNMutableNotificationContent> content(
+        [[UNMutableNotificationContent alloc] init]);
+    content.get().userInfo = @{
       kNotificationId : base::SysUTF8ToNSString(notification_id),
       kNotificationProfileId : base::SysUTF8ToNSString(profile_id),
       kNotificationIncognito : [NSNumber numberWithBool:incognito],
     };
     if (!category_id.empty())
-      content.categoryIdentifier = base::SysUTF8ToNSString(category_id);
+      content.get().categoryIdentifier = base::SysUTF8ToNSString(category_id);
 
     UNNotificationRequest* request =
         [UNNotificationRequest requestWithIdentifier:identifier
-                                             content:content
+                                             content:content.get()
                                              trigger:nil];
 
     base::scoped_nsobject<FakeUNNotification> notification(
diff --git a/chrome/services/mac_notifications/notification_category_manager_unittest.mm b/chrome/services/mac_notifications/notification_category_manager_unittest.mm
index e4f3180..7639c7b 100644
--- a/chrome/services/mac_notifications/notification_category_manager_unittest.mm
+++ b/chrome/services/mac_notifications/notification_category_manager_unittest.mm
@@ -49,13 +49,13 @@
   base::scoped_nsobject<FakeUNNotification> CreateNotification(
       NSString* identifier,
       UNNotificationCategory* category) {
-    UNMutableNotificationContent* content =
-        [[UNMutableNotificationContent alloc] init];
-    content.categoryIdentifier = [category identifier];
+    base::scoped_nsobject<UNMutableNotificationContent> content(
+        [[UNMutableNotificationContent alloc] init]);
+    content.get().categoryIdentifier = [category identifier];
 
     UNNotificationRequest* request =
         [UNNotificationRequest requestWithIdentifier:identifier
-                                             content:content
+                                             content:content.get()
                                              trigger:nil];
 
     base::scoped_nsobject<FakeUNNotification> notification(
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 7f8de569..b67df00 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -610,6 +610,8 @@
       "../browser/ash/login/lock/screen_locker_tester.h",
       "../browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.cc",
       "../browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.h",
+      "../browser/ash/login/users/avatar/user_image_manager_test_util.cc",
+      "../browser/ash/login/users/avatar/user_image_manager_test_util.h",
       "../browser/chromeos/extensions/login_screen/login_screen_apitest_base.cc",
       "../browser/chromeos/extensions/login_screen/login_screen_apitest_base.h",
       "../browser/component_updater/fake_cros_component_manager.cc",
@@ -2392,6 +2394,7 @@
       "../common/time_format_browsertest.cc",
       "../renderer/accessibility/ax_tree_distiller_browsertest.cc",
       "../renderer/accessibility/read_anything_app_controller_browsertest.cc",
+      "../renderer/accessibility/read_anything_app_model_browsertest.cc",
       "../renderer/autofill/autofill_renderer_browsertest.cc",
       "../renderer/autofill/fake_mojo_password_manager_driver.cc",
       "../renderer/autofill/fake_mojo_password_manager_driver.h",
@@ -4008,8 +4011,6 @@
         "../browser/ash/login/user_allowlist_policy_browsertest.cc",
         "../browser/ash/login/user_flags_login_browsertest.cc",
         "../browser/ash/login/users/avatar/user_image_manager_browsertest.cc",
-        "../browser/ash/login/users/avatar/user_image_manager_test_util.cc",
-        "../browser/ash/login/users/avatar/user_image_manager_test_util.h",
         "../browser/ash/login/users/wallpaper_policy_browsertest.cc",
         "../browser/ash/login/webview_login_browsertest.cc",
         "../browser/ash/login/wizard_controller_browsertest.cc",
@@ -7587,7 +7588,7 @@
       "../browser/ui/ash/assistant/device_actions_unittest.cc",
       "../browser/ui/ash/assistant/search_and_assistant_enabled_checker_unittest.cc",
       "../browser/ui/ash/calendar/calendar_keyed_service_unittest.cc",
-      "../browser/ui/ash/desks/chrome_desks_templates_delegate_unittest.cc",
+      "../browser/ui/ash/desks/chrome_saved_desk_delegate_unittest.cc",
       "../browser/ui/ash/device_scheduled_reboot/reboot_notification_controller_unittest.cc",
       "../browser/ui/ash/device_scheduled_reboot/scheduled_reboot_dialog_unittest.cc",
       "../browser/ui/ash/glanceables/glanceables_keyed_service_factory_unittest.cc",
@@ -8603,6 +8604,7 @@
       "../browser/component_updater/real_time_url_checks_allowlist_component_installer_unittest.cc",
       "../browser/safe_browsing/android/password_reuse_controller_android_unittest.cc",
       "../browser/safe_browsing/tailored_security/chrome_tailored_security_service_android_unittest.cc",
+      "../browser/safe_browsing/tailored_security/consented_message_android_unittest.cc",
       "../browser/safe_browsing/telemetry/android/android_telemetry_service_unittest.cc",
     ]
 
diff --git a/chrome/test/data/chromedriver/orientation_test.html b/chrome/test/data/chromedriver/orientation_test.html
deleted file mode 100644
index 8c73a7d..0000000
--- a/chrome/test/data/chromedriver/orientation_test.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<html>
-  <title>orientation test</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-  </head>
-  <body>
-    <script type="text/javascript">
-      var testnumber = 1;
-
-      window.addEventListener('orientationchange', function() {
-        var elt = document.getElementById('orientation');
-        elt.innerHTML = 'orientation change ' + testnumber;
-        testnumber++;
-      });
-
-    </script>
-    <div id='orientation'>
-    </div>
-  </body>
-</html>
diff --git a/chrome/test/data/webui/chromeos/cloud_upload/cloud_upload_test_browser_proxy.ts b/chrome/test/data/webui/chromeos/cloud_upload/cloud_upload_test_browser_proxy.ts
index ab7f081..73ef016 100644
--- a/chrome/test/data/webui/chromeos/cloud_upload/cloud_upload_test_browser_proxy.ts
+++ b/chrome/test/data/webui/chromeos/cloud_upload/cloud_upload_test_browser_proxy.ts
@@ -12,7 +12,7 @@
   installOfficeWebAppResult: boolean;
   odfsMounted: boolean;
   dialogPage: DialogPage;
-  tasks?: DialogTask[]|null;
+  localTasks?: DialogTask[]|null;
   firstTimeSetup?: boolean|null;
   officeMoveConfirmationShown?: boolean|null;
 }
@@ -29,14 +29,14 @@
     const args: DialogArgs = {
       fileNames: [],
       dialogPage: options.dialogPage,
-      tasks: [],
+      localTasks: [],
       firstTimeSetup: true,
     };
     if (options.fileName != null) {
       args.fileNames.push(options.fileName);
     }
-    if (options.tasks != null) {
-      args.tasks = options.tasks;
+    if (options.localTasks != null) {
+      args.localTasks = options.localTasks;
     }
     if (options.firstTimeSetup != null) {
       args.firstTimeSetup = options.firstTimeSetup;
diff --git a/chrome/test/data/webui/chromeos/cloud_upload/file_handler_page_test.ts b/chrome/test/data/webui/chromeos/cloud_upload/file_handler_page_test.ts
index c9fd95f0..a04ec3e 100644
--- a/chrome/test/data/webui/chromeos/cloud_upload/file_handler_page_test.ts
+++ b/chrome/test/data/webui/chromeos/cloud_upload/file_handler_page_test.ts
@@ -80,7 +80,7 @@
       installOfficeWebAppResult: false,
       odfsMounted: false,
       dialogPage: DialogPage.kFileHandlerDialog,
-      tasks: createTasks(numTasks),
+      localTasks: createTasks(numTasks),
     });
 
     assertEquals(fileHandlerPageApp.cloudProviderCards.length, 2);
@@ -113,7 +113,7 @@
       installOfficeWebAppResult: false,
       odfsMounted: false,
       dialogPage: DialogPage.kFileHandlerDialog,
-      tasks: createTasks(numTasks),
+      localTasks: createTasks(numTasks),
     });
 
     assertEquals(fileHandlerPageApp.cloudProviderCards.length, 2);
@@ -145,7 +145,7 @@
       installOfficeWebAppResult: false,
       odfsMounted: false,
       dialogPage: DialogPage.kFileHandlerDialog,
-      tasks: createTasks(numTasks),
+      localTasks: createTasks(numTasks),
     });
 
     assertEquals(fileHandlerPageApp.cloudProviderCards.length, 2);
@@ -178,7 +178,7 @@
       installOfficeWebAppResult: false,
       odfsMounted: false,
       dialogPage: DialogPage.kFileHandlerDialog,
-      tasks: createTasks(numTasks),
+      localTasks: createTasks(numTasks),
     });
 
     assertEquals(fileHandlerPageApp.cloudProviderCards.length, 2);
@@ -213,7 +213,7 @@
               installOfficeWebAppResult: false,
               odfsMounted: false,
               dialogPage: DialogPage.kFileHandlerDialog,
-              tasks: createTasks(numTasks),
+              localTasks: createTasks(numTasks),
             });
             const accordionCard =
                 fileHandlerPageApp.$<AccordionTopCardElement>('#accordion');
@@ -259,7 +259,7 @@
               installOfficeWebAppResult: false,
               odfsMounted: false,
               dialogPage: DialogPage.kFileHandlerDialog,
-              tasks: createTasks(numTasks),
+              localTasks: createTasks(numTasks),
             });
             const accordionCard =
                 fileHandlerPageApp.$<AccordionTopCardElement>('#accordion');
@@ -297,7 +297,7 @@
       installOfficeWebAppResult: false,
       odfsMounted: false,
       dialogPage: DialogPage.kFileHandlerDialog,
-      tasks: [],
+      localTasks: [],
     });
     assertEquals(fileHandlerPageApp.cloudProviderCards.length, 2);
     assertEquals(fileHandlerPageApp.localHandlerCards.length, numTasks);
@@ -318,7 +318,7 @@
           installOfficeWebAppResult: false,
           odfsMounted: false,
           dialogPage: DialogPage.kFileHandlerDialog,
-          tasks: createTasks(numTasks),
+          localTasks: createTasks(numTasks),
         });
         const accordionCard =
             fileHandlerPageApp.$<AccordionTopCardElement>('#accordion');
diff --git a/chrome/test/data/webui/chromeos/personalization_app/avatar_list_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/avatar_list_element_test.ts
index 9f64d5a..5054ae4b 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/avatar_list_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/avatar_list_element_test.ts
@@ -6,6 +6,7 @@
 import 'chrome://webui-test/mojo_webui_test_support.js';
 
 import {AvatarCameraMode, AvatarList, UserActionName, UserImageObserver} from 'chrome://personalization/js/personalization_app.js';
+import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
 import {assertDeepEquals, assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
@@ -167,4 +168,50 @@
         !avatarListElement.shadowRoot!.querySelector('avatar-camera'),
         'avatar-camera should be gone because camera no longer available');
   });
+
+  test('custom avatar selectors are shown with pref enabled', async () => {
+    testPersonalizationStore.data.user.isCameraPresent = true;
+    testPersonalizationStore.data.user.profileImage =
+        testUserProvider.profileImage;
+    avatarListElement = initElement(AvatarList);
+
+    await waitAfterNextRender(avatarListElement);
+
+    assertTrue(
+        !!avatarListElement!.shadowRoot!.getElementById('openCamera'),
+        'open camera button exists');
+    assertTrue(
+        !!avatarListElement!.shadowRoot!.getElementById('openVideo'),
+        'open video button exists');
+    assertTrue(
+        !!avatarListElement!.shadowRoot!.getElementById('openFolder'),
+        'open folder button exists');
+    assertTrue(
+        !!avatarListElement!.shadowRoot!.getElementById('profileImage'),
+        'select profile image button exists');
+  });
+
+  test('custom avatar selectors are not shown with pref disabled', async () => {
+    loadTimeData.overrideValues(
+        {isUserAvatarCustomizationSelectorsEnabled: false});
+    testPersonalizationStore.data.user.isCameraPresent = true;
+    testPersonalizationStore.data.user.profileImage =
+        testUserProvider.profileImage;
+    avatarListElement = initElement(AvatarList);
+
+    await waitAfterNextRender(avatarListElement);
+
+    assertTrue(
+        !avatarListElement!.shadowRoot!.getElementById('openCamera'),
+        'open camera button does not exist');
+    assertTrue(
+        !avatarListElement!.shadowRoot!.getElementById('openVideo'),
+        'open video button does not exist');
+    assertTrue(
+        !avatarListElement!.shadowRoot!.getElementById('openFolder'),
+        'open folder button does not exist');
+    assertTrue(
+        !avatarListElement!.shadowRoot!.getElementById('profileImage'),
+        'select profile button does not exist');
+  });
 });
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_zero_state_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/google_photos_zero_state_element_test.ts
index 76c2879..0132a4a 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_zero_state_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_zero_state_element_test.ts
@@ -34,11 +34,24 @@
       googlePhotosZeroStateElement.tab = tab;
       await waitAfterNextRender(googlePhotosZeroStateElement);
 
+      const localizedLink =
+          googlePhotosZeroStateElement.shadowRoot!.querySelector(
+              'localized-link');
+
+      assertTrue(!!localizedLink, 'localized link exists');
+
+      // `localizedLink.localizedString` typescript type is string but is
+      // actually TrustedHTML.
+      assertTrue(
+          (localizedLink.localizedString as unknown) instanceof TrustedHTML,
+          'localizedLink has message set as TrustedHTML');
       assertEquals(
-          'No image available. To add photos, go to photos.google.com',
-          googlePhotosZeroStateElement.shadowRoot!.getElementById(
-                                                      'message')!.innerText,
-          'inner text matches');
+          'No image available. To add photos, go to ' +
+              '<a target="_blank" href="https://photos.google.com">' +
+              'photos.google.com</a>',
+          localizedLink.localizedString.toString(),
+          'localized link message matches');
+
       assertTrue(
           !!googlePhotosZeroStateElement.shadowRoot!.querySelector('img'),
           'img is shown');
@@ -50,10 +63,24 @@
     googlePhotosZeroStateElement.tab = GooglePhotosTab.PHOTOS_BY_ALBUM_ID;
     await waitAfterNextRender(googlePhotosZeroStateElement);
 
+    const localizedLink =
+        googlePhotosZeroStateElement.shadowRoot!.querySelector(
+            'localized-link');
+
+    assertTrue(!!localizedLink, 'localized link exists');
+
+    // `localizedLink.localizedString` typescript type is string but is
+    // actually TrustedHTML.
+    assertTrue(
+        (localizedLink.localizedString as unknown) instanceof TrustedHTML,
+        'localizedLink has message set as TrustedHTML');
+
     assertEquals(
-        `This album doesn't have any photos. To add photos, go to photos.google.com`,
-        googlePhotosZeroStateElement.shadowRoot!.getElementById(
-                                                    'message')!.innerText,
+        `This album doesn't have any photos. ` +
+            'To add photos, go to ' +
+            '<a target="_blank" href="https://photos.google.com">' +
+            'photos.google.com</a>',
+        localizedLink.localizedString.toString(),
         'inner text matches on photos_by_album_id tab');
 
     assertTrue(
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/network_config_test.js b/chrome/test/data/webui/cr_components/chromeos/network/network_config_test.js
index 9c93fb0..c2fe223 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network/network_config_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network/network_config_test.js
@@ -992,6 +992,12 @@
       await flushAsync();
       assertTrue(networkConfig.enableConnect);
 
+      peer.endpoint = '[fd01::1]:12345';
+      networkConfig.notifyPath(
+          `configProperties_.typeConfig.vpn.wireguard.peers.0.endpoint`);
+      await flushAsync();
+      assertTrue(networkConfig.enableConnect);
+
       peer.presharedKey = 'invalid_key';
       networkConfig.notifyPath(
           `configProperties_.typeConfig.vpn.wireguard.peers.0.presharedKey`);
diff --git a/chrome/test/data/webui/cr_elements/cr_url_list_item_test.ts b/chrome/test/data/webui/cr_elements/cr_url_list_item_test.ts
index a6803c71..5d0ac7d 100644
--- a/chrome/test/data/webui/cr_elements/cr_url_list_item_test.ts
+++ b/chrome/test/data/webui/cr_elements/cr_url_list_item_test.ts
@@ -106,4 +106,33 @@
     // No more than two images may be displayed for a folder.
     assertEquals(2, imageElements.length);
   });
+
+  test('DisplaysImageAfterLoad', () => {
+    element.url = 'http://google.com';
+    element.imageUrls = [
+      'http://www.image.png',
+    ];
+    flush();
+    const imageContainer =
+        element.shadowRoot!.querySelector<HTMLElement>('.image-container');
+    assertTrue(!!imageContainer);
+    assertFalse(isVisible(imageContainer));
+
+    const firstImage = element.shadowRoot!.querySelector('img');
+    assertTrue(!!firstImage);
+    firstImage.dispatchEvent(new Event('load'));
+    flush();
+    assertTrue(isVisible(imageContainer));
+
+    // Changing imageUrls should reset the load logic
+    element.imageUrls = [
+      'http://www.image2.png',
+    ];
+    flush();
+    assertFalse(isVisible(imageContainer));
+
+    firstImage.dispatchEvent(new Event('load'));
+    flush();
+    assertTrue(isVisible(imageContainer));
+  });
 });
diff --git a/chrome/test/data/webui/css/color_provider_css_colors_test.ts b/chrome/test/data/webui/css/color_provider_css_colors_test.ts
index 4ac7d77..be5103bdf 100644
--- a/chrome/test/data/webui/css/color_provider_css_colors_test.ts
+++ b/chrome/test/data/webui/css/color_provider_css_colors_test.ts
@@ -29,6 +29,8 @@
               '',
               style.getPropertyValue(
                   '--color-app-menu-highlight-severity-low'));
+          // Check that rgb vars are not generated.
+          assertEquals('', style.getPropertyValue('--color-accent-rgb'));
           done();
         };
         link.onerror = function(e) {
@@ -46,10 +48,52 @@
       assertEquals(
           '',
           style.getPropertyValue('--color-app-menu-highlight-severity-low'));
+      // Check that rgb vars are not generated.
+      assertEquals('', style.getPropertyValue('--color-accent-rgb'));
       done();
     };
     link.onerror = function(e) {
       done(new Error('Error loading colors.css' + e));
     };
   });
+
+  test('test fetching color set with generate_rgb_vars=true', function(done) {
+    link.href = 'chrome://theme/colors.css?sets=ui&generate_rgb_vars=true';
+    link.onload = function() {
+      const style = getComputedStyle(document.body);
+      assertNotEquals('', style.getPropertyValue('--color-accent-rgb'));
+      done();
+    };
+    link.onerror = function(e) {
+      done(new Error('Error loading colors.css' + e));
+    };
+  });
+
+  test('test fetching color set with generate_rgb_vars=false', function(done) {
+    link.href = 'chrome://theme/colors.css?sets=ui&generate_rgb_vars=false';
+    link.onload = function() {
+      const style = getComputedStyle(document.body);
+      assertEquals('', style.getPropertyValue('--color-accent-rgb'));
+      done();
+    };
+    link.onerror = function(e) {
+      done(new Error('Error loading colors.css' + e));
+    };
+  });
+
+  test(
+      'test fetching color set with invalid generate_rgb_vars value',
+      function(done) {
+        link.href = 'chrome://theme/colors.css?sets=ui&generate_rgb_vars=asdf';
+        link.onload = function() {
+          const style = getComputedStyle(document.body);
+          // generate_rgb_vars when not provided with a explicitly truthy value
+          // should default to false.
+          assertEquals('', style.getPropertyValue('--color-accent-rgb'));
+          done();
+        };
+        link.onerror = function(e) {
+          done(new Error('Error loading colors.css' + e));
+        };
+      });
 });
diff --git a/chrome/test/data/webui/password_manager/add_password_dialog_test.ts b/chrome/test/data/webui/password_manager/add_password_dialog_test.ts
index 279c03e..e02e08d 100644
--- a/chrome/test/data/webui/password_manager/add_password_dialog_test.ts
+++ b/chrome/test/data/webui/password_manager/add_password_dialog_test.ts
@@ -330,4 +330,32 @@
     assertEquals(dialog.$.noteInput.value, params.note);
     assertEquals(false, params.useAccountStore);
   });
+
+  test('error when leaving website blank', async function() {
+    const dialog = document.createElement('add-password-dialog');
+    document.body.appendChild(dialog);
+    await flushTasks();
+
+    assertFalse(dialog.$.websiteInput.invalid);
+
+    dialog.$.websiteInput.dispatchEvent(new CustomEvent('blur'));
+    await flushTasks();
+
+    assertTrue(dialog.$.websiteInput.invalid);
+    assertEquals(
+        dialog.i18n('notValidWebsite'), dialog.$.websiteInput.errorMessage);
+  });
+
+  test('error when leaving password blank', async function() {
+    const dialog = document.createElement('add-password-dialog');
+    document.body.appendChild(dialog);
+    await flushTasks();
+
+    assertFalse(dialog.$.passwordInput.invalid);
+
+    dialog.$.passwordInput.dispatchEvent(new CustomEvent('blur'));
+    await flushTasks();
+
+    assertTrue(dialog.$.passwordInput.invalid);
+  });
 });
diff --git a/chrome/test/data/webui/password_manager/password_details_card_test.ts b/chrome/test/data/webui/password_manager/password_details_card_test.ts
index e5f27483..361af336 100644
--- a/chrome/test/data/webui/password_manager/password_details_card_test.ts
+++ b/chrome/test/data/webui/password_manager/password_details_card_test.ts
@@ -349,4 +349,72 @@
 
     assertTrue(deleteDialog.$.removeButton.disabled);
   });
+
+  test('Sites title', async function() {
+    const password = createPasswordEntry(
+        {url: 'test.com', username: 'vik', password: 'password69'});
+    password.affiliatedDomains = [
+      {
+        name: 'test.com',
+        url: 'https://test.com',
+        signonRealm: 'https://test.com/',
+      },
+    ];
+
+    const card = document.createElement('password-details-card');
+    card.password = password;
+    document.body.appendChild(card);
+    await flushTasks();
+
+    assertEquals(
+        card.$.domainLabel.textContent!.trim(),
+        loadTimeData.getString('sitesLabel'));
+  });
+
+  test('Apps title', async function() {
+    const password = createPasswordEntry(
+        {url: 'test.com', username: 'vik', password: 'password69'});
+    password.affiliatedDomains = [
+      {
+        name: 'test.com',
+        url: 'https://test.com',
+        signonRealm: 'android://someHash/',
+      },
+    ];
+
+    const card = document.createElement('password-details-card');
+    card.password = password;
+    document.body.appendChild(card);
+    await flushTasks();
+
+    assertEquals(
+        card.$.domainLabel.textContent!.trim(),
+        loadTimeData.getString('appsLabel'));
+  });
+
+  test('Apps and sites title', async function() {
+    const password = createPasswordEntry(
+        {url: 'test.com', username: 'vik', password: 'password69'});
+    password.affiliatedDomains = [
+      {
+        name: 'test.com',
+        url: 'https://test.com',
+        signonRealm: 'android://someHash/',
+      },
+      {
+        name: 'test.com',
+        url: 'https://test.com',
+        signonRealm: 'https://test.com/',
+      },
+    ];
+
+    const card = document.createElement('password-details-card');
+    card.password = password;
+    document.body.appendChild(card);
+    await flushTasks();
+
+    assertEquals(
+        card.$.domainLabel.textContent!.trim(),
+        loadTimeData.getString('sitesAndAppsLabel'));
+  });
 });
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn
index 49281ba..1ecede3 100644
--- a/chrome/test/data/webui/settings/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -120,8 +120,6 @@
     "os_sync_controls_subpage_test.js",
     "people_page_account_manager_subpage_test.js",
     "per_device_keyboard_subsection_test.js",
-    "per_device_keyboard_remap_keys_test.js",
-    "per_device_pointing_stick_subsection_test.js",
     "personalization_page_with_personalization_hub_test.js",
     "privacy_hub_subpage_tests.js",
     "quick_unlock_authenticate_browsertest_chromeos.js",
@@ -200,9 +198,11 @@
     "date_time_page/timezone_subpage_test.ts",
 
     "device_page/device_page_tests.js",
-    "device_page/per_device_keyboard_test.js",
+    "device_page/per_device_keyboard_remap_keys_test.ts",
+    "device_page/per_device_keyboard_test.ts",
     "device_page/per_device_mouse_subsection_test.ts",
     "device_page/per_device_mouse_test.ts",
+    "device_page/per_device_pointing_stick_subsection_test.ts",
     "device_page/per_device_pointing_stick_test.ts",
     "device_page/per_device_touchpad_subsection_test.ts",
     "device_page/per_device_touchpad_test.ts",
@@ -224,6 +224,7 @@
     "os_bluetooth_page/os_bluetooth_true_wireless_images_tests.js",
     "os_bluetooth_page/test_os_bluetooth_subpage_browser_proxy.ts",
 
+    "os_files_page/google_drive_page_test.ts",
     "os_files_page/office_page_test.ts",
 
     "os_languages_page/smart_inputs_page_test.ts",
diff --git a/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_remap_keys_test.ts b/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_remap_keys_test.ts
new file mode 100644
index 0000000..f60b5576
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_remap_keys_test.ts
@@ -0,0 +1,282 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {CrButtonElement, FakeInputDeviceSettingsProvider, fakeKeyboards, Keyboard, KeyboardRemapModifierKeyRowElement, MetaKey, ModifierKey, Router, routes, setInputDeviceSettingsProviderForTesting, SettingsPerDeviceKeyboardRemapKeysElement} from 'chrome://os-settings/chromeos/os_settings.js';
+import {assert} from 'chrome://resources/js/assert_ts.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
+
+suite('<settings-per-device-keyboard-remap-keys>', () => {
+  let page: SettingsPerDeviceKeyboardRemapKeysElement;
+  let provider: FakeInputDeviceSettingsProvider;
+
+  setup(async () => {
+    provider = new FakeInputDeviceSettingsProvider();
+    provider.setFakeKeyboards(fakeKeyboards);
+    setInputDeviceSettingsProviderForTesting(provider);
+
+    page = document.createElement('settings-per-device-keyboard-remap-keys');
+    page.set('keyboards', fakeKeyboards);
+    assertFalse(page.get('isInitialized'));
+    // Set the current route with keyboardId as search param and notify
+    // the observer to update keyboard settings.
+    const url = new URLSearchParams(
+        'keyboardId=' + encodeURIComponent(fakeKeyboards[0]!.id));
+    await Router.getInstance().setCurrentRoute(
+        routes.PER_DEVICE_KEYBOARD_REMAP_KEYS,
+        /* dynamicParams= */ url, /* removeSearch= */ true);
+
+    document.body.appendChild(page);
+    await flushTasks();
+  });
+
+  teardown(() => {
+    page.remove();
+  });
+
+  /**
+   * Check that all the prefs are set to default keyboard value.
+   */
+  function checkPrefsSetToDefault() {
+    const ctrlDefaultMapping =
+        page.get('keyboard.metaKey') === MetaKey.kCommand ?
+        ModifierKey.kMeta :
+        ModifierKey.kControl;
+    const metaDefaultMapping =
+        page.get('keyboard.metaKey') === MetaKey.kCommand ?
+        ModifierKey.kControl :
+        ModifierKey.kMeta;
+    assertEquals(ModifierKey.kAlt, page.get('fakeAltPref.value'));
+    assertEquals(ModifierKey.kAssistant, page.get('fakeAssistantPref.value'));
+    assertEquals(ModifierKey.kBackspace, page.get('fakeBackspacePref.value'));
+    assertEquals(ModifierKey.kCapsLock, page.get('fakeCapsLockPref.value'));
+    assertEquals(ctrlDefaultMapping, page.get('fakeCtrlPref.value'));
+    assertEquals(ModifierKey.kEscape, page.get('fakeEscPref.value'));
+    assertEquals(metaDefaultMapping, page.get('fakeMetaPref.value'));
+  }
+
+  /**
+   * Verify that the remap subpage is correctly loaded with keyboard data.
+   */
+  test('keyboard remap subpage loaded', async () => {
+    assert(page.get('keyboard'));
+
+    // Verify that the dropdown menu for unremapped key is displayed as default.
+    const altKeyRow =
+        page.shadowRoot!.querySelector<KeyboardRemapModifierKeyRowElement>(
+            '#altKey');
+    assert(altKeyRow);
+    const altKeyDropdown = altKeyRow.shadowRoot!.querySelector('#keyDropdown');
+    assert(altKeyDropdown);
+    assertEquals(
+        ModifierKey.kAlt.toString(),
+        altKeyDropdown.shadowRoot!.querySelector('select')!.value);
+
+    // Verify that the default key icon is not highlighted.
+    assertEquals('default-remapping', altKeyRow.keyState);
+
+    // Verify that the dropdown menu for remapped key is displayed as the
+    // the target key in keyboard remapping settings.
+    const ctrlKeyRow =
+        page.shadowRoot!.querySelector<KeyboardRemapModifierKeyRowElement>(
+            '#ctrlKey');
+    assert(ctrlKeyRow);
+    const ctrlKeyMappedTo =
+        fakeKeyboards[0]!.settings.modifierRemappings[ModifierKey.kControl]!
+            .toString();
+    const ctrlKeyDropdown =
+        ctrlKeyRow.shadowRoot!.querySelector('#keyDropdown');
+    assert(ctrlKeyDropdown);
+    assertEquals(
+        ctrlKeyMappedTo,
+        ctrlKeyDropdown.shadowRoot!.querySelector('select')!.value);
+    // Verify that the remapped key icon is highlighted.
+    assertEquals('modifier-remapped', ctrlKeyRow.keyState);
+
+    // Verify that the label for meta key is displayed as the
+    // the target key in keyboard remapping settings.
+    const metaKeyRow =
+        page.shadowRoot!.querySelector<KeyboardRemapModifierKeyRowElement>(
+            '#metaKey');
+    assert(metaKeyRow);
+    assertEquals('Command', metaKeyRow.get('keyLabel'));
+
+    // Verify that the icon is hidden.
+    const commandKeyIcon = metaKeyRow.shadowRoot!.querySelector('iron-icon');
+    assertEquals(null, commandKeyIcon);
+  });
+
+  /**
+   * Verify that the remap subpage is correctly updated when a different
+   * keyboardId is passed through the query url.
+   */
+  test('keyboard remap subpage updated for different keyboard', async () => {
+    // Update the subpage with a new keyboard.
+    const url = new URLSearchParams(
+        'keyboardId=' + encodeURIComponent(fakeKeyboards[2]!.id));
+    await Router.getInstance().setCurrentRoute(
+        routes.PER_DEVICE_KEYBOARD_REMAP_KEYS,
+        /* dynamicParams= */ url, /* removeSearch= */ true);
+    assert(page.get('keyboard'));
+    await flushTasks();
+
+    // Verify that the dropdown menu for unremapped key in the new
+    // keyboard is updated and displayed as default.
+    const ctrlKeyRow =
+        page.shadowRoot!.querySelector<KeyboardRemapModifierKeyRowElement>(
+            '#ctrlKey');
+    assert(ctrlKeyRow);
+    const ctrlKeyDropdown =
+        ctrlKeyRow.shadowRoot!.querySelector('#keyDropdown');
+    const ctrlKeyMappedTo = ModifierKey.kControl.toString();
+    assert(ctrlKeyDropdown);
+    assertEquals(
+        ctrlKeyMappedTo,
+        ctrlKeyDropdown.shadowRoot!.querySelector('select')!.value);
+    // Verify that the default key icon is not highlighted.
+    assertEquals('default-remapping', ctrlKeyRow.keyState);
+
+    // Verify that the dropdown menu for remapped key is updated and displayed
+    // as the target key in the new keyboard remapping settings.
+    const altKeyRow =
+        page.shadowRoot!.querySelector<KeyboardRemapModifierKeyRowElement>(
+            '#altKey');
+    assert(altKeyRow);
+    const altKeyDropDown = altKeyRow.shadowRoot!.querySelector('#keyDropdown');
+    const altKeyMappedTo =
+        fakeKeyboards[2]!.settings.modifierRemappings[ModifierKey.kAlt]!
+            .toString();
+    assert(altKeyDropDown);
+    assertEquals(
+        altKeyMappedTo,
+        altKeyDropDown.shadowRoot!.querySelector('select')!.value);
+    // Verify that the remapped key icon is highlighted.
+    assertEquals('modifier-remapped', altKeyRow.keyState);
+
+    // Verify that the label for meta key is displayed as the
+    // the target key in the new keyboard remapping settings.
+    const metaKeyRow =
+        page.shadowRoot!.querySelector<KeyboardRemapModifierKeyRowElement>(
+            '#metaKey');
+    assert(metaKeyRow);
+    assertEquals('Launcher', metaKeyRow.get('keyLabel'));
+
+    const launcherKeyIcon = metaKeyRow.shadowRoot!.querySelector('iron-icon');
+    assert(launcherKeyIcon);
+    assertEquals('os-settings:launcher', launcherKeyIcon.icon);
+  });
+
+  /**
+   * Verify that the restore defaults button will restore the remapping keys.
+   */
+  test('keyboard remap subpage restore defaults', async () => {
+    // Click the restore defaults button.
+    const restoreButton = page.shadowRoot!.querySelector<CrButtonElement>(
+        '#restoreDefaultsButton');
+    assert(restoreButton);
+    restoreButton.click();
+    await flushTasks();
+
+    // The keyboard has "Command" as metaKey, so ctrl key should be restored to
+    // meta, meta key should be restored to ctrl.
+    const ctrlKeyRow =
+        page.shadowRoot!.querySelector<KeyboardRemapModifierKeyRowElement>(
+            '#ctrlKey');
+    assert(ctrlKeyRow);
+    const ctrlKeyDropdown =
+        ctrlKeyRow.shadowRoot!.querySelector('#keyDropdown');
+    assert(ctrlKeyDropdown);
+    const metaKeyValue = ModifierKey.kMeta.toString();
+    assertEquals(
+        metaKeyValue,
+        ctrlKeyDropdown.shadowRoot!.querySelector('select')!.value);
+    // Verify that the restored key icon is not highlighted.
+    assertEquals('default-remapping', ctrlKeyRow.keyState);
+
+    const metaKeyRow =
+        page.shadowRoot!.querySelector<KeyboardRemapModifierKeyRowElement>(
+            '#metaKey');
+    assert(metaKeyRow);
+    const metaKeyDropdown =
+        metaKeyRow.shadowRoot!.querySelector('#keyDropdown');
+    assertEquals(
+        ModifierKey.kControl.toString(),
+        metaKeyDropdown!.shadowRoot!.querySelector('select')!.value);
+    // Verify that the restored key icon is not highlighted.
+    assertEquals('default-remapping', metaKeyRow.keyState);
+
+    // Update the subpage with a new keyboard.
+    const url = new URLSearchParams(
+        'keyboardId=' + encodeURIComponent(fakeKeyboards[2]!.id));
+    await Router.getInstance().setCurrentRoute(
+        routes.PER_DEVICE_KEYBOARD_REMAP_KEYS,
+        /* dynamicParams= */ url, /* removeSearch= */ true);
+    assert(page.get('keyboard'));
+    await flushTasks();
+
+    restoreButton.click();
+    await flushTasks();
+    // The keyboard has "Launcher" as metaKey, meta key should be restored to
+    // default metaKey mappings.
+    const altKeyValue = ModifierKey.kAlt.toString();
+    const altKeyRow =
+        page.shadowRoot!.querySelector<KeyboardRemapModifierKeyRowElement>(
+            '#altKey');
+    assert(altKeyRow);
+    const altKeyDropDown = altKeyRow.shadowRoot!.querySelector('#keyDropdown');
+    assert(altKeyDropDown);
+    assertEquals(
+        altKeyValue, altKeyDropDown.shadowRoot!.querySelector('select')!.value);
+    assertEquals(
+        metaKeyValue,
+        metaKeyDropdown!.shadowRoot!.querySelector('select')!.value);
+    // Verify that the restored key icon is not highlighted.
+    assertEquals('default-remapping', metaKeyRow.keyState);
+  });
+
+  /**
+   * Verify that if the keyboard is disconnected while the user is in
+   * the remapping page, it will switch back to per device keyboard page.
+   */
+  test('re-route to back page when keyboard disconnected', async () => {
+    // Check it's currently in the modifier remapping page.
+    assertEquals(
+        routes.PER_DEVICE_KEYBOARD_REMAP_KEYS,
+        Router.getInstance().currentRoute);
+    assertEquals(page.get('keyboardId'), page.get('keyboards')[0].id);
+    const updatedKeyboards = [fakeKeyboards[1], fakeKeyboards[2]] as Keyboard[];
+    page.set('keyboards', updatedKeyboards);
+    assertEquals(routes.PER_DEVICE_KEYBOARD, Router.getInstance().currentRoute);
+  });
+
+  /**
+   * Test that update keyboard settings api is called when keyboard remapping
+   * prefs settings change.
+   */
+  test('Update keyboard settings', async () => {
+    assertTrue(page.get('isInitialized'));
+    // Set the modifier remappings to default stage.
+    const restoreButton = page.shadowRoot!.querySelector<CrButtonElement>(
+        '#restoreDefaultsButton');
+    assert(restoreButton);
+    restoreButton.click();
+    checkPrefsSetToDefault();
+
+    // Change several key remappings in the page.
+    page.set('fakeAltPref.value', ModifierKey.kAssistant);
+    page.set('fakeBackspacePref.value', ModifierKey.kControl);
+    page.set('fakeEscPref.value', ModifierKey.kVoid);
+
+    // Verify that the keyboard settings in the provider are updated.
+    const keyboards = await provider.getConnectedKeyboardSettings();
+    assert(keyboards);
+    const updatedRemapping = keyboards[0]!.settings.modifierRemappings;
+    assert(updatedRemapping);
+    assertEquals(3, Object.keys(updatedRemapping).length);
+    assertEquals(ModifierKey.kAssistant, updatedRemapping[ModifierKey.kAlt]);
+    assertEquals(
+        ModifierKey.kControl, updatedRemapping[ModifierKey.kBackspace]);
+    assertEquals(ModifierKey.kVoid, updatedRemapping[ModifierKey.kEscape]);
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.js b/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.js
deleted file mode 100644
index 9caa308..0000000
--- a/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.js
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
-
-import {DevicePageBrowserProxyImpl, FakeInputDeviceSettingsProvider, fakeKeyboards, fakeKeyboards2, Router, routes, setInputDeviceSettingsProviderForTesting, SettingsPerDeviceKeyboardElement} from 'chrome://os-settings/chromeos/os_settings.js';
-import {assertTrue} from 'chrome://webui-test/chai_assert.js';
-import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
-import {isVisible} from 'chrome://webui-test/test_util.js';
-
-import {TestDevicePageBrowserProxy} from './test_device_page_browser_proxy.js';
-
-function getFakeAutoRepeatPrefs() {
-  return {
-    settings: {
-      language: {
-        xkb_auto_repeat_enabled_r2: {
-          key: 'prefs.settings.language.xkb_auto_repeat_enabled_r2',
-          type: chrome.settingsPrivate.PrefType.BOOLEAN,
-          value: true,
-        },
-        xkb_auto_repeat_delay_r2: {
-          key: 'settings.language.xkb_auto_repeat_delay_r2',
-          type: chrome.settingsPrivate.PrefType.NUMBER,
-          value: 500,
-        },
-        xkb_auto_repeat_interval_r2: {
-          key: 'settings.language.xkb_auto_repeat_interval_r2',
-          type: chrome.settingsPrivate.PrefType.NUMBER,
-          value: 500,
-        },
-      },
-    },
-  };
-}
-
-suite('PerDeviceKeyboard', function() {
-  /**
-   * @type {?SettingsPerDeviceKeyboardElement}
-   */
-  let perDeviceKeyboardPage = null;
-
-  setup(() => {
-    PolymerTest.clearBody();
-  });
-
-  teardown(() => {
-    perDeviceKeyboardPage = null;
-    Router.getInstance().resetRouteForTesting();
-  });
-
-  function initializePerDeviceKeyboardPage(keyboards = fakeKeyboards) {
-    DevicePageBrowserProxyImpl.setInstanceForTesting(
-        new TestDevicePageBrowserProxy());
-    perDeviceKeyboardPage =
-        document.createElement('settings-per-device-keyboard');
-    perDeviceKeyboardPage.prefs = getFakeAutoRepeatPrefs();
-    assertTrue(perDeviceKeyboardPage != null);
-    perDeviceKeyboardPage.keyboards = keyboards;
-    document.body.appendChild(perDeviceKeyboardPage);
-    return flushTasks();
-  }
-
-  test('Keyboard page updates with new keyboards', async () => {
-    await initializePerDeviceKeyboardPage();
-    let subsections = perDeviceKeyboardPage.shadowRoot.querySelectorAll(
-        'settings-per-device-keyboard-subsection');
-    assertEquals(fakeKeyboards.length, subsections.length);
-
-    // Check the number of subsections when the keyboard list is updated.
-    perDeviceKeyboardPage.keyboards = fakeKeyboards2;
-    await flushTasks();
-    subsections = perDeviceKeyboardPage.shadowRoot.querySelectorAll(
-        'settings-per-device-keyboard-subsection');
-    assertEquals(fakeKeyboards2.length, subsections.length);
-  });
-
-  test(
-      'Display correct name used for internal/external keyboards', async () => {
-        await initializePerDeviceKeyboardPage();
-        const subsections = perDeviceKeyboardPage.shadowRoot.querySelectorAll(
-            'settings-per-device-keyboard-subsection');
-        for (let i = 0; i < subsections.length; i++) {
-          const name =
-              subsections[i].shadowRoot.querySelector('h2').textContent;
-          if (fakeKeyboards[i].isExternal) {
-            assertEquals(fakeKeyboards[i].name, name);
-          } else {
-            assertTrue(subsections[i].i18nExists('builtInKeyboardName'));
-            assertEquals('Built-in Keyboard', name);
-          }
-        }
-      });
-
-  test('Auto repeat toggle and slides', async () => {
-    await initializePerDeviceKeyboardPage();
-
-    const collapse =
-        perDeviceKeyboardPage.shadowRoot.querySelector('iron-collapse');
-    assertTrue(!!collapse);
-    assertTrue(collapse.opened);
-
-    assertEquals(
-        500,
-        perDeviceKeyboardPage.shadowRoot.querySelector('#delaySlider')
-            .pref.value);
-    assertEquals(
-        500,
-        perDeviceKeyboardPage.shadowRoot.querySelector('#repeatRateSlider')
-            .pref.value);
-
-    // Test interaction with the settings-slider's underlying cr-slider.
-    MockInteractions.pressAndReleaseKeyOn(
-        perDeviceKeyboardPage.shadowRoot.querySelector('#delaySlider')
-            .shadowRoot.querySelector('cr-slider'),
-        37 /* left */, [], 'ArrowLeft');
-    MockInteractions.pressAndReleaseKeyOn(
-        perDeviceKeyboardPage.shadowRoot.querySelector('#repeatRateSlider')
-            .shadowRoot.querySelector('cr-slider'),
-        39, [], 'ArrowRight');
-    await flushTasks();
-    assertEquals(
-        1000,
-        perDeviceKeyboardPage.get(
-            'prefs.settings.language.xkb_auto_repeat_delay_r2.value'));
-    assertEquals(
-        300,
-        perDeviceKeyboardPage.get(
-            'prefs.settings.language.xkb_auto_repeat_interval_r2.value'));
-
-    // Test sliders change when prefs change.
-    perDeviceKeyboardPage.set(
-        'prefs.settings.language.xkb_auto_repeat_delay_r2.value', 1500);
-    await flushTasks();
-    assertEquals(
-        1500,
-        perDeviceKeyboardPage.shadowRoot.querySelector('#delaySlider')
-            .pref.value);
-    perDeviceKeyboardPage.set(
-        'prefs.settings.language.xkb_auto_repeat_interval_r2.value', 2000);
-    await flushTasks();
-    assertEquals(
-        2000,
-        perDeviceKeyboardPage.shadowRoot.querySelector('#repeatRateSlider')
-            .pref.value);
-
-    // Test sliders round to nearest value when prefs change.
-    perDeviceKeyboardPage.set(
-        'prefs.settings.language.xkb_auto_repeat_delay_r2.value', 600);
-    await flushTasks();
-    assertEquals(
-        500,
-        perDeviceKeyboardPage.shadowRoot.querySelector('#delaySlider')
-            .pref.value);
-    perDeviceKeyboardPage.set(
-        'prefs.settings.language.xkb_auto_repeat_interval_r2.value', 45);
-    await flushTasks();
-    assertEquals(
-        50,
-        perDeviceKeyboardPage.shadowRoot.querySelector('#repeatRateSlider')
-            .pref.value);
-
-    perDeviceKeyboardPage.set(
-        'prefs.settings.language.xkb_auto_repeat_enabled_r2.value', false);
-    assertFalse(collapse.opened);
-  });
-
-  test('Open keyboard shortcut viewer', async () => {
-    await initializePerDeviceKeyboardPage();
-    perDeviceKeyboardPage.shadowRoot.querySelector('#keyboardShortcutViewer')
-        .click();
-    assertEquals(
-        1,
-        DevicePageBrowserProxyImpl.getInstance().getCallCount(
-            'showKeyboardShortcutViewer'));
-  });
-
-  test('Navigate to input tab', async () => {
-    await initializePerDeviceKeyboardPage();
-    perDeviceKeyboardPage.shadowRoot.querySelector('#showLanguagesInput')
-        .click();
-    assertEquals(routes.OS_LANGUAGES_INPUT, Router.getInstance().currentRoute);
-  });
-
-  test('Help message shown when no keyboards are connected', async () => {
-    await initializePerDeviceKeyboardPage();
-    perDeviceKeyboardPage.keyboards = [];
-    await flushTasks();
-    assertTrue(isVisible(perDeviceKeyboardPage.shadowRoot.querySelector(
-        '#noKeyboardsConnectedContainer')));
-    assertEquals(
-        'No keyboard detected',
-        perDeviceKeyboardPage.shadowRoot
-            .querySelector('#noKeyboardsConnectedMessage')
-            .innerText.trim());
-  });
-});
diff --git a/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.ts b/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.ts
new file mode 100644
index 0000000..a9f71308
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.ts
@@ -0,0 +1,187 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {DevicePageBrowserProxyImpl, fakeKeyboards, fakeKeyboards2, Router, routes, SettingsPerDeviceKeyboardElement, SettingsSliderElement} from 'chrome://os-settings/chromeos/os_settings.js';
+import {CrLinkRowElement} from 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
+import {assert} from 'chrome://resources/js/assert_ts.js';
+import {pressAndReleaseKeyOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
+import {isVisible} from 'chrome://webui-test/test_util.js';
+
+import {TestDevicePageBrowserProxy} from './test_device_page_browser_proxy.js';
+
+suite('<settings-per-device-keyboard>', () => {
+  let perDeviceKeyboardPage: SettingsPerDeviceKeyboardElement;
+  let devicePageBrowserProxy: TestDevicePageBrowserProxy;
+
+  function getFakeAutoRepeatPrefs() {
+    return {
+      settings: {
+        language: {
+          xkb_auto_repeat_enabled_r2: {
+            key: 'prefs.settings.language.xkb_auto_repeat_enabled_r2',
+            type: chrome.settingsPrivate.PrefType.BOOLEAN,
+            value: true,
+          },
+          xkb_auto_repeat_delay_r2: {
+            key: 'settings.language.xkb_auto_repeat_delay_r2',
+            type: chrome.settingsPrivate.PrefType.NUMBER,
+            value: 500,
+          },
+          xkb_auto_repeat_interval_r2: {
+            key: 'settings.language.xkb_auto_repeat_interval_r2',
+            type: chrome.settingsPrivate.PrefType.NUMBER,
+            value: 500,
+          },
+        },
+      },
+    };
+  }
+
+  setup(async () => {
+    devicePageBrowserProxy = new TestDevicePageBrowserProxy();
+    DevicePageBrowserProxyImpl.setInstanceForTesting(devicePageBrowserProxy);
+    perDeviceKeyboardPage =
+        document.createElement('settings-per-device-keyboard');
+    assert(perDeviceKeyboardPage);
+    perDeviceKeyboardPage.set('prefs', getFakeAutoRepeatPrefs());
+    perDeviceKeyboardPage.set('keyboards', fakeKeyboards);
+    document.body.appendChild(perDeviceKeyboardPage);
+    await flushTasks();
+  });
+
+  teardown(() => {
+    perDeviceKeyboardPage.remove();
+    Router.getInstance().resetRouteForTesting();
+  });
+
+  test('Keyboard page updates with new keyboards', async () => {
+    let subsections = perDeviceKeyboardPage.shadowRoot!.querySelectorAll(
+        'settings-per-device-keyboard-subsection');
+    assertEquals(fakeKeyboards.length, subsections.length);
+
+    // Check the number of subsections when the keyboard list is updated.
+    perDeviceKeyboardPage.set('keyboards', fakeKeyboards2);
+    await flushTasks();
+    subsections = perDeviceKeyboardPage.shadowRoot!.querySelectorAll(
+        'settings-per-device-keyboard-subsection');
+    assertEquals(fakeKeyboards2.length, subsections.length);
+  });
+
+  test(
+      'Display correct name used for internal/external keyboards', async () => {
+        const subsections = perDeviceKeyboardPage.shadowRoot!.querySelectorAll(
+            'settings-per-device-keyboard-subsection');
+        for (let i = 0; i < subsections.length; i++) {
+          const name =
+              subsections[i]!.shadowRoot!.querySelector('h2')!.textContent;
+          if (fakeKeyboards[i]!.isExternal) {
+            assertEquals(fakeKeyboards[i]!.name, name);
+          } else {
+            assertTrue(subsections[i]!.i18nExists('builtInKeyboardName'));
+            assertEquals('Built-in Keyboard', name);
+          }
+        }
+      });
+
+  test('Auto repeat toggle and slides', async () => {
+    const collapse =
+        perDeviceKeyboardPage.shadowRoot!.querySelector('iron-collapse');
+    assert(collapse);
+    assertTrue(collapse.opened);
+
+    assertEquals(
+        500,
+        perDeviceKeyboardPage.shadowRoot!
+            .querySelector<SettingsSliderElement>('#delaySlider')!.pref!.value);
+    assertEquals(
+        500,
+        perDeviceKeyboardPage.shadowRoot!
+            .querySelector<SettingsSliderElement>(
+                '#repeatRateSlider')!.pref!.value);
+
+    // Test interaction with the settings-slider's underlying cr-slider.
+    pressAndReleaseKeyOn(
+        perDeviceKeyboardPage.shadowRoot!.querySelector('#delaySlider')!
+            .shadowRoot!.querySelector('cr-slider')!,
+        37, [], 'ArrowLeft');
+    pressAndReleaseKeyOn(
+        perDeviceKeyboardPage.shadowRoot!.querySelector('#repeatRateSlider')!
+            .shadowRoot!.querySelector('cr-slider')!,
+        39, [], 'ArrowRight');
+    await flushTasks();
+    assertEquals(
+        1000,
+        perDeviceKeyboardPage.get(
+            'prefs.settings.language.xkb_auto_repeat_delay_r2.value'));
+    assertEquals(
+        300,
+        perDeviceKeyboardPage.get(
+            'prefs.settings.language.xkb_auto_repeat_interval_r2.value'));
+
+    // Test sliders change when prefs change.
+    perDeviceKeyboardPage.set(
+        'prefs.settings.language.xkb_auto_repeat_delay_r2.value', 1500);
+    await flushTasks();
+    assertEquals(
+        1500,
+        perDeviceKeyboardPage.shadowRoot!
+            .querySelector<SettingsSliderElement>('#delaySlider')!.pref!.value);
+    perDeviceKeyboardPage.set(
+        'prefs.settings.language.xkb_auto_repeat_interval_r2.value', 2000);
+    await flushTasks();
+    assertEquals(
+        2000,
+        perDeviceKeyboardPage.shadowRoot!
+            .querySelector<SettingsSliderElement>(
+                '#repeatRateSlider')!.pref!.value);
+
+    // Test sliders round to nearest value when prefs change.
+    perDeviceKeyboardPage.set(
+        'prefs.settings.language.xkb_auto_repeat_delay_r2.value', 600);
+    await flushTasks();
+    assertEquals(
+        500,
+        perDeviceKeyboardPage.shadowRoot!
+            .querySelector<SettingsSliderElement>('#delaySlider')!.pref!.value);
+    perDeviceKeyboardPage.set(
+        'prefs.settings.language.xkb_auto_repeat_interval_r2.value', 45);
+    await flushTasks();
+    assertEquals(
+        50,
+        perDeviceKeyboardPage.shadowRoot!
+            .querySelector<SettingsSliderElement>(
+                '#repeatRateSlider')!.pref!.value);
+
+    perDeviceKeyboardPage.set(
+        'prefs.settings.language.xkb_auto_repeat_enabled_r2.value', false);
+    assertFalse(collapse.opened);
+  });
+
+  test('Open keyboard shortcut viewer', async () => {
+    perDeviceKeyboardPage.shadowRoot!
+        .querySelector<CrLinkRowElement>('#keyboardShortcutViewer')!.click();
+    assertEquals(
+        1, devicePageBrowserProxy.getCallCount('showKeyboardShortcutViewer'));
+  });
+
+  test('Navigate to input tab', async () => {
+    perDeviceKeyboardPage.shadowRoot!
+        .querySelector<CrLinkRowElement>('#showLanguagesInput')!.click();
+    assertEquals(routes.OS_LANGUAGES_INPUT, Router.getInstance().currentRoute);
+  });
+
+  test('Help message shown when no keyboards are connected', async () => {
+    perDeviceKeyboardPage.set('keyboards', []);
+    await flushTasks();
+    assertTrue(isVisible(perDeviceKeyboardPage.shadowRoot!.querySelector(
+        '#noKeyboardsConnectedContainer')));
+    assertEquals(
+        'No keyboard detected',
+        perDeviceKeyboardPage.shadowRoot!
+            .querySelector<HTMLElement>(
+                '#noKeyboardsConnectedMessage')!.innerText.trim());
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/device_page/per_device_pointing_stick_subsection_test.ts b/chrome/test/data/webui/settings/chromeos/device_page/per_device_pointing_stick_subsection_test.ts
new file mode 100644
index 0000000..2ab4c29f
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/device_page/per_device_pointing_stick_subsection_test.ts
@@ -0,0 +1,166 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {FakeInputDeviceSettingsProvider, fakePointingSticks, Router, routes, setInputDeviceSettingsProviderForTesting, SettingsDropdownMenuElement, SettingsPerDevicePointingStickSubsectionElement, SettingsSliderElement, SettingsToggleButtonElement} from 'chrome://os-settings/chromeos/os_settings.js';
+import {assert} from 'chrome://resources/js/assert_ts.js';
+import {pressAndReleaseKeyOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
+import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
+
+const POINTING_STICK_SPEED_SETTING_ID = 435;
+
+suite('<settings-per-device-pointing-stick-subsection>', () => {
+  let subsection: SettingsPerDevicePointingStickSubsectionElement;
+  let provider: FakeInputDeviceSettingsProvider;
+
+  setup(async () => {
+    provider = new FakeInputDeviceSettingsProvider();
+    provider.setFakePointingSticks(fakePointingSticks);
+    setInputDeviceSettingsProviderForTesting(provider);
+    subsection =
+        document.createElement('settings-per-device-pointing-stick-subsection');
+    assert(subsection);
+    subsection.set('pointingStick', {...fakePointingSticks[0]});
+    document.body.appendChild(subsection);
+    await flushTasks();
+  });
+
+  teardown(() => {
+    subsection.remove();
+  });
+
+  /**
+   * Test that API are updated when pointing stick settings change.
+   */
+  test('Update API when pointing stick settings change', async () => {
+    const pointingStickSwapButtonDropdown =
+        subsection.shadowRoot!.querySelector<SettingsDropdownMenuElement>(
+            '#pointingStickSwapButtonDropdown');
+    assert(pointingStickSwapButtonDropdown);
+    pointingStickSwapButtonDropdown.set('pref.value', true);
+
+    await flushTasks();
+    let updatedPointingSticks =
+        await provider.getConnectedPointingStickSettings();
+    assertEquals(
+        updatedPointingSticks[0]!.settings.swapRight,
+        pointingStickSwapButtonDropdown.pref!.value);
+
+    const pointingStickAccelerationToggleButton =
+        subsection.shadowRoot!.querySelector<SettingsToggleButtonElement>(
+            '#pointingStickAcceleration');
+    pointingStickAccelerationToggleButton!.click();
+    await flushTasks();
+    updatedPointingSticks = await provider.getConnectedPointingStickSettings();
+    assertEquals(
+        updatedPointingSticks[0]!.settings.accelerationEnabled,
+        pointingStickAccelerationToggleButton!.pref!.value);
+
+    const pointingStickSpeedSlider =
+        subsection.shadowRoot!.querySelector<SettingsSliderElement>(
+            '#pointingStickSpeedSlider');
+    assert(pointingStickSpeedSlider);
+    pressAndReleaseKeyOn(
+        pointingStickSpeedSlider.shadowRoot!.querySelector('cr-slider')!, 39,
+        [], 'ArrowRight');
+    await flushTasks();
+    updatedPointingSticks = await provider.getConnectedPointingStickSettings();
+    assertEquals(
+        updatedPointingSticks[0]!.settings.sensitivity,
+        pointingStickSpeedSlider.pref!.value);
+  });
+
+  /**
+   * Test that pointing stick settings data are from the pointing stick
+   * provider.
+   */
+  test('Verify pointing stick settings data', async () => {
+    let pointingStickSwapButtonDropdown =
+        subsection.shadowRoot!.querySelector<SettingsDropdownMenuElement>(
+            '#pointingStickSwapButtonDropdown');
+    assertEquals(
+        fakePointingSticks[0]!.settings.swapRight,
+        pointingStickSwapButtonDropdown!.pref!.value);
+    let pointingStickAccelerationToggleButton =
+        subsection.shadowRoot!.querySelector<SettingsToggleButtonElement>(
+            '#pointingStickAcceleration');
+    assertEquals(
+        fakePointingSticks[0]!.settings.accelerationEnabled,
+        pointingStickAccelerationToggleButton!.pref!.value);
+    let pointingStickSpeedSlider =
+        subsection.shadowRoot!.querySelector<SettingsSliderElement>(
+            '#pointingStickSpeedSlider');
+    assert(pointingStickSpeedSlider);
+    assertEquals(
+        fakePointingSticks[0]!.settings.sensitivity,
+        pointingStickSpeedSlider.pref.value);
+
+    subsection.set('pointingStick', fakePointingSticks[1]);
+    await flushTasks();
+    pointingStickSwapButtonDropdown = subsection.shadowRoot!.querySelector(
+        '#pointingStickSwapButtonDropdown');
+    assertEquals(
+        fakePointingSticks[1]!.settings.swapRight,
+        pointingStickSwapButtonDropdown!.pref!.value);
+    pointingStickAccelerationToggleButton =
+        subsection.shadowRoot!.querySelector('#pointingStickAcceleration');
+    assertEquals(
+        fakePointingSticks[1]!.settings.accelerationEnabled,
+        pointingStickAccelerationToggleButton!.pref!.value);
+    pointingStickSpeedSlider =
+        subsection.shadowRoot!.querySelector('#pointingStickSpeedSlider');
+    assert(pointingStickSpeedSlider);
+    assertEquals(
+        fakePointingSticks[1]!.settings.sensitivity,
+        pointingStickSpeedSlider.pref.value);
+  });
+
+  /**
+   * Verify entering the page with search tags matched will auto focus the
+   * searched element.
+   */
+  test('deep linking mixin focus on the first searched element', async () => {
+    const pointingStickSpeedSlider =
+        subsection.shadowRoot!.querySelector<SettingsSliderElement>(
+            '#pointingStickSpeedSlider');
+    subsection.set('pointingStickIndex', 0);
+    // Enter the page from auto repeat search tag.
+    const url = new URLSearchParams(
+        'search=trackpoint+speed&settingId=' +
+        encodeURIComponent(POINTING_STICK_SPEED_SETTING_ID));
+
+    await Router.getInstance().navigateTo(
+        routes.PER_DEVICE_POINTING_STICK,
+        /* dynamicParams= */ url, /* removeSearch= */ true);
+
+    assert(pointingStickSpeedSlider);
+    await waitAfterNextRender(pointingStickSpeedSlider);
+    assertEquals(
+        pointingStickSpeedSlider, subsection.shadowRoot!.activeElement);
+  });
+
+  /**
+   * Verify entering the page with search tags matched wll not auto focus the
+   * searched element if it's not the first keyboard displayed.
+   */
+  test('deep linkng mixin does not focus on second element', async () => {
+    const pointingStickSpeedSlider =
+        subsection.shadowRoot!.querySelector<SettingsSliderElement>(
+            '#pointingStickSpeedSlider');
+    subsection.set('pointingStickIndex', 1);
+    // Enter the page from auto repeat search tag.
+    const url = new URLSearchParams(
+        'search=trackpoint+speed&settingId=' +
+        encodeURIComponent(POINTING_STICK_SPEED_SETTING_ID));
+
+    await Router.getInstance().navigateTo(
+        routes.PER_DEVICE_POINTING_STICK,
+        /* dynamicParams= */ url, /* removeSearch= */ true);
+    await flushTasks();
+
+    assert(pointingStickSpeedSlider);
+    await waitAfterNextRender(pointingStickSpeedSlider);
+    assertEquals(null, subsection.shadowRoot!.activeElement);
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js b/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js
index 6c25ca25..3d7b772f 100644
--- a/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js
@@ -544,6 +544,37 @@
     await checkHasEndOfLife(false);
   });
 
+  test('DeviceEndOfLifeIncentive', async () => {
+    async function checkEndOfLifeIncentive(isShowing) {
+      await aboutBrowserProxy.whenCalled('getEndOfLifeInfo');
+      const eolSection = page.shadowRoot.querySelector('eol-offer-section');
+      assertEquals(isShowing, !!eolSection);
+
+      if (isShowing) {
+        eolSection.$.eolIncentiveButton.click();
+        await aboutBrowserProxy.whenCalled('endOfLifeIncentiveButtonClicked');
+      }
+    }
+
+    aboutBrowserProxy.setEndOfLifeInfo({
+      hasEndOfLife: false,
+      endOfLifeAboutMessage: '',
+      shouldShowEndOfLifeIncentive: false,
+      shouldShowOfferText: false,
+    });
+    await initNewPage();
+    await checkEndOfLifeIncentive(false);
+
+    aboutBrowserProxy.setEndOfLifeInfo({
+      hasEndOfLife: false,
+      endOfLifeAboutMessage: '',
+      shouldShowEndOfLifeIncentive: true,
+      shouldShowOfferText: false,
+    });
+    await initNewPage();
+    await checkEndOfLifeIncentive(true);
+  });
+
   test('managed detailed build info page', async () => {
     loadTimeData.overrideValues({
       isManaged: true,
diff --git a/chrome/test/data/webui/settings/chromeos/os_files_page/google_drive_page_test.ts b/chrome/test/data/webui/settings/chromeos/os_files_page/google_drive_page_test.ts
new file mode 100644
index 0000000..ba60226
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/os_files_page/google_drive_page_test.ts
@@ -0,0 +1,105 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://os-settings/chromeos/lazy_load.js';
+
+import {SettingsGoogleDriveSubpageElement} from 'chrome://os-settings/chromeos/lazy_load.js';
+import {CrSettingsPrefs, SettingsPrefsElement} from 'chrome://os-settings/chromeos/os_settings.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+
+import {assertAsync, querySelectorShadow} from '../utils.js';
+
+suite('<settings-google-drive-subpage>', function() {
+  let page: SettingsGoogleDriveSubpageElement;
+  let prefElement: SettingsPrefsElement;
+  let connectDisconnectButton: CrButtonElement;
+
+  setup(async function() {
+    prefElement = document.createElement('settings-prefs');
+    document.body.appendChild(prefElement);
+
+    await CrSettingsPrefs.initialized;
+    page = document.createElement('settings-google-drive-subpage');
+    page.prefs = prefElement.prefs;
+    document.body.appendChild(page);
+    flush();
+
+    connectDisconnectButton =
+        querySelectorShadow(
+            page.shadowRoot!, ['#driveConnectDisconnect', 'cr-button']) as
+        CrButtonElement;
+  });
+
+  teardown(function() {
+    page.remove();
+    prefElement.remove();
+  });
+
+  test('drive connect label is updated when pref is changed', function() {
+    // Update the preference and ensure the text has the value "Connect".
+    page.setPrefValue('gdata.disabled', true);
+    flush();
+    assertEquals(connectDisconnectButton!.textContent!.trim(), 'Connect');
+
+    // Update the preference and ensure the text has the value "Disconnect".
+    page.setPrefValue('gdata.disabled', false);
+    flush();
+    assertEquals(connectDisconnectButton!.textContent!.trim(), 'Disconnect');
+  });
+
+  test('confirming drive disconnect updates pref', async function() {
+    page.setPrefValue('gdata.disabled', false);
+    flush();
+
+    connectDisconnectButton.click();
+
+    const getDisconnectConfirmationButton = () => {
+      return querySelectorShadow(
+                 page.shadowRoot!,
+                 [
+                   'settings-disconnect-drive-confirmation-dialog',
+                   '.action-button',
+                 ]) as CrButtonElement |
+          null;
+    };
+
+    // Wait for the disconnect confirmation button to be visible.
+    await assertAsync(() => getDisconnectConfirmationButton() !== null);
+    const disconnectButton = getDisconnectConfirmationButton()!;
+    disconnectButton.click();
+
+    // Ensure after clicking the disconnect button the preference is true
+    // (timeout after 5s).
+    await assertAsync(() => page.getPref('gdata.disabled').value, 5000);
+  });
+
+  test(
+      'cancelling drive disconnect confirmation dialog doesnt update pref',
+      async function() {
+        page.setPrefValue('gdata.disabled', false);
+        flush();
+
+        connectDisconnectButton.click();
+
+        const getCancelConfirmationDialogButton = () => {
+          return querySelectorShadow(
+                     page.shadowRoot!,
+                     [
+                       'settings-disconnect-drive-confirmation-dialog',
+                       '.cancel-button',
+                     ]) as CrButtonElement |
+              null;
+        };
+
+        // Wait for the disconnect confirmation button to be visible.
+        await assertAsync(() => getCancelConfirmationDialogButton() !== null);
+        const cancelButton = getCancelConfirmationDialogButton()!;
+        cancelButton.click();
+
+        // Ensure after cancelling the dialog the preference is unchanged.
+        await assertAsync(() => !page.getPref('gdata.disabled').value, 5000);
+      });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
index 42d6b7bc..05e35da 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -270,6 +270,11 @@
    {enabled: ['ash::features::kInputDeviceSettingsSplit']}
  ],
  [
+   'DevicePagePerDeviceKeyboardRemapKeys',
+   'device_page/per_device_keyboard_remap_keys_test.js',
+   {enabled: ['ash::features::kInputDeviceSettingsSplit']}
+ ],
+ [
    'DevicePagePerDeviceMouse', 'device_page/per_device_mouse_test.js',
    {enabled: ['ash::features::kInputDeviceSettingsSplit']}
  ],
@@ -294,6 +299,11 @@
    {enabled: ['ash::features::kInputDeviceSettingsSplit']}
  ],
  [
+   'DevicePagePerDevicePointingStickSubsection',
+   'device_page/per_device_pointing_stick_subsection_test.js',
+   {enabled: ['ash::features::kInputDeviceSettingsSplit']},
+ ],
+ [
    'DisplayAndMagnificationPage',
    'display_and_magnification_page_tests.js',
  ],
@@ -438,6 +448,7 @@
    'OsClearPersonalizationDataPage',
    'os_clear_personalization_data_page_test.js'
  ],
+ ['OsFilesGoogleDrivePage', 'os_files_page/google_drive_page_test.js'],
  ['OsFilesPageOfficePage', 'os_files_page/office_page_test.js'],
  [
    'OsLanguagesPageSmartInputsPage',
@@ -480,20 +491,11 @@
  ],
  ['PeoplePageQuickUnlock', 'quick_unlock_authenticate_browsertest_chromeos.js'],
  [
-   'PerDeviceKeyboardRemapKeys', 'per_device_keyboard_remap_keys_test.js',
-   {enabled: ['ash::features::kInputDeviceSettingsSplit']}
- ],
- [
    'PerDeviceKeyboardSubsection',
    'per_device_keyboard_subsection_test.js',
    {enabled: ['ash::features::kInputDeviceSettingsSplit']},
  ],
  [
-   'PerDevicePointingStickSubsection',
-   'per_device_pointing_stick_subsection_test.js',
-   {enabled: ['ash::features::kInputDeviceSettingsSplit']}
- ],
- [
    'PersonalizationPageWithPersonalizationHub',
    'personalization_page_with_personalization_hub_test.js',
  ],
diff --git a/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js b/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js
deleted file mode 100644
index a21782c..0000000
--- a/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {FakeInputDeviceSettingsProvider, fakeKeyboards, KeyboardRemapModifierKeyRowElement, MetaKey, ModifierKey, Router, routes, setInputDeviceSettingsProviderForTesting, SettingsPerDeviceKeyboardRemapKeysElement} from 'chrome://os-settings/chromeos/os_settings.js';
-import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
-import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
-
-suite('PerDeviceKeyboardRemapKeys', function() {
-  /**
-   * @type {?SettingsPerDeviceKeyboardRemapKeysElement}
-   */
-  let page = null;
-
-  /**
-   *  @type {?FakeInputDeviceSettingsProvider}
-   */
-  let provider = null;
-  setup(() => {
-    provider = new FakeInputDeviceSettingsProvider();
-    provider.setFakeKeyboards(fakeKeyboards);
-    setInputDeviceSettingsProviderForTesting(provider);
-    PolymerTest.clearBody();
-  });
-
-  teardown(() => {
-    page = null;
-    provider = null;
-  });
-
-  async function initializeRemapKeysPage(keyboards = fakeKeyboards) {
-    page = document.createElement('settings-per-device-keyboard-remap-keys');
-    page.keyboards = keyboards;
-    // Set the current route with keyboardId as search param and notify
-    // the observer to update keyboard settings.
-    const url = new URLSearchParams(
-        'keyboardId=' + encodeURIComponent(keyboards[0].id));
-    await Router.getInstance().setCurrentRoute(
-        routes.PER_DEVICE_KEYBOARD_REMAP_KEYS,
-        /* dynamicParams= */ url, /* removeSearch= */ true);
-
-    document.body.appendChild(page);
-    assertTrue(page != null);
-    return flushTasks();
-  }
-
-  async function setKeyboards(keyboards) {
-    page.keyboards = keyboards;
-    return flushTasks();
-  }
-
-  /**
-   * Check that all the prefs are set to default keyboard value.
-   */
-  function checkPrefsSetToDefault() {
-    const ctrlDefaultMapping = page.keyboard.metaKey === MetaKey.kCommand ?
-        ModifierKey.kMeta :
-        ModifierKey.kControl;
-    const metaDefaultMapping = page.keyboard.metaKey === MetaKey.kCommand ?
-        ModifierKey.kControl :
-        ModifierKey.kMeta;
-    assertEquals(page.fakeAltPref.value, ModifierKey.kAlt);
-    assertEquals(page.fakeAssistantPref.value, ModifierKey.kAssistant);
-    assertEquals(page.fakeBackspacePref.value, ModifierKey.kBackspace);
-    assertEquals(page.fakeCapsLockPref.value, ModifierKey.kCapsLock);
-    assertEquals(page.fakeCtrlPref.value, ctrlDefaultMapping);
-    assertEquals(page.fakeEscPref.value, ModifierKey.kEscape);
-    assertEquals(page.fakeMetaPref.value, metaDefaultMapping);
-  }
-
-  /**
-   * Verify that the remap subpage is correctly loaded with keyboard data.
-   */
-  test('keyboard remap subpage loaded', async () => {
-    await initializeRemapKeysPage();
-    assertTrue(!!page.keyboard);
-
-    // Verify that the dropdown menu for unremapped key is displayed as default.
-    /**  @type {?KeyboardRemapModifierKeyRowElement} */
-    const altKeyRow = page.shadowRoot.querySelector('#altKey');
-    const altKeyDropdown = altKeyRow.shadowRoot.querySelector('#keyDropdown');
-    const altKeyMappedTo = ModifierKey.kAlt.toString();
-    assertTrue(!!altKeyDropdown);
-    assertEquals(
-        altKeyDropdown.shadowRoot.querySelector('select').value,
-        altKeyMappedTo);
-
-    // Verify that the default key icon is not highlighted.
-    assertEquals(altKeyRow.keyState, 'default-remapping');
-
-    // Verify that the dropdown menu for remapped key is displayed as the
-    // the target key in keyboard remapping settings.
-    /**  @type {?KeyboardRemapModifierKeyRowElement} */
-    const ctrlKeyRow = page.shadowRoot.querySelector('#ctrlKey');
-    const ctrlKeyMappedTo =
-        fakeKeyboards[0]
-            .settings.modifierRemappings[ModifierKey.kControl]
-            .toString();
-    const ctrlKeyDropdown = ctrlKeyRow.shadowRoot.querySelector('#keyDropdown');
-    assertTrue(!!ctrlKeyDropdown);
-    assertEquals(
-        ctrlKeyDropdown.shadowRoot.querySelector('select').value,
-        ctrlKeyMappedTo);
-    // Verify that the remapped key icon is highlighted.
-    assertEquals(ctrlKeyRow.keyState, 'modifier-remapped');
-
-    // Verify that the label for meta key is displayed as the
-    // the target key in keyboard remapping settings.
-    /**  @type {?KeyboardRemapModifierKeyRowElement} */
-    const metaKeyRow = page.shadowRoot.querySelector('#metaKey');
-    assertTrue(!!metaKeyRow);
-    assertEquals(metaKeyRow.keyLabel, 'Command');
-
-    // Verify that the icon is hidden.
-    const commandKeyIcon = metaKeyRow.shadowRoot.querySelector('iron-icon');
-    assertFalse(!!commandKeyIcon);
-  });
-
-  /**
-   * Verify that the remap subpage is correctly updated when a different
-   * keyboardId is passed through the query url.
-   */
-  test('keyboard remap subpage updated for different keyboard', async () => {
-    await initializeRemapKeysPage();
-
-    // Update the subpage with a new keyboard.
-    const url = new URLSearchParams(
-        'keyboardId=' + encodeURIComponent(fakeKeyboards[2].id));
-    await Router.getInstance().setCurrentRoute(
-        routes.PER_DEVICE_KEYBOARD_REMAP_KEYS,
-        /* dynamicParams= */ url, /* removeSearch= */ true);
-    assertTrue(!!page.keyboard);
-    await flushTasks();
-
-    // Verify that the dropdown menu for unremapped key in the new
-    // keyboard is updated and displayed as default.
-    /**  @type {?KeyboardRemapModifierKeyRowElement} */
-    const ctrlKeyRow = page.shadowRoot.querySelector('#ctrlKey');
-    const ctrlKeyDropdown = ctrlKeyRow.shadowRoot.querySelector('#keyDropdown');
-    const ctrlKeyMappedTo = ModifierKey.kControl.toString();
-    assertTrue(!!ctrlKeyDropdown);
-    assertEquals(
-        ctrlKeyDropdown.shadowRoot.querySelector('select').value,
-        ctrlKeyMappedTo);
-    // Verify that the default key icon is not highlighted.
-    assertEquals(ctrlKeyRow.keyState, 'default-remapping');
-
-    // Verify that the dropdown menu for remapped key is updated and displayed
-    // as the target key in the new keyboard remapping settings.
-    const altKeyRow = page.shadowRoot.querySelector('#altKey');
-    const altKeyDropDown = altKeyRow.shadowRoot.querySelector('#keyDropdown');
-    const altKeyMappedTo = fakeKeyboards[2]
-                               .settings.modifierRemappings[ModifierKey.kAlt]
-                               .toString();
-    assertTrue(!!altKeyDropDown);
-    assertEquals(
-        altKeyDropDown.shadowRoot.querySelector('select').value,
-        altKeyMappedTo);
-    // Verify that the remapped key icon is highlighted.
-    assertEquals(altKeyRow.keyState, 'modifier-remapped');
-
-    // Verify that the label for meta key is displayed as the
-    // the target key in the new keyboard remapping settings.
-    /**  @type {?KeyboardRemapModifierKeyRowElement} */
-    const metaKeyRow = page.shadowRoot.querySelector('#metaKey');
-    assertTrue(!!metaKeyRow);
-    assertEquals(metaKeyRow.keyLabel, 'Launcher');
-
-    const launcherKeyIcon = metaKeyRow.shadowRoot.querySelector('iron-icon');
-    assertTrue(!!launcherKeyIcon);
-    assertEquals('os-settings:launcher', launcherKeyIcon.icon);
-  });
-
-  /**
-   * Verify that the restore defaults button will restore the remapping keys.
-   */
-  test('keyboard remap subpage restore defaults', async () => {
-    await initializeRemapKeysPage();
-
-    // Click the restore defaults button.
-    const restoreButton =
-        page.shadowRoot.querySelector('#restoreDefaultsButton');
-    assertTrue(!!restoreButton);
-    restoreButton.click();
-    await flushTasks();
-
-    // The keyboard has "Command" as metaKey, so ctrl key should be restored to
-    // meta, meta key should be restored to ctrl.
-    /**  @type {?KeyboardRemapModifierKeyRowElement} */
-    const ctrlKeyRow = page.shadowRoot.querySelector('#ctrlKey');
-    const ctrlKeyDropdown = ctrlKeyRow.shadowRoot.querySelector('#keyDropdown');
-    assertTrue(!!ctrlKeyDropdown);
-    const metaKeyValue = ModifierKey.kMeta.toString();
-    assertEquals(
-        ctrlKeyDropdown.shadowRoot.querySelector('select').value, metaKeyValue);
-    // Verify that the restored key icon is not highlighted.
-    assertEquals(ctrlKeyRow.keyState, 'default-remapping');
-
-    const ctrlKeyValue = ModifierKey.kControl.toString();
-    /**  @type {?KeyboardRemapModifierKeyRowElement} */
-    const metaKeyRow = page.shadowRoot.querySelector('#metaKey');
-    const metaKeyDropdown = metaKeyRow.shadowRoot.querySelector('#keyDropdown');
-    assertEquals(
-        metaKeyDropdown.shadowRoot.querySelector('select').value, ctrlKeyValue);
-    // Verify that the restored key icon is not highlighted.
-    assertEquals(metaKeyRow.keyState, 'default-remapping');
-
-    // Update the subpage with a new keyboard.
-    const url = new URLSearchParams(
-        'keyboardId=' + encodeURIComponent(fakeKeyboards[2].id));
-    await Router.getInstance().setCurrentRoute(
-        routes.PER_DEVICE_KEYBOARD_REMAP_KEYS,
-        /* dynamicParams= */ url, /* removeSearch= */ true);
-    assertTrue(!!page.keyboard);
-    await flushTasks();
-
-    restoreButton.click();
-    await flushTasks();
-    // The keyboard has "Launcher" as metaKey, meta key should be restored to
-    // default metaKey mappings.
-    const altKeyValue = ModifierKey.kAlt.toString();
-    /**  @type {?KeyboardRemapModifierKeyRowElement} */
-    const altKeyRow = page.shadowRoot.querySelector('#altKey');
-    const altKeyDropDown = altKeyRow.shadowRoot.querySelector('#keyDropdown');
-    assertTrue(!!altKeyDropDown);
-    assertEquals(
-        altKeyDropDown.shadowRoot.querySelector('select').value, altKeyValue);
-    assertEquals(
-        metaKeyDropdown.shadowRoot.querySelector('select').value, metaKeyValue);
-    // Verify that the restored key icon is not highlighted.
-    assertEquals(metaKeyRow.keyState, 'default-remapping');
-  });
-
-  /**
-   * Verify that if the keyboard is disconnected while the user is in
-   * the remapping page, it will switch back to per device keyboard page.
-   */
-  test('re-route to back page when keyboard disconnected', async () => {
-    await initializeRemapKeysPage();
-    // Check it's currently in the modifier remapping page.
-    assertEquals(
-        routes.PER_DEVICE_KEYBOARD_REMAP_KEYS,
-        Router.getInstance().currentRoute);
-    assertEquals(page.keyboardId, page.keyboards[0].id);
-    const updatedKeyboards = [fakeKeyboards[1], fakeKeyboards[2]];
-    await setKeyboards(updatedKeyboards);
-    assertEquals(routes.PER_DEVICE_KEYBOARD, Router.getInstance().currentRoute);
-  });
-
-  /**
-   * Test that update keyboard settings api is called when keyboard remapping
-   * prefs settings change.
-   */
-  test('Update keyboard settings', async () => {
-    await initializeRemapKeysPage();
-    assertTrue(page.isInitialized);
-    // Set the modifier remappings to default stage.
-    const restoreButton =
-        page.shadowRoot.querySelector('#restoreDefaultsButton');
-    assertTrue(!!restoreButton);
-    restoreButton.click();
-    checkPrefsSetToDefault();
-
-    // Change several key remappings in the page.
-    page.set('fakeAltPref.value', ModifierKey.kAssistant);
-    page.set('fakeBackspacePref.value', ModifierKey.kControl);
-    page.set('fakeEscPref.value', ModifierKey.kVoid);
-
-    // Verify that the keyboard settings in the provider are updated.
-    const keyboards = page.keyboards;
-    assertTrue(!!keyboards);
-    const updatedRemapping = keyboards[0].settings.modifierRemappings;
-    assertTrue(!!updatedRemapping);
-    assertEquals(Object.keys(updatedRemapping).length, 3);
-    assertEquals(updatedRemapping[ModifierKey.kAlt], ModifierKey.kAssistant);
-    assertEquals(
-        updatedRemapping[ModifierKey.kBackspace], ModifierKey.kControl);
-    assertEquals(updatedRemapping[ModifierKey.kEscape], ModifierKey.kVoid);
-  });
-});
\ No newline at end of file
diff --git a/chrome/test/data/webui/settings/chromeos/per_device_pointing_stick_subsection_test.js b/chrome/test/data/webui/settings/chromeos/per_device_pointing_stick_subsection_test.js
deleted file mode 100644
index 975989a..0000000
--- a/chrome/test/data/webui/settings/chromeos/per_device_pointing_stick_subsection_test.js
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
-
-import {FakeInputDeviceSettingsProvider, fakePointingSticks, Router, routes, setInputDeviceSettingsProviderForTesting, SettingsPerDevicePointingStickSubsectionElement} from 'chrome://os-settings/chromeos/os_settings.js';
-import {assert} from 'chrome://resources/ash/common/assert.js';
-import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
-import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
-
-const POINTING_STICK_SPEED_SETTING_ID = 435;
-
-suite('PerDevicePointingStickSubsection', function() {
-  /**
-   * @type {?SettingsPerDevicePointingStickSubsectionElement}
-   */
-  let subsection = null;
-  /**
-   * @type {?FakeInputDeviceSettingsProvider}
-   */
-  let provider = null;
-
-  setup(() => {
-    PolymerTest.clearBody();
-  });
-
-  teardown(() => {
-    subsection = null;
-    provider = null;
-  });
-
-  /**
-   * @return {!Promise}
-   */
-  function initializePerDevicePointingStickSubsection() {
-    provider = new FakeInputDeviceSettingsProvider();
-    provider.setFakePointingSticks(fakePointingSticks);
-    setInputDeviceSettingsProviderForTesting(provider);
-    subsection =
-        document.createElement('settings-per-device-pointing-stick-subsection');
-    assertTrue(subsection != null);
-    subsection.pointingStick = {...fakePointingSticks[0]};
-    document.body.appendChild(subsection);
-    return flushTasks();
-  }
-
-  /**
-   * @param {!Object} pointingStick
-   * @return {!Promise}
-   */
-  function changePointingStickSubsectionState(pointingStick) {
-    subsection.pointingStick = pointingStick;
-    return flushTasks();
-  }
-
-  async function getConnectedPointingStickSettings() {
-    const pointingSticks = await provider.getConnectedPointingStickSettings();
-    return pointingSticks;
-  }
-
-  // Test that API are updated when pointing stick settings change.
-  test('Update API when pointing stick settings change', async () => {
-    await initializePerDevicePointingStickSubsection();
-    const pointingStickSwapButtonDropdown =
-        subsection.shadowRoot.querySelector('#pointingStickSwapButtonDropdown');
-    pointingStickSwapButtonDropdown.pref = {
-      ...pointingStickSwapButtonDropdown.pref,
-      value: true,
-    };
-    await flushTasks();
-    let updatedPointingSticks = await getConnectedPointingStickSettings();
-    assertEquals(
-        updatedPointingSticks[0].settings.swapRight,
-        pointingStickSwapButtonDropdown.pref.value);
-
-    const pointingStickAccelerationToggleButton =
-        subsection.shadowRoot.querySelector('#pointingStickAcceleration');
-    pointingStickAccelerationToggleButton.click();
-    await flushTasks();
-    updatedPointingSticks = await getConnectedPointingStickSettings();
-    assertEquals(
-        updatedPointingSticks[0].settings.accelerationEnabled,
-        pointingStickAccelerationToggleButton.pref.value);
-
-    const pointingStickSpeedSlider = assert(
-        subsection.shadowRoot.querySelector('#pointingStickSpeedSlider'));
-    MockInteractions.pressAndReleaseKeyOn(
-        pointingStickSpeedSlider.shadowRoot.querySelector('cr-slider'),
-        39 /* right */, [], 'ArrowRight');
-    await flushTasks();
-    updatedPointingSticks = await getConnectedPointingStickSettings();
-    assertEquals(
-        updatedPointingSticks[0].settings.sensitivity,
-        pointingStickSpeedSlider.pref.value);
-  });
-
-  // Test that pointing stick settings data are from the pointing stick
-  // provider.
-  test('Verify pointing stick settings data', async () => {
-    await initializePerDevicePointingStickSubsection();
-    let pointingStickSwapButtonDropdown =
-        subsection.shadowRoot.querySelector('#pointingStickSwapButtonDropdown');
-    assertEquals(
-        fakePointingSticks[0].settings.swapRight,
-        pointingStickSwapButtonDropdown.pref.value);
-    let pointingStickAccelerationToggleButton =
-        subsection.shadowRoot.querySelector('#pointingStickAcceleration');
-    assertEquals(
-        fakePointingSticks[0].settings.accelerationEnabled,
-        pointingStickAccelerationToggleButton.pref.value);
-    let pointingStickSpeedSlider = assert(
-        subsection.shadowRoot.querySelector('#pointingStickSpeedSlider'));
-    assertEquals(
-        fakePointingSticks[0].settings.sensitivity,
-        pointingStickSpeedSlider.pref.value);
-
-    await changePointingStickSubsectionState(fakePointingSticks[1]);
-    pointingStickSwapButtonDropdown =
-        subsection.shadowRoot.querySelector('#pointingStickSwapButtonDropdown');
-    assertEquals(
-        fakePointingSticks[1].settings.swapRight,
-        pointingStickSwapButtonDropdown.pref.value);
-    pointingStickAccelerationToggleButton =
-        subsection.shadowRoot.querySelector('#pointingStickAcceleration');
-    assertEquals(
-        fakePointingSticks[1].settings.accelerationEnabled,
-        pointingStickAccelerationToggleButton.pref.value);
-    pointingStickSpeedSlider = assert(
-        subsection.shadowRoot.querySelector('#pointingStickSpeedSlider'));
-    assertEquals(
-        fakePointingSticks[1].settings.sensitivity,
-        pointingStickSpeedSlider.pref.value);
-  });
-
-  /**
-   * Verify entering the page with search tags matched will auto focus the
-   * searched element.
-   */
-  test('deep linking mixin focus on the first searched element', async () => {
-    await initializePerDevicePointingStickSubsection();
-    const pointingStickSpeedSlider =
-        subsection.shadowRoot.querySelector('#pointingStickSpeedSlider');
-    subsection.pointingStickIndex = 0;
-    // Enter the page from auto repeat search tag.
-    const url = new URLSearchParams(
-        'search=trackpoint+speed&settingId=' +
-        encodeURIComponent(POINTING_STICK_SPEED_SETTING_ID));
-
-    await Router.getInstance().navigateTo(
-        routes.PER_DEVICE_POINTING_STICK,
-        /* dynamicParams= */ url, /* removeSearch= */ true);
-
-    await waitAfterNextRender(pointingStickSpeedSlider);
-    assertTrue(!!pointingStickSpeedSlider);
-    assertEquals(subsection.shadowRoot.activeElement, pointingStickSpeedSlider);
-  });
-
-  /**
-   * Verify entering the page with search tags matched wll not auto focus the
-   * searched element if it's not the first keyboard displayed.
-   */
-  test('deep linkng mixin does not focus on second element', async () => {
-    await initializePerDevicePointingStickSubsection();
-    const pointingStickSpeedSlider =
-        subsection.shadowRoot.querySelector('#pointingStickSpeedSlider');
-    subsection.pointingStickIndex = 1;
-    // Enter the page from auto repeat search tag.
-    const url = new URLSearchParams(
-        'search=trackpoint+speed&settingId=' +
-        encodeURIComponent(POINTING_STICK_SPEED_SETTING_ID));
-
-    await Router.getInstance().navigateTo(
-        routes.PER_DEVICE_POINTING_STICK,
-        /* dynamicParams= */ url, /* removeSearch= */ true);
-    await flushTasks();
-
-    assertTrue(!!pointingStickSpeedSlider);
-    assertFalse(!!subsection.shadowRoot.activeElement);
-  });
-});
diff --git a/chrome/test/data/webui/settings/chromeos/test_about_page_browser_proxy_chromeos.js b/chrome/test/data/webui/settings/chromeos/test_about_page_browser_proxy_chromeos.js
index 0ea5c68..d6110b9 100644
--- a/chrome/test/data/webui/settings/chromeos/test_about_page_browser_proxy_chromeos.js
+++ b/chrome/test/data/webui/settings/chromeos/test_about_page_browser_proxy_chromeos.js
@@ -21,6 +21,7 @@
       'getRegulatoryInfo',
       'checkInternetConnection',
       'getEndOfLifeInfo',
+      'endOfLifeIncentiveButtonClicked',
       'launchReleaseNotes',
       'openOsHelpPage',
       'openDiagnostics',
@@ -67,6 +68,7 @@
     this.endOfLifeInfo_ = {
       hasEndOfLife: false,
       aboutPageEndOfLifeMessage: '',
+      shouldShowEndOfLifeIncentive: false,
     };
 
     /** @private {!boolean} */
@@ -203,6 +205,10 @@
     return Promise.resolve(this.endOfLifeInfo_);
   }
 
+  endOfLifeIncentiveButtonClicked() {
+    this.methodCalled('endOfLifeIncentiveButtonClicked');
+  }
+
   /** @override */
   setChannel(channel, isPowerwashAllowed) {
     this.methodCalled('setChannel', [channel, isPowerwashAllowed]);
diff --git a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_context_menu_test.ts b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_context_menu_test.ts
index 1fb316d6..73344be 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_context_menu_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_context_menu_test.ts
@@ -78,6 +78,8 @@
       menuOpenNewWindowWithCount: 'Open all in new window',
       menuOpenIncognito: 'Open in Incognito window',
       menuOpenIncognitoWithCount: 'Open all in Incognito window',
+      menuOpenNewTabGroup: 'Open in new tab group',
+      menuOpenNewTabGroupWithCount: 'Open all in new tab group',
       menuEdit: 'Edit…',
       menuMoveToBookmarksBar: 'Move to Bookmarks Bar folder',
       menuTrackPrice: 'Track price',
@@ -137,7 +139,7 @@
 
     const menuItems = powerBookmarksContextMenu.shadowRoot!.querySelectorAll(
         '.dropdown-item');
-    assertEquals(menuItems.length, 6);
+    assertEquals(menuItems.length, 7);
     assertEquals(
         menuItems[0]!.textContent!.includes(
             loadTimeData.getString('menuOpenNewTab')),
@@ -152,14 +154,18 @@
         true);
     assertEquals(
         menuItems[3]!.textContent!.includes(
-            loadTimeData.getString('menuMoveToBookmarksBar')),
+            loadTimeData.getString('menuOpenNewTabGroup')),
         true);
     assertEquals(
         menuItems[4]!.textContent!.includes(
-            loadTimeData.getString('menuRename')),
+            loadTimeData.getString('menuMoveToBookmarksBar')),
         true);
     assertEquals(
         menuItems[5]!.textContent!.includes(
+            loadTimeData.getString('menuRename')),
+        true);
+    assertEquals(
+        menuItems[6]!.textContent!.includes(
             loadTimeData.getString('tooltipDelete')),
         true);
   });
@@ -174,7 +180,7 @@
 
     const menuItems = powerBookmarksContextMenu.shadowRoot!.querySelectorAll(
         '.dropdown-item');
-    assertEquals(menuItems.length, 3);
+    assertEquals(menuItems.length, 4);
     assertEquals(
         menuItems[0]!.textContent!.includes(
             loadTimeData.getString('menuOpenNewTabWithCount')),
@@ -187,6 +193,10 @@
         menuItems[2]!.textContent!.includes(
             loadTimeData.getString('menuOpenIncognitoWithCount')),
         true);
+    assertEquals(
+        menuItems[3]!.textContent!.includes(
+            loadTimeData.getString('menuOpenNewTabGroupWithCount')),
+        true);
   });
 
   test('ShowsMenuItemsForPriceTracking', () => {
diff --git a/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts b/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts
index fc18eb3..543a003e 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts
@@ -31,6 +31,7 @@
       'contextMenuOpenBookmarkInNewTab',
       'contextMenuOpenBookmarkInNewWindow',
       'contextMenuOpenBookmarkInIncognitoWindow',
+      'contextMenuOpenBookmarkInNewTabGroup',
       'contextMenuAddToBookmarksBar',
       'contextMenuRemoveFromBookmarksBar',
       'contextMenuDelete',
@@ -95,6 +96,10 @@
     this.methodCalled('contextMenuOpenBookmarkInIncognitoWindow', ids, source);
   }
 
+  contextMenuOpenBookmarkInNewTabGroup(ids: string[], source: ActionSource) {
+    this.methodCalled('contextMenuOpenBookmarkInNewTabGroup', ids, source);
+  }
+
   contextMenuAddToBookmarksBar(id: string, source: ActionSource) {
     this.methodCalled('contextMenuAddToBookmarksBar', id, source);
   }
diff --git a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts
index 95cf1ee0..6a365f6 100644
--- a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts
+++ b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts
@@ -796,6 +796,150 @@
     assertEquals(selection!.focusOffset, 2);
   });
 
+  test('updateContent selection outsideDistilledContent', () => {
+    // root htmlTag='#document' id=1
+    // ++paragraph htmlTag='p' id=2
+    // ++++staticText name='Hello' id=3
+    // ++paragraph htmlTag='p' id=4
+    // ++++staticText name='World' id=5
+    // ++paragraph htmlTag='p' id=6
+    // ++++staticText name='Friend' id=7
+    // ++++staticText name='!' id=8
+    const axTree = {
+      rootId: 1,
+      nodes: [
+        {
+          id: 1,
+          role: 'rootWebArea',
+          htmlTag: '#document',
+          childIds: [2, 4, 6],
+        },
+        {
+          id: 2,
+          role: 'paragraph',
+          htmlTag: 'p',
+          childIds: [3],
+        },
+        {
+          id: 3,
+          role: 'staticText',
+          name: 'Hello',
+        },
+        {
+          id: 4,
+          role: 'paragraph',
+          htmlTag: 'p',
+          childIds: [5],
+        },
+        {
+          id: 5,
+          role: 'staticText',
+          name: 'World',
+        },
+        {
+          id: 6,
+          role: 'paragraph',
+          htmlTag: 'p',
+          childIds: [7, 8],
+        },
+        {
+          id: 7,
+          role: 'staticText',
+          name: 'Friend',
+        },
+        {
+          id: 8,
+          role: 'staticText',
+          name: '!',
+        },
+      ],
+      selection: {
+        anchor_object_id: 5,
+        focus_object_id: 7,
+        anchor_offset: 1,
+        focus_offset: 2,
+        is_backward: false,
+      },
+    };
+    chrome.readAnything.setContentForTesting(axTree, [2]);
+    // The selection is outside the content nodes.The expected string contains
+    // the complete text of each node in the selection.
+    const expected = '<div><p>World</p><p>Friend</p></div>';
+    assertContainerInnerHTML(expected);
+  });
+
+  test('updateContent selection partiallyOutsideDistilledContent', () => {
+    // root htmlTag='#document' id=1
+    // ++paragraph htmlTag='p' id=2
+    // ++++staticText name='Hello' id=3
+    // ++paragraph htmlTag='p' id=4
+    // ++++staticText name='World' id=5
+    // ++paragraph htmlTag='p' id=6
+    // ++++staticText name='Friend' id=7
+    // ++++staticText name='!' id=8
+    const axTree = {
+      rootId: 1,
+      nodes: [
+        {
+          id: 1,
+          role: 'rootWebArea',
+          htmlTag: '#document',
+          childIds: [2, 4, 6],
+        },
+        {
+          id: 2,
+          role: 'paragraph',
+          htmlTag: 'p',
+          childIds: [3],
+        },
+        {
+          id: 3,
+          role: 'staticText',
+          name: 'Hello',
+        },
+        {
+          id: 4,
+          role: 'paragraph',
+          htmlTag: 'p',
+          childIds: [5],
+        },
+        {
+          id: 5,
+          role: 'staticText',
+          name: 'World',
+        },
+        {
+          id: 6,
+          role: 'paragraph',
+          htmlTag: 'p',
+          childIds: [7, 8],
+        },
+        {
+          id: 7,
+          role: 'staticText',
+          name: 'Friend',
+        },
+        {
+          id: 8,
+          role: 'staticText',
+          name: '!',
+        },
+      ],
+      selection: {
+        anchor_object_id: 3,
+        focus_object_id: 7,
+        anchor_offset: 1,
+        focus_offset: 2,
+        is_backward: false,
+      },
+    };
+    chrome.readAnything.setContentForTesting(axTree, [2, 4]);
+    // The selection has content inside and outside the content nodes. The
+    // expected string contains the complete text of each node in the selection.
+    const expected = '<div><p>Hello</p><p>World</p><p>Friend</p></div>';
+    assertContainerInnerHTML(expected);
+  });
+
   test('updateContent setSelectedText', async () => {
     // root htmlTag='#document' id=1
     // ++staticText name='Hello' id=2
diff --git a/chrome/test/webapps/coverage/coverage_cros.tsv b/chrome/test/webapps/coverage/coverage_cros.tsv
index 464c404f..7a7e956 100644
--- a/chrome/test/webapps/coverage/coverage_cros.tsv
+++ b/chrome/test/webapps/coverage/coverage_cros.tsv
@@ -1026,96 +1026,63 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌑	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_tab_created🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	close_pwa🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	close_pwa🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	close_pwa🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	close_pwa🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	close_pwa🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	close_pwa🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
 create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
@@ -1126,16 +1093,16 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
 create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
@@ -1146,16 +1113,16 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_tab_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
 create_shortcut_FileHandler_Windowed🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 create_shortcut_FileHandler_Browser🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
diff --git a/chrome/test/webapps/coverage/coverage_linux.tsv b/chrome/test/webapps/coverage/coverage_linux.tsv
index 785903f5..d5b2b559 100644
--- a/chrome/test/webapps/coverage/coverage_linux.tsv
+++ b/chrome/test/webapps/coverage/coverage_linux.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 71%, with partial coverage: 91%
+# Full coverage: 73%, with partial coverage: 92%
 create_shortcut_Standalone_Windowed🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_chrome_apps_Standalone🌓	check_app_title_Standalone_StandaloneOriginal🌑
@@ -1339,96 +1339,63 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
@@ -1439,16 +1406,16 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
@@ -1459,16 +1426,16 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
 create_shortcut_FileHandler_Windowed🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 create_shortcut_FileHandler_Browser🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
diff --git a/chrome/test/webapps/coverage/coverage_mac.tsv b/chrome/test/webapps/coverage/coverage_mac.tsv
index d564949..cb3f3c9 100644
--- a/chrome/test/webapps/coverage/coverage_mac.tsv
+++ b/chrome/test/webapps/coverage/coverage_mac.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 67%, with partial coverage: 85%
+# Full coverage: 75%, with partial coverage: 92%
 create_shortcut_Standalone_Windowed🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_chrome_apps_Standalone🌓	check_app_title_Standalone_StandaloneOriginal🌑
@@ -229,30 +229,30 @@
 install_policy_app_Standalone_NoShortcut_Browser_WebApp🌓	enable_run_on_os_login_from_app_home_Standalone🌕	apply_run_on_os_login_policy_blocked_Standalone🌕	remove_run_on_os_login_policy_Standalone🌕	check_run_on_os_login_enabled_Standalone🌕
 install_menu_option_Standalone🌕	enable_run_on_os_login_from_app_settings_Standalone🌕	apply_run_on_os_login_policy_blocked_Standalone🌕	remove_run_on_os_login_policy_Standalone🌕	check_run_on_os_login_enabled_Standalone🌕
 install_menu_option_Standalone🌕	enable_run_on_os_login_from_app_home_Standalone🌕	apply_run_on_os_login_policy_blocked_Standalone🌕	remove_run_on_os_login_policy_Standalone🌕	check_run_on_os_login_enabled_Standalone🌕
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_app_settings_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_app_settings_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_app_settings_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_app_settings_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_app_settings_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	switch_profile_clients_Client1🌑	sync_turn_off🌑	uninstall_from_app_settings_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_app_settings_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_app_settings_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_app_settings_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕	install_locally_Standalone🌓	check_run_on_os_login_enabled_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕	install_locally_Standalone🌓	check_run_on_os_login_enabled_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_app_settings_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕	install_locally_Standalone🌓	check_run_on_os_login_enabled_Standalone🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕	install_locally_Standalone🌓	check_run_on_os_login_enabled_Standalone🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕	install_locally_Standalone🌓	check_run_on_os_login_enabled_Standalone🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_app_settings_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕	install_locally_Standalone🌓	check_run_on_os_login_enabled_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕	install_locally_Standalone🌓	check_run_on_os_login_enabled_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕	install_locally_Standalone🌓	check_run_on_os_login_enabled_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	switch_profile_clients_Client2🌑	apply_run_on_os_login_policy_run_windowed_Standalone🌑	check_run_on_os_login_disabled_Standalone🌑	install_locally_Standalone🌑	check_run_on_os_login_enabled_Standalone🌑
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	switch_profile_clients_Client1🌕	sync_turn_off🌕	uninstall_from_app_settings_Standalone🌕	switch_profile_clients_Client2🌕	apply_run_on_os_login_policy_run_windowed_Standalone🌕	check_run_on_os_login_disabled_Standalone🌕	install_locally_Standalone🌓	check_run_on_os_login_enabled_Standalone🌕
 create_shortcut_Standalone_Windowed🌕	set_app_badge_Standalone🌑	clear_app_badge_Standalone🌑	check_app_badge_empty_Standalone🌑
 install_omnibox_icon_Standalone🌕	set_app_badge_Standalone🌑	clear_app_badge_Standalone🌑	check_app_badge_empty_Standalone🌑
 install_menu_option_Standalone🌕	set_app_badge_Standalone🌑	clear_app_badge_Standalone🌑	check_app_badge_empty_Standalone🌑
@@ -658,107 +658,107 @@
 install_policy_app_Standalone_NoShortcut_Windowed_WebApp🌓	open_app_settings_from_app_menu_Standalone🌕	check_browser_navigation_is_app_settings_Standalone🌕
 install_menu_option_Standalone🌕	open_app_settings_from_chrome_apps_Standalone🌕	check_browser_navigation_is_app_settings_Standalone🌕
 install_menu_option_Standalone🌕	open_app_settings_from_app_menu_Standalone🌕	check_browser_navigation_is_app_settings_Standalone🌕
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	check_platform_shortcut_and_icon_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	check_platform_shortcut_and_icon_Standalone🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	check_platform_shortcut_and_icon_Standalone🌕
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	check_platform_shortcut_and_icon_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	check_platform_shortcut_and_icon_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	check_platform_shortcut_and_icon_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	check_platform_shortcut_and_icon_Standalone🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	check_app_in_list_tabbed_Standalone🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	navigate_browser_Standalone🌕	check_install_icon_shown🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	navigate_browser_Standalone🌕	check_launch_icon_not_shown🌕
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	check_app_in_list_windowed_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	check_app_in_list_windowed_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	check_app_in_list_windowed_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	navigate_browser_Standalone🌑	check_install_icon_not_shown🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	navigate_browser_Standalone🌑	check_install_icon_not_shown🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	navigate_browser_Standalone🌑	check_install_icon_not_shown🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	navigate_browser_Standalone🌑	check_launch_icon_shown🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	navigate_browser_Standalone🌑	check_launch_icon_shown🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	navigate_browser_Standalone🌑	check_launch_icon_shown🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	check_app_in_list_windowed_Standalone🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	check_app_in_list_windowed_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	check_app_in_list_windowed_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	navigate_browser_Standalone🌕	check_install_icon_not_shown🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	navigate_browser_Standalone🌕	check_install_icon_not_shown🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	navigate_browser_Standalone🌕	check_install_icon_not_shown🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	navigate_browser_Standalone🌕	check_launch_icon_shown🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	navigate_browser_Standalone🌕	check_launch_icon_shown🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	navigate_browser_Standalone🌕	check_launch_icon_shown🌕
 create_shortcut_NotPromotable_Browser🌕	switch_profile_clients_Client2🌕	install_locally_NotPromotable🌓	check_app_in_list_tabbed_NotPromotable🌕
 create_shortcut_NotPromotable_Browser🌕	switch_profile_clients_Client2🌕	install_locally_NotPromotable🌓	navigate_browser_NotPromotable🌕	check_launch_icon_not_shown🌕
-create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_NotPromotable🌑	check_app_in_list_windowed_NotPromotable🌑
-create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_NotPromotable🌑	navigate_browser_NotPromotable🌑	check_install_icon_not_shown🌑
-create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_NotPromotable🌑	navigate_browser_NotPromotable🌑	check_launch_icon_shown🌑
-create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_NotPromotable🌑	check_platform_shortcut_and_icon_NotPromotable🌑
+create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_NotPromotable🌓	check_app_in_list_windowed_NotPromotable🌕
+create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_NotPromotable🌓	navigate_browser_NotPromotable🌕	check_install_icon_not_shown🌕
+create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_NotPromotable🌓	navigate_browser_NotPromotable🌕	check_launch_icon_shown🌕
+create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_NotPromotable🌓	check_platform_shortcut_and_icon_NotPromotable🌕
 create_shortcut_NotPromotable_Browser🌕	switch_profile_clients_Client2🌕	install_locally_NotPromotable🌓	check_platform_shortcut_and_icon_NotPromotable🌕
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_menu_option_Standalone🌑	check_window_created🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_launch_icon_Standalone🌑	check_window_created🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_chrome_apps_Standalone🌑	check_window_created🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_platform_shortcut_Standalone🌑	check_window_created🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_menu_option_Standalone🌑	check_window_created🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_launch_icon_Standalone🌑	check_window_created🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_chrome_apps_Standalone🌑	check_window_created🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_platform_shortcut_Standalone🌑	check_window_created🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_menu_option_Standalone🌑	check_window_created🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_launch_icon_Standalone🌑	check_window_created🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_chrome_apps_Standalone🌑	check_window_created🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	install_locally_Standalone🌑	launch_from_platform_shortcut_Standalone🌑	check_window_created🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_menu_option_Standalone🌕	check_window_created🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_launch_icon_Standalone🌕	check_window_created🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌓	check_window_created🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_platform_shortcut_Standalone🌑	check_window_created🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_menu_option_Standalone🌕	check_window_created🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_launch_icon_Standalone🌕	check_window_created🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌓	check_window_created🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_platform_shortcut_Standalone🌑	check_window_created🌑
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_menu_option_Standalone🌕	check_window_created🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_launch_icon_Standalone🌕	check_window_created🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌓	check_window_created🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_platform_shortcut_Standalone🌑	check_window_created🌑
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_Standalone🌓	check_tab_created🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	launch_from_platform_shortcut_Standalone🌑	check_tab_created🌑
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌓	check_tab_created🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_platform_shortcut_Standalone🌑	check_tab_created🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	launch_from_chrome_apps_Standalone🌑	check_tab_created🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	launch_from_platform_shortcut_Standalone🌑	check_tab_created🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	launch_from_chrome_apps_Standalone🌑	check_tab_created🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	launch_from_platform_shortcut_Standalone🌑	check_tab_created🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	launch_from_chrome_apps_Standalone🌑	check_tab_created🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	launch_from_platform_shortcut_Standalone🌑	check_tab_created🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	uninstall_from_list_Standalone🌑	check_app_not_in_list_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_Standalone🌓	check_tab_created🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	launch_from_platform_shortcut_Standalone🌑	check_tab_created🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_Standalone🌓	check_tab_created🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	launch_from_platform_shortcut_Standalone🌑	check_tab_created🌑
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_Standalone🌓	check_tab_created🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	launch_from_platform_shortcut_Standalone🌑	check_tab_created🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	uninstall_from_list_Standalone🌕	check_app_not_in_list_Standalone🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	uninstall_from_list_Standalone🌕	check_app_not_in_list_Standalone🌕
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	uninstall_from_list_Standalone🌑	check_app_not_in_list_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	uninstall_from_list_Standalone🌑	check_app_not_in_list_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	uninstall_from_list_Standalone🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	uninstall_from_list_Standalone🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	uninstall_from_list_Standalone🌕	check_app_not_in_list_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client1🌕	check_app_not_in_list_Standalone🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client1🌕	check_app_not_in_list_Standalone🌕
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	uninstall_from_list_Standalone🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	uninstall_from_list_Standalone🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client1🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	uninstall_from_list_Standalone🌕	switch_profile_clients_Client1🌕	check_app_not_in_list_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_Standalone🌑
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	check_platform_shortcut_not_exists_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	check_platform_shortcut_not_exists_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	navigate_browser_Standalone🌑	check_install_icon_shown🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	navigate_browser_Standalone🌑	check_install_icon_shown🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	navigate_browser_Standalone🌑	check_install_icon_shown🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	navigate_browser_Standalone🌑	check_launch_icon_not_shown🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	navigate_browser_Standalone🌑	check_launch_icon_not_shown🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	navigate_browser_Standalone🌑	check_launch_icon_not_shown🌑
-create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_NotPromotable🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	navigate_browser_Standalone🌕	check_install_icon_shown🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	navigate_browser_Standalone🌕	check_install_icon_shown🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	navigate_browser_Standalone🌕	check_install_icon_shown🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	navigate_browser_Standalone🌕	check_launch_icon_not_shown🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	navigate_browser_Standalone🌕	check_launch_icon_not_shown🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	navigate_browser_Standalone🌕	check_launch_icon_not_shown🌕
+create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_NotPromotable🌕
 create_shortcut_NotPromotable_Browser🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_NotPromotable🌕
-create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌑	check_platform_shortcut_not_exists_NotPromotable🌑
+create_shortcut_NotPromotable_Windowed🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_NotPromotable🌑
 create_shortcut_NotPromotable_Browser🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_NotPromotable🌑
-sync_turn_off🌕	create_shortcut_Standalone_Windowed🌑	sync_turn_on🌑	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_Standalone🌑
+sync_turn_off🌕	create_shortcut_Standalone_Windowed🌕	sync_turn_on🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕
 sync_turn_off🌕	create_shortcut_Standalone_Browser🌕	sync_turn_on🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕
-sync_turn_off🌕	install_omnibox_icon_Standalone🌑	sync_turn_on🌑	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_Standalone🌑
-sync_turn_off🌕	install_menu_option_Standalone🌑	sync_turn_on🌑	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_Standalone🌑
-sync_turn_off🌕	create_shortcut_NotPromotable_Windowed🌑	sync_turn_on🌑	switch_profile_clients_Client2🌑	check_app_in_list_not_locally_installed_NotPromotable🌑
+sync_turn_off🌕	install_omnibox_icon_Standalone🌕	sync_turn_on🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕
+sync_turn_off🌕	install_menu_option_Standalone🌕	sync_turn_on🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕
+sync_turn_off🌕	create_shortcut_NotPromotable_Windowed🌕	sync_turn_on🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_NotPromotable🌕
 sync_turn_off🌕	create_shortcut_NotPromotable_Browser🌕	sync_turn_on🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_NotPromotable🌕
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	sync_turn_on🌕	check_app_in_list_not_locally_installed_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	sync_turn_on🌕	check_app_in_list_not_locally_installed_Standalone🌕
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	sync_turn_on🌕	check_app_in_list_not_locally_installed_Standalone🌕
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
-create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	sync_turn_on🌕	check_app_in_list_not_locally_installed_Standalone🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	sync_turn_on🌕	check_app_in_list_not_locally_installed_Standalone🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	sync_turn_on🌕	check_app_in_list_not_locally_installed_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	sync_turn_on🌕	check_app_in_list_not_locally_installed_Standalone🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_app_in_list_not_locally_installed_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	sync_turn_on🌕	check_platform_shortcut_not_exists_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	sync_turn_on🌕	check_platform_shortcut_not_exists_Standalone🌑
+create_shortcut_Standalone_Windowed🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	sync_turn_on🌕	check_platform_shortcut_not_exists_Standalone🌑
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
 create_shortcut_Standalone_Browser🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
-install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_list_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_menu_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
-install_menu_option_Standalone🌕	switch_profile_clients_Client2🌑	sync_turn_off🌑	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	sync_turn_on🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	sync_turn_on🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_list_Standalone🌕	sync_turn_on🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_menu_Standalone🌕	sync_turn_on🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	sync_turn_off🌕	uninstall_from_os_Standalone🌑	sync_turn_on🌑	check_platform_shortcut_not_exists_Standalone🌑
 create_shortcut_Standalone_Browser🌕	install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	check_platform_shortcut_and_icon_Standalone🌕
 create_shortcut_Standalone_Browser🌕	install_policy_app_Standalone_NoShortcut_Windowed_WebApp🌓	check_platform_shortcut_and_icon_Standalone🌕
 create_shortcut_Standalone_Windowed🌕	install_policy_app_Standalone_NoShortcut_Windowed_WebApp🌓	check_platform_shortcut_and_icon_Standalone🌕
@@ -1329,96 +1329,63 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
@@ -1429,16 +1396,16 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
@@ -1449,16 +1416,16 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
 create_shortcut_FileHandler_Windowed🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 create_shortcut_FileHandler_Browser🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
diff --git a/chrome/test/webapps/coverage/coverage_win.tsv b/chrome/test/webapps/coverage/coverage_win.tsv
index 5751880..51d26f64 100644
--- a/chrome/test/webapps/coverage/coverage_win.tsv
+++ b/chrome/test/webapps/coverage/coverage_win.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 73%, with partial coverage: 92%
+# Full coverage: 74%, with partial coverage: 93%
 create_shortcut_Standalone_Windowed🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_chrome_apps_Standalone🌓	check_app_title_Standalone_StandaloneOriginal🌑
@@ -1339,96 +1339,63 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_OneBarFile🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+create_shortcut_FileHandler_Windowed🌕	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_settings_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	set_open_in_tab_from_app_home_FileHandler🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_tab_created🌕	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	close_pwa🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_files_loaded_in_site_FileHandler_OneFooFile🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
@@ -1439,16 +1406,16 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
@@ -1459,16 +1426,16 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_tab_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
 create_shortcut_FileHandler_Windowed🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 create_shortcut_FileHandler_Browser🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
diff --git a/chrome/test/webapps/data/critical_user_journeys.md b/chrome/test/webapps/data/critical_user_journeys.md
index 400ff25d..9adab92 100644
--- a/chrome/test/webapps/data/critical_user_journeys.md
+++ b/chrome/test/webapps/data/critical_user_journeys.md
@@ -319,22 +319,48 @@
 | #Platforms | Test -> | | | | | | | | | | | | | | | | |
 | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
 | WMLC | install_or_shortcut(FileHandler) | check_site_handles_file(FileHandler, Foo) | check_site_handles_file(FileHandler, Bar) |
-| # Single open & multiple open behavior |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, AskAgain) |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, AskAgain) | check_pwa_window_created(FileHandler, One) | check_files_loaded_in_site(FileHandler, OneFooFile) |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleFooFiles, Allow, AskAgain) |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleFooFiles, Allow, AskAgain) | check_pwa_window_created(FileHandler, One) | check_files_loaded_in_site(FileHandler, MultipleFooFiles) |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneBarFile, Allow, AskAgain) |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneBarFile, Allow, AskAgain) | check_pwa_window_created(FileHandler, One) | check_files_loaded_in_site(FileHandler, OneBarFile) |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleBarFiles, Allow, AskAgain) |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleBarFiles, Allow, AskAgain) | check_pwa_window_created(FileHandler, Two) | check_files_loaded_in_site(FileHandler, MultipleBarFiles) |
-| # Dialog options |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, Remember) | launch_file_expect_no_dialog(FileHandler, OneFooFile) | check_pwa_window_created(FileHandler, One) |
+
+### Launching a single window or tab vs multiple
+
+The test behavior can change whether the site is configured to open as a window or open as a tab. To achieve this, we use three actions to enter those states:
+- `install_or_shortcut_windowed`
+- `install_or_shortcut_tabbed`
+- `install_or_shortcut_windowed` + `set_open_in_tab`
+
+| #Platforms | Test -> | | | | | | | | | | | | | | | | |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| # Single file opens should open just one window or tab. |
+| WMLC | install_or_shortcut_windowed(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, AskAgain) | check_pwa_window_created(FileHandler, One) | check_files_loaded_in_site(FileHandler, OneFooFile) |
+| WMLC | install_or_shortcut_tabbed(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, AskAgain) | check_tab_created | check_files_loaded_in_site(FileHandler, OneFooFile) |
+| WMLC | install_or_shortcut_windowed(FileHandler) | set_open_in_tab(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, AskAgain) | check_tab_created | check_files_loaded_in_site(FileHandler, OneFooFile) |
+| WMLC | install_or_shortcut_windowed(FileHandler) | launch_file_expect_dialog(FileHandler, OneBarFile, Allow, AskAgain) | check_pwa_window_created(FileHandler, One) | check_files_loaded_in_site(FileHandler, OneBarFile) |
+| WMLC | install_or_shortcut_tabbed(FileHandler) | launch_file_expect_dialog(FileHandler, OneBarFile, Allow, AskAgain) | check_tab_created | check_files_loaded_in_site(FileHandler, OneBarFile) |
+| WMLC | install_or_shortcut_windowed(FileHandler) | set_open_in_tab(FileHandler) | launch_file_expect_dialog(FileHandler, OneBarFile, Allow, AskAgain) | check_tab_created | check_files_loaded_in_site(FileHandler, OneBarFile) |
+| # Opening multiple Foo files only opens one window or tab. |
+| WMLC | install_or_shortcut_windowed(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleFooFiles, Allow, AskAgain) | check_pwa_window_created(FileHandler, One) | check_files_loaded_in_site(FileHandler, MultipleFooFiles) |
+| WMLC | install_or_shortcut_tabbed(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleFooFiles, Allow, AskAgain) | check_tab_created | check_files_loaded_in_site(FileHandler, MultipleFooFiles) |
+| WMLC | install_or_shortcut_windowed(FileHandler) | set_open_in_tab(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleFooFiles, Allow, AskAgain) | check_tab_created | check_files_loaded_in_site(FileHandler, MultipleFooFiles) |
+| # Opening multiple Bar files opens multiple windows or tabs. |
+| WMLC | install_or_shortcut_windowed(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleBarFiles, Allow, AskAgain) | check_pwa_window_created(FileHandler, Two) | check_files_loaded_in_site(FileHandler, MultipleBarFiles) |
+| WMLC | install_or_shortcut_tabbed(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleBarFiles, Allow, AskAgain) | check_tab_created | check_files_loaded_in_site(FileHandler, MultipleBarFiles) |
+| WMLC | install_or_shortcut_windowed(FileHandler) | set_open_in_tab(FileHandler) | launch_file_expect_dialog(FileHandler, MultipleBarFiles, Allow, AskAgain) | check_tab_created | check_files_loaded_in_site(FileHandler, MultipleBarFiles) |
+
+### Dialog option
+
+| #Platforms | Test -> | | | | | | | | | | | | | | | | |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| WMLC | install_or_shortcut_windowed(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, Remember) | launch_file_expect_no_dialog(FileHandler, OneFooFile) |
+| WMLC | install_or_shortcut_windowed(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, Remember) | close_pwa | launch_file_expect_no_dialog(FileHandler, OneFooFile) | check_files_loaded_in_site(FileHandler, OneFooFile) |
+| WMLC | install_or_shortcut_windowed(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, Remember) | close_pwa | launch_file_expect_no_dialog(FileHandler, OneFooFile) | check_files_loaded_in_site(FileHandler, OneFooFile) |
 | WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, AskAgain) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, AskAgain) |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Deny, AskAgain) | check_window_not_created | check_site_handles_file(FileHandler, Foo) | check_site_handles_file(FileHandler, Bar) |
+| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Deny, AskAgain) | check_window_not_created | check_tab_not_created | check_site_handles_file(FileHandler, Foo) | check_site_handles_file(FileHandler, Bar) |
 | WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Deny, AskAgain) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, AskAgain) |
-| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Deny, Remember) | check_window_not_created | check_site_not_handles_file(FileHandler, Foo) | check_site_not_handles_file(FileHandler, Bar) |
-| # Policy approval |
+| WMLC | install_or_shortcut(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Deny, Remember) | check_window_not_created | check_tab_not_created | check_site_not_handles_file(FileHandler, Foo) | check_site_not_handles_file(FileHandler, Bar) |
+
+### Policy test for forcing file handling approval
+
+| #Platforms | Test -> | | | | | | | | | | | | | | | | |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
 | WMLC | install_or_shortcut(FileHandler) | add_file_handling_policy_approval(FileHandler) | launch_file_expect_no_dialog(FileHandler, OneFooFile) | check_pwa_window_created(FileHandler, One) |
 | WMLC | install_or_shortcut(FileHandler) | add_file_handling_policy_approval(FileHandler) | remove_file_handling_policy_approval(FileHandler) | launch_file_expect_dialog(FileHandler, OneFooFile, Allow, AskAgain) |
 
diff --git a/chrome/updater/app/server/win/server.cc b/chrome/updater/app/server/win/server.cc
index eeffef0..8876dc2 100644
--- a/chrome/updater/app/server/win/server.cc
+++ b/chrome/updater/app/server/win/server.cc
@@ -237,6 +237,18 @@
   return list->Do();
 }
 
+absl::optional<int> DaynumFromDWORD(DWORD value) {
+  const int daynum = static_cast<int>(value);
+
+  // When daynum is positive, it is the number of days since January 1, 2007.
+  // It's reasonable to only accept value between 3000 (maps to Mar 20, 2015)
+  // and 50000 (maps to Nov 24, 2143).
+  // -1 is special value for first install.
+  return daynum == -1 || (daynum >= 3000 && daynum <= 50000)
+             ? absl::make_optional(daynum)
+             : absl::nullopt;
+}
+
 }  // namespace
 
 HRESULT IsCOMCallerAllowed() {
@@ -452,6 +464,18 @@
       if (client_state_key.ReadValue(kRegValueAP, &ap) == ERROR_SUCCESS) {
         registration.ap = base::SysWideToUTF8(ap);
       }
+
+      DWORD date_last_activity = 0;
+      if (client_state_key.ReadValueDW(kRegValueDateOfLastActivity,
+                                       &date_last_activity) == ERROR_SUCCESS) {
+        registration.dla = DaynumFromDWORD(date_last_activity);
+      }
+
+      DWORD date_last_rollcall = 0;
+      if (client_state_key.ReadValueDW(kRegValueDateOfLastRollcall,
+                                       &date_last_rollcall) == ERROR_SUCCESS) {
+        registration.dlrc = DaynumFromDWORD(date_last_rollcall);
+      }
     }
 
     register_callback.Run(registration);
diff --git a/chrome/updater/ipc/proxy_impl_base_win.h b/chrome/updater/ipc/proxy_impl_base_win.h
index 252a453..901bfb43 100644
--- a/chrome/updater/ipc/proxy_impl_base_win.h
+++ b/chrome/updater/ipc/proxy_impl_base_win.h
@@ -75,7 +75,6 @@
       constexpr int kNumTries = 2;
       HRESULT hr = E_FAIL;
       for (int i = 0; i != kNumTries; ++i) {
-        base::PlatformThread::Sleep(kCreateUpdaterInstanceDelay);
         Microsoft::WRL::ComPtr<IUnknown> server;
         hr = ::CoCreateInstance(clsid, nullptr, CLSCTX_LOCAL_SERVER,
                                 IID_PPV_ARGS(&server));
@@ -92,6 +91,9 @@
         if (hr == REGDB_E_CLASSNOTREG) {
           return base::unexpected(hr);
         }
+
+        // Sleep before trying again.
+        base::PlatformThread::Sleep(kCreateUpdaterInstanceDelay);
       }
       return base::unexpected(hr);
     }(Derived::GetClassGuid(scope_));
diff --git a/chrome/updater/persisted_data.cc b/chrome/updater/persisted_data.cc
index bc48822..a8ac0bb 100644
--- a/chrome/updater/persisted_data.cc
+++ b/chrome/updater/persisted_data.cc
@@ -148,11 +148,23 @@
 #endif
 }
 
+absl::optional<int> PersistedData::GetDateLastActive(
+    const std::string& id) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return GetInteger(id, kDLA);
+}
+
 void PersistedData::SetDateLastActive(const std::string& id, int dla) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   SetInteger(id, kDLA, dla);
 }
 
+absl::optional<int> PersistedData::GetDateLastRollcall(
+    const std::string& id) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return GetInteger(id, kDLRC);
+}
+
 void PersistedData::SetDateLastRollcall(const std::string& id, int dlrc) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   SetInteger(id, kDLRC, dlrc);
@@ -249,6 +261,25 @@
   return app;
 }
 
+absl::optional<int> PersistedData::GetInteger(const std::string& id,
+                                              const std::string& key) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!pref_service_) {
+    return absl::nullopt;
+  }
+  ScopedDictPrefUpdate update(pref_service_,
+                              update_client::kPersistedDataPreference);
+  base::Value::Dict* apps = update->FindDict("apps");
+  if (!apps) {
+    return absl::nullopt;
+  }
+  base::Value::Dict* app = apps->FindDict(base::ToLowerASCII(id));
+  if (!app) {
+    return absl::nullopt;
+  }
+  return app->FindInt(key);
+}
+
 void PersistedData::SetInteger(const std::string& id,
                                const std::string& key,
                                int value) {
diff --git a/chrome/updater/persisted_data.h b/chrome/updater/persisted_data.h
index 656362051..b94a6b69 100644
--- a/chrome/updater/persisted_data.h
+++ b/chrome/updater/persisted_data.h
@@ -74,9 +74,14 @@
   std::string GetAP(const std::string& id) const;
   void SetAP(const std::string& id, const std::string& ap);
 
-  // These functions set the client-regulated-counting data for the specified
-  // id. The functions are for app migration only.
+  // These functions get/set the client-regulated-counting data for the
+  // specified id. The functions are for app migration only.
+  // The getters return nullopt when the persisted data does not have the
+  // corresponding value, or any node subtype is not expected along the
+  // path to the target value.
+  absl::optional<int> GetDateLastActive(const std::string& id) const;
   void SetDateLastActive(const std::string& id, int dla);
+  absl::optional<int> GetDateLastRollcall(const std::string& id) const;
   void SetDateLastRollcall(const std::string& id, int dlrc);
 
   // This function sets any non-empty field in the registration request object
@@ -134,6 +139,8 @@
   base::Value::Dict* GetOrCreateAppKey(const std::string& id,
                                        base::Value::Dict& root);
 
+  absl::optional<int> GetInteger(const std::string& id,
+                                 const std::string& key) const;
   void SetInteger(const std::string& id, const std::string& key, int value);
   std::string GetString(const std::string& id, const std::string& key) const;
   void SetString(const std::string& id,
diff --git a/chrome/updater/test/integration_tests_mac.mm b/chrome/updater/test/integration_tests_mac.mm
index 0c41d99..488e416 100644
--- a/chrome/updater/test/integration_tests_mac.mm
+++ b/chrome/updater/test/integration_tests_mac.mm
@@ -298,19 +298,22 @@
 }
 
 void SetupFakeLegacyUpdater(UpdaterScope scope) {
-  base::FilePath test_ticket_store_path;
+  base::FilePath updater_test_data_path;
   ASSERT_TRUE(
-      base::PathService::Get(chrome::DIR_TEST_DATA, &test_ticket_store_path));
-  test_ticket_store_path =
-      test_ticket_store_path.Append(FILE_PATH_LITERAL("updater"))
-          .Append(FILE_PATH_LITERAL("Keystone.legacy.ticketstore"));
+      base::PathService::Get(chrome::DIR_TEST_DATA, &updater_test_data_path));
+  updater_test_data_path =
+      updater_test_data_path.Append(FILE_PATH_LITERAL("updater"));
 
+  base::FilePath keystone_path = GetKeystoneFolderPath(scope).value();
   base::FilePath keystone_ticket_store_path =
-      GetKeystoneFolderPath(scope)->Append(FILE_PATH_LITERAL("TicketStore"));
+      keystone_path.Append(FILE_PATH_LITERAL("TicketStore"));
   ASSERT_TRUE(base::CreateDirectory(keystone_ticket_store_path));
-  ASSERT_TRUE(base::CopyFile(test_ticket_store_path,
-                             keystone_ticket_store_path.Append(
-                                 FILE_PATH_LITERAL("Keystone.ticketstore"))));
+  ASSERT_TRUE(base::CopyFile(
+      updater_test_data_path.AppendASCII("Keystone.legacy.ticketstore"),
+      keystone_ticket_store_path.AppendASCII("Keystone.ticketstore")));
+  ASSERT_TRUE(base::CopyFile(
+      updater_test_data_path.AppendASCII("CountingMetrics.plist"),
+      keystone_path.AppendASCII("CountingMetrics.plist")));
 }
 
 void ExpectLegacyUpdaterMigrated(UpdaterScope scope) {
@@ -336,6 +339,8 @@
   EXPECT_TRUE(persisted_data->GetBrandCode(kKippleApp).empty());
   EXPECT_TRUE(persisted_data->GetBrandPath(kKippleApp).empty());
   EXPECT_TRUE(persisted_data->GetFingerprint(kKippleApp).empty());
+  EXPECT_FALSE(persisted_data->GetDateLastActive(kKippleApp));    // no data.
+  EXPECT_FALSE(persisted_data->GetDateLastRollcall(kKippleApp));  // wrong type.
 
   // App PopularApp.
   const std::string kPopularApp = "com.chromium.PopularApp";
@@ -344,9 +349,21 @@
   EXPECT_EQ(persisted_data->GetExistenceCheckerPath(kPopularApp),
             base::FilePath("/"));
   EXPECT_EQ(persisted_data->GetAP(kPopularApp), "GOOG");
-  EXPECT_TRUE(persisted_data->GetBrandCode(kKippleApp).empty());
+  EXPECT_TRUE(persisted_data->GetBrandCode(kPopularApp).empty());
   EXPECT_EQ(persisted_data->GetBrandPath(kPopularApp), base::FilePath("/"));
   EXPECT_TRUE(persisted_data->GetFingerprint(kPopularApp).empty());
+  EXPECT_EQ(persisted_data->GetDateLastActive(kPopularApp).value(), 5921);
+  EXPECT_EQ(persisted_data->GetDateLastRollcall(kPopularApp).value(), 5922);
+
+  // App CorruptedApp (client-regulated counting data is corrupted).
+  const std::string kCorruptedApp = "com.chromium.CorruptedApp";
+  EXPECT_EQ(persisted_data->GetProductVersion(kCorruptedApp),
+            base::Version("1.2.1"));
+  EXPECT_EQ(persisted_data->GetExistenceCheckerPath(kCorruptedApp),
+            base::FilePath("/"));
+  EXPECT_EQ(persisted_data->GetAP(kCorruptedApp), "canary");
+  EXPECT_FALSE(persisted_data->GetDateLastActive(kCorruptedApp));
+  EXPECT_FALSE(persisted_data->GetDateLastRollcall(kCorruptedApp));
 }
 
 void InstallApp(UpdaterScope scope, const std::string& app_id) {
diff --git a/chrome/updater/test/integration_tests_win.cc b/chrome/updater/test/integration_tests_win.cc
index 3428259..4b7458f 100644
--- a/chrome/updater/test/integration_tests_win.cc
+++ b/chrome/updater/test/integration_tests_win.cc
@@ -97,9 +97,6 @@
 template <typename ComInterface>
 HRESULT CreateLocalServer(GUID clsid,
                           Microsoft::WRL::ComPtr<ComInterface>& server) {
-  // crbug.com/1259178 - there is known race condition between the COM server
-  // shutdown and server start up.
-  base::PlatformThread::Sleep(kCreateUpdaterInstanceDelay);
   return ::CoCreateInstance(clsid, nullptr, CLSCTX_LOCAL_SERVER,
                             IID_PPV_ARGS(&server));
 }
diff --git a/chrome/updater/win/win_constants.cc b/chrome/updater/win/win_constants.cc
index c5e6792..8b0c9eab 100644
--- a/chrome/updater/win/win_constants.cc
+++ b/chrome/updater/win/win_constants.cc
@@ -22,6 +22,8 @@
 const wchar_t kRegValuePV[] = L"pv";
 const wchar_t kRegValueBrandCode[] = L"brand";
 const wchar_t kRegValueAP[] = L"ap";
+const wchar_t kRegValueDateOfLastActivity[] = L"DayOfLastActivity";
+const wchar_t kRegValueDateOfLastRollcall[] = L"DayOfLastRollCall";
 const wchar_t kRegValueName[] = L"name";
 const wchar_t kRegValueUninstallCmdLine[] = L"UninstallCmdLine";
 
diff --git a/chrome/updater/win/win_constants.h b/chrome/updater/win/win_constants.h
index 5d2d002..b696c84 100644
--- a/chrome/updater/win/win_constants.h
+++ b/chrome/updater/win/win_constants.h
@@ -47,6 +47,8 @@
 extern const wchar_t kRegValuePV[];
 extern const wchar_t kRegValueBrandCode[];
 extern const wchar_t kRegValueAP[];
+extern const wchar_t kRegValueDateOfLastActivity[];
+extern const wchar_t kRegValueDateOfLastRollcall[];
 extern const wchar_t kRegValueName[];
 extern const wchar_t kRegValueUninstallCmdLine[];
 
diff --git a/chromeos/ash/components/login/hibernate/OWNERS b/chromeos/ash/components/login/hibernate/OWNERS
index 6ddee49..7ef81749 100644
--- a/chromeos/ash/components/login/hibernate/OWNERS
+++ b/chromeos/ash/components/login/hibernate/OWNERS
@@ -1,3 +1,6 @@
 file://chromeos/ash/components/login/OWNERS
-evgreen@chromium.org
+allenwebb@google.com
 asavery@chromium.org
+bgeffon@chromium.org
+mka@chromium.org
+vovoy@chromium.org
diff --git a/chromeos/ash/components/network/geolocation_handler.cc b/chromeos/ash/components/network/geolocation_handler.cc
index d7407df7..64bfdd5 100644
--- a/chromeos/ash/components/network/geolocation_handler.cc
+++ b/chromeos/ash/components/network/geolocation_handler.cc
@@ -196,9 +196,9 @@
 
   const std::string* age_str = entry.FindString(shill::kGeoAgeProperty);
   if (age_str) {
-    int64_t age_ms;
-    if (base::StringToInt64(*age_str, &age_ms)) {
-      wap.timestamp = base::Time::Now() - base::Milliseconds(age_ms);
+    int64_t age_seconds;
+    if (base::StringToInt64(*age_str, &age_seconds)) {
+      wap.timestamp = base::Time::Now() - base::Seconds(age_seconds);
     }
   }
 
@@ -233,9 +233,9 @@
   // Read time fields into object.
   const std::string* age_str = entry.FindString(shill::kGeoAgeProperty);
   if (age_str) {
-    int64_t age_ms;
-    if (base::StringToInt64(*age_str, &age_ms)) {
-      ct.timestamp = base::Time::Now() - base::Milliseconds(age_ms);
+    int64_t age_seconds;
+    if (base::StringToInt64(*age_str, &age_seconds)) {
+      ct.timestamp = base::Time::Now() - base::Seconds(age_seconds);
     }
   }
 
diff --git a/chromeos/ash/components/phonehub/fake_feature_status_provider.cc b/chromeos/ash/components/phonehub/fake_feature_status_provider.cc
index f525eba..18500ec 100644
--- a/chromeos/ash/components/phonehub/fake_feature_status_provider.cc
+++ b/chromeos/ash/components/phonehub/fake_feature_status_provider.cc
@@ -4,8 +4,7 @@
 
 #include "chromeos/ash/components/phonehub/fake_feature_status_provider.h"
 
-namespace ash {
-namespace phonehub {
+namespace ash::phonehub {
 
 FakeFeatureStatusProvider::FakeFeatureStatusProvider()
     : FakeFeatureStatusProvider(FeatureStatus::kEnabledAndConnected) {}
@@ -28,5 +27,4 @@
   return status_;
 }
 
-}  // namespace phonehub
-}  // namespace ash
+}  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/fake_feature_status_provider.h b/chromeos/ash/components/phonehub/fake_feature_status_provider.h
index d4255a9..bfdd5d7 100644
--- a/chromeos/ash/components/phonehub/fake_feature_status_provider.h
+++ b/chromeos/ash/components/phonehub/fake_feature_status_provider.h
@@ -7,8 +7,7 @@
 
 #include "chromeos/ash/components/phonehub/feature_status_provider.h"
 
-namespace ash {
-namespace phonehub {
+namespace ash::phonehub {
 
 class FakeFeatureStatusProvider : public FeatureStatusProvider {
  public:
@@ -26,7 +25,6 @@
   FeatureStatus status_;
 };
 
-}  // namespace phonehub
-}  // namespace ash
+}  // namespace ash::phonehub
 
 #endif  // CHROMEOS_ASH_COMPONENTS_PHONEHUB_FAKE_FEATURE_STATUS_PROVIDER_H_
diff --git a/chromeos/ash/components/phonehub/fake_ping_manager.cc b/chromeos/ash/components/phonehub/fake_ping_manager.cc
index 9c452e8..35bb564b 100644
--- a/chromeos/ash/components/phonehub/fake_ping_manager.cc
+++ b/chromeos/ash/components/phonehub/fake_ping_manager.cc
@@ -31,4 +31,8 @@
   return is_waiting_for_response_;
 }
 
+void FakePingManager::Reset() {
+  is_waiting_for_response_ = false;
+}
+
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/fake_ping_manager.h b/chromeos/ash/components/phonehub/fake_ping_manager.h
index f396e8d..9b758bd 100644
--- a/chromeos/ash/components/phonehub/fake_ping_manager.h
+++ b/chromeos/ash/components/phonehub/fake_ping_manager.h
@@ -23,6 +23,9 @@
   bool GetIsWaitingForResponse() const;
 
  private:
+  // PingManager:
+  void Reset() override;
+
   int num_ping_requests_ = 0;
   bool is_waiting_for_response_;
 };
diff --git a/chromeos/ash/components/phonehub/feature_status.cc b/chromeos/ash/components/phonehub/feature_status.cc
index 1fe515f..088527b9f 100644
--- a/chromeos/ash/components/phonehub/feature_status.cc
+++ b/chromeos/ash/components/phonehub/feature_status.cc
@@ -4,8 +4,7 @@
 
 #include "chromeos/ash/components/phonehub/feature_status.h"
 
-namespace ash {
-namespace phonehub {
+namespace ash::phonehub {
 
 std::ostream& operator<<(std::ostream& stream, FeatureStatus status) {
   switch (status) {
@@ -41,5 +40,4 @@
   return stream;
 }
 
-}  // namespace phonehub
-}  // namespace ash
+}  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/feature_status.h b/chromeos/ash/components/phonehub/feature_status.h
index 73c8d83f..6836368 100644
--- a/chromeos/ash/components/phonehub/feature_status.h
+++ b/chromeos/ash/components/phonehub/feature_status.h
@@ -7,8 +7,7 @@
 
 #include <ostream>
 
-namespace ash {
-namespace phonehub {
+namespace ash::phonehub {
 
 // Enum representing potential status values for the Phone Hub feature. Note
 // that there is no value representing "prohibited" - when the feature is
@@ -62,7 +61,6 @@
 
 std::ostream& operator<<(std::ostream& stream, FeatureStatus status);
 
-}  // namespace phonehub
-}  // namespace ash
+}  // namespace ash::phonehub
 
 #endif  // CHROMEOS_ASH_COMPONENTS_PHONEHUB_FEATURE_STATUS_H_
diff --git a/chromeos/ash/components/phonehub/feature_status_provider.cc b/chromeos/ash/components/phonehub/feature_status_provider.cc
index afae3ef..25014ff1 100644
--- a/chromeos/ash/components/phonehub/feature_status_provider.cc
+++ b/chromeos/ash/components/phonehub/feature_status_provider.cc
@@ -4,8 +4,7 @@
 
 #include "chromeos/ash/components/phonehub/feature_status_provider.h"
 
-namespace ash {
-namespace phonehub {
+namespace ash::phonehub {
 
 FeatureStatusProvider::FeatureStatusProvider() = default;
 
@@ -24,5 +23,4 @@
     observer.OnFeatureStatusChanged();
 }
 
-}  // namespace phonehub
-}  // namespace ash
+}  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/feature_status_provider.h b/chromeos/ash/components/phonehub/feature_status_provider.h
index dea8f4c..94735ec 100644
--- a/chromeos/ash/components/phonehub/feature_status_provider.h
+++ b/chromeos/ash/components/phonehub/feature_status_provider.h
@@ -9,8 +9,7 @@
 #include "base/observer_list_types.h"
 #include "chromeos/ash/components/phonehub/feature_status.h"
 
-namespace ash {
-namespace phonehub {
+namespace ash::phonehub {
 
 // Provides the current status of Phone Hub and notifies observers when the
 // status changes.
@@ -42,7 +41,6 @@
   base::ObserverList<Observer> observer_list_;
 };
 
-}  // namespace phonehub
-}  // namespace ash
+}  // namespace ash::phonehub
 
 #endif  // CHROMEOS_ASH_COMPONENTS_PHONEHUB_FEATURE_STATUS_PROVIDER_H_
diff --git a/chromeos/ash/components/phonehub/feature_status_provider_impl.cc b/chromeos/ash/components/phonehub/feature_status_provider_impl.cc
index b703fda..9c60bd34 100644
--- a/chromeos/ash/components/phonehub/feature_status_provider_impl.cc
+++ b/chromeos/ash/components/phonehub/feature_status_provider_impl.cc
@@ -16,8 +16,8 @@
 #include "chromeos/ash/components/multidevice/software_feature_state.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 
-namespace ash {
-namespace phonehub {
+namespace ash::phonehub {
+
 namespace {
 
 using multidevice::RemoteDeviceRef;
@@ -298,5 +298,4 @@
   UpdateStatus();
 }
 
-}  // namespace phonehub
-}  // namespace ash
+}  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/feature_status_provider_impl.h b/chromeos/ash/components/phonehub/feature_status_provider_impl.h
index 9ca346d3..553b414 100644
--- a/chromeos/ash/components/phonehub/feature_status_provider_impl.h
+++ b/chromeos/ash/components/phonehub/feature_status_provider_impl.h
@@ -16,8 +16,7 @@
 #include "components/session_manager/core/session_manager_observer.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 
-namespace ash {
-namespace phonehub {
+namespace ash::phonehub {
 
 // FeatureStatusProvider implementation which utilizes DeviceSyncClient,
 // MultiDeviceSetupClient and BluetoothAdapter to determine the current status.
@@ -91,7 +90,6 @@
   base::WeakPtrFactory<FeatureStatusProviderImpl> weak_ptr_factory_{this};
 };
 
-}  // namespace phonehub
-}  // namespace ash
+}  // namespace ash::phonehub
 
 #endif  // CHROMEOS_ASH_COMPONENTS_PHONEHUB_FEATURE_STATUS_PROVIDER_IMPL_H_
diff --git a/chromeos/ash/components/phonehub/feature_status_provider_impl_unittest.cc b/chromeos/ash/components/phonehub/feature_status_provider_impl_unittest.cc
index d9311bf5..63f1c441 100644
--- a/chromeos/ash/components/phonehub/feature_status_provider_impl_unittest.cc
+++ b/chromeos/ash/components/phonehub/feature_status_provider_impl_unittest.cc
@@ -20,8 +20,8 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace ash {
-namespace phonehub {
+namespace ash::phonehub {
+
 namespace {
 
 using multidevice_setup::mojom::Feature;
@@ -620,5 +620,4 @@
   EXPECT_EQ(3u, GetNumObserverCalls());
 }
 
-}  // namespace phonehub
-}  // namespace ash
+}  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/phone_hub_manager_impl.cc b/chromeos/ash/components/phonehub/phone_hub_manager_impl.cc
index f0ffc2d..1b70898 100644
--- a/chromeos/ash/components/phonehub/phone_hub_manager_impl.cc
+++ b/chromeos/ash/components/phonehub/phone_hub_manager_impl.cc
@@ -185,12 +185,13 @@
                     message_receiver_.get(),
                     multidevice_feature_access_manager_.get())
               : nullptr),
-      ping_manager_(
-          features::IsPhoneHubPingOnBubbleOpenEnabled()
-              ? std::make_unique<PingManagerImpl>(connection_manager_.get(),
-                                                  message_receiver_.get(),
-                                                  message_sender_.get())
-              : nullptr) {}
+      ping_manager_(features::IsPhoneHubPingOnBubbleOpenEnabled()
+                        ? std::make_unique<PingManagerImpl>(
+                              connection_manager_.get(),
+                              feature_status_provider_.get(),
+                              message_receiver_.get(),
+                              message_sender_.get())
+                        : nullptr) {}
 
 PhoneHubManagerImpl::~PhoneHubManagerImpl() = default;
 
diff --git a/chromeos/ash/components/phonehub/ping_manager.h b/chromeos/ash/components/phonehub/ping_manager.h
index 2b2f05a..fc403ad 100644
--- a/chromeos/ash/components/phonehub/ping_manager.h
+++ b/chromeos/ash/components/phonehub/ping_manager.h
@@ -19,6 +19,9 @@
 
   virtual void SendPingRequest() = 0;
 
+ private:
+  virtual void Reset() = 0;
+
  protected:
   PingManager() = default;
 };
diff --git a/chromeos/ash/components/phonehub/ping_manager_impl.cc b/chromeos/ash/components/phonehub/ping_manager_impl.cc
index ba251e79..31e57de 100644
--- a/chromeos/ash/components/phonehub/ping_manager_impl.cc
+++ b/chromeos/ash/components/phonehub/ping_manager_impl.cc
@@ -12,6 +12,7 @@
 #include "chromeos/ash/components/phonehub/message_sender_impl.h"
 #include "chromeos/ash/components/phonehub/proto/phonehub_api.pb.h"
 #include "chromeos/ash/services/secure_channel/public/cpp/client/connection_manager.h"
+#include "feature_status.h"
 
 namespace ash::phonehub {
 
@@ -19,19 +20,24 @@
 
 PingManagerImpl::PingManagerImpl(
     secure_channel::ConnectionManager* connection_manager,
+    FeatureStatusProvider* feature_status_provider,
     MessageReceiver* message_receiver,
     MessageSender* message_sender)
     : connection_manager_(connection_manager),
+      feature_status_provider_(feature_status_provider),
       message_receiver_(message_receiver),
       message_sender_(message_sender) {
   DCHECK(connection_manager);
+  DCHECK(feature_status_provider);
   DCHECK(message_receiver);
   DCHECK(message_sender);
 
+  feature_status_provider_->AddObserver(this);
   message_receiver_->AddObserver(this);
 }
 
 PingManagerImpl::~PingManagerImpl() {
+  feature_status_provider_->RemoveObserver(this);
   message_receiver_->RemoveObserver(this);
 }
 
@@ -45,6 +51,17 @@
   UpdatePhoneSupport(phone_status_update.properties());
 }
 
+void PingManagerImpl::OnFeatureStatusChanged() {
+  if (!is_waiting_for_response_ || !IsPingTimeoutTimerRunning()) {
+    return;
+  }
+
+  if (feature_status_provider_->GetStatus() !=
+      FeatureStatus::kEnabledAndConnected) {
+    Reset();
+  }
+}
+
 void PingManagerImpl::OnPingResponseReceived() {
   is_waiting_for_response_ = false;
   ping_timeout_timer_.AbandonAndStop();
@@ -73,6 +90,15 @@
   is_waiting_for_response_ = true;
 }
 
+void PingManagerImpl::Reset() {
+  PA_LOG(INFO) << "Reseting ping state.";
+  is_waiting_for_response_ = false;
+
+  if (IsPingTimeoutTimerRunning()) {
+    ping_timeout_timer_.AbandonAndStop();
+  }
+}
+
 void PingManagerImpl::OnPingTimerFired() {
   PA_LOG(WARNING) << "Ping response never received. Disconnecting.";
   is_waiting_for_response_ = false;
diff --git a/chromeos/ash/components/phonehub/ping_manager_impl.h b/chromeos/ash/components/phonehub/ping_manager_impl.h
index f2fcdee..f59e9a2 100644
--- a/chromeos/ash/components/phonehub/ping_manager_impl.h
+++ b/chromeos/ash/components/phonehub/ping_manager_impl.h
@@ -6,6 +6,8 @@
 #define CHROMEOS_ASH_COMPONENTS_PHONEHUB_PING_MANAGER_IMPL_H_
 
 #include "base/timer/timer.h"
+#include "chromeos/ash/components/phonehub/feature_status.h"
+#include "chromeos/ash/components/phonehub/feature_status_provider.h"
 #include "chromeos/ash/components/phonehub/message_receiver.h"
 #include "chromeos/ash/components/phonehub/ping_manager.h"
 #include "chromeos/ash/components/phonehub/proto/phonehub_api.pb.h"
@@ -18,9 +20,12 @@
 
 class MessageSender;
 
-class PingManagerImpl : public PingManager, public MessageReceiver::Observer {
+class PingManagerImpl : public PingManager,
+                        public MessageReceiver::Observer,
+                        public FeatureStatusProvider::Observer {
  public:
   PingManagerImpl(secure_channel::ConnectionManager* connection_manager,
+                  FeatureStatusProvider* feature_status_provider,
                   MessageReceiver* message_receiver,
                   MessageSender* message_sender);
   ~PingManagerImpl() override;
@@ -32,29 +37,40 @@
       proto::PhoneStatusUpdate phone_status_update) override;
   void OnPingResponseReceived() override;
 
+  // // FeatureStatusProvider::Observer:
+  void OnFeatureStatusChanged() override;
+
   // PingManager:
   void SendPingRequest() override;
 
   bool IsPingTimeoutTimerRunning();
 
-  bool is_ping_supported_by_phone() { return is_ping_supported_by_phone_; }
-  bool is_waiting_for_response() { return is_waiting_for_response_; }
-  void set_is_ping_supported_by_phone(bool is_ping_supported_by_phone) {
+  // Test Helpers
+  bool is_ping_supported_by_phone_for_test() {
+    return is_ping_supported_by_phone_;
+  }
+  bool is_waiting_for_response_for_test() { return is_waiting_for_response_; }
+  void set_is_ping_supported_by_phone_for_test(
+      bool is_ping_supported_by_phone) {
     is_ping_supported_by_phone_ = is_ping_supported_by_phone;
   }
-  void set_is_waiting_for_response(bool is_waiting_for_response) {
+  void set_is_waiting_for_response_for_test(bool is_waiting_for_response) {
     is_waiting_for_response_ = is_waiting_for_response;
   }
 
  private:
   friend class PingManagerImplTest;
 
+  // PingManager:
+  void Reset() override;
+
   void OnPingTimerFired();
   void UpdatePhoneSupport(proto::PhoneProperties phone_properties);
 
   base::OneShotTimer ping_timeout_timer_;
   base::TimeTicks ping_sent_timestamp_;
   secure_channel::ConnectionManager* connection_manager_;
+  FeatureStatusProvider* feature_status_provider_;
   MessageReceiver* message_receiver_;
   MessageSender* message_sender_;
   bool is_ping_supported_by_phone_ = false;
diff --git a/chromeos/ash/components/phonehub/ping_manager_impl_unittest.cc b/chromeos/ash/components/phonehub/ping_manager_impl_unittest.cc
index 3f46a85..acbb7bb 100644
--- a/chromeos/ash/components/phonehub/ping_manager_impl_unittest.cc
+++ b/chromeos/ash/components/phonehub/ping_manager_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/phonehub/fake_feature_status_provider.h"
 #include "chromeos/ash/components/phonehub/fake_message_receiver.h"
 #include "chromeos/ash/components/phonehub/fake_message_sender.h"
 #include "chromeos/ash/components/phonehub/proto/phonehub_api.pb.h"
@@ -41,26 +42,76 @@
     fake_connection_manager_ =
         std::make_unique<secure_channel::FakeConnectionManager>();
     ping_manager_ = std::make_unique<PingManagerImpl>(
-        fake_connection_manager_.get(), &fake_message_receiver_,
-        &fake_message_sender_);
+        fake_connection_manager_.get(), &fake_feature_status_provider_,
+        &fake_message_receiver_, &fake_message_sender_);
 
-    ping_manager_->set_is_ping_supported_by_phone(true);
+    SetIsPingSupportedByPhone(true);
+  }
+
+  void TearDown() override {
+    ping_manager_.reset();
+    fake_connection_manager_.reset();
+  }
+
+  PingManagerImpl* ping_manager() { return ping_manager_.get(); }
+
+  bool IsPingSupportedByPhone() {
+    return ping_manager_->is_ping_supported_by_phone_for_test();
+  }
+
+  bool IsWaitingForResponse() {
+    return ping_manager_->is_waiting_for_response_for_test();
+  }
+
+  void SetIsPingSupportedByPhone(bool is_supported) {
+    ping_manager_->set_is_ping_supported_by_phone_for_test(is_supported);
+  }
+
+  void SetIsWaitingForResponse(bool is_waiting) {
+    ping_manager_->set_is_waiting_for_response_for_test(is_waiting);
+  }
+
+  void SetFeatureStatus(FeatureStatus feature_status) {
+    fake_feature_status_provider_.SetStatus(feature_status);
+  }
+
+  void NotifyPhoneStatusSnapshotReceived(
+      proto::PhoneStatusSnapshot status_snapshot) {
+    fake_message_receiver_.NotifyPhoneStatusSnapshotReceived(status_snapshot);
+  }
+
+  void NotifyPhoneStatusUpdateReceived(proto::PhoneStatusUpdate status_update) {
+    fake_message_receiver_.NotifyPhoneStatusUpdateReceived(status_update);
+  }
+
+  void NotifyPingResponseReceived() {
+    fake_message_receiver_.NotifyPingResponseReceived();
+  }
+
+  size_t GetPingRequestCallCount() {
+    return fake_message_sender_.GetPingRequestCallCount();
+  }
+
+  size_t GetNumDisconnectCalls() {
+    return fake_connection_manager_->num_disconnect_calls();
   }
 
   base::test::TaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
   base::test::ScopedFeatureList feature_list_;
 
+ private:
   std::unique_ptr<secure_channel::FakeConnectionManager>
       fake_connection_manager_;
   std::unique_ptr<PingManagerImpl> ping_manager_;
+  FakeFeatureStatusProvider fake_feature_status_provider_;
   FakeMessageReceiver fake_message_receiver_;
   FakeMessageSender fake_message_sender_;
 };
 
 TEST_F(PingManagerImplTest, OnPhoneStatusSnapshotReceivedPingSupported) {
-  ping_manager_->set_is_ping_supported_by_phone(false);
-  EXPECT_FALSE(ping_manager_->is_ping_supported_by_phone());
+  SetIsPingSupportedByPhone(false);
+  EXPECT_FALSE(IsPingSupportedByPhone());
 
   auto config = std::make_unique<proto::FeatureSetupConfig>();
   config->set_ping_capability_supported(true);
@@ -74,9 +125,9 @@
       expected_phone_properties.release());
 
   // Simulate receiving a message
-  fake_message_receiver_.NotifyPhoneStatusSnapshotReceived(expected_snapshot);
+  NotifyPhoneStatusSnapshotReceived(expected_snapshot);
 
-  EXPECT_TRUE(ping_manager_->is_ping_supported_by_phone());
+  EXPECT_TRUE(IsPingSupportedByPhone());
 }
 
 TEST_F(PingManagerImplTest, OnPhoneStatusSnapshotReceivedPingNotSupported) {
@@ -92,14 +143,14 @@
       expected_phone_properties.release());
 
   // Simulate receiving a message
-  fake_message_receiver_.NotifyPhoneStatusSnapshotReceived(expected_snapshot);
+  NotifyPhoneStatusSnapshotReceived(expected_snapshot);
 
-  EXPECT_FALSE(ping_manager_->is_ping_supported_by_phone());
+  EXPECT_FALSE(IsPingSupportedByPhone());
 }
 
 TEST_F(PingManagerImplTest, OnPhoneStatusUpdateReceivedPingSupported) {
-  ping_manager_->set_is_ping_supported_by_phone(false);
-  EXPECT_FALSE(ping_manager_->is_ping_supported_by_phone());
+  SetIsPingSupportedByPhone(false);
+  EXPECT_FALSE(IsPingSupportedByPhone());
 
   auto config = std::make_unique<proto::FeatureSetupConfig>();
   config->set_ping_capability_supported(true);
@@ -112,9 +163,9 @@
   expected_update.set_allocated_properties(expected_phone_properties.release());
 
   // Simulate receiving a message
-  fake_message_receiver_.NotifyPhoneStatusUpdateReceived(expected_update);
+  NotifyPhoneStatusUpdateReceived(expected_update);
 
-  EXPECT_TRUE(ping_manager_->is_ping_supported_by_phone());
+  EXPECT_TRUE(IsPingSupportedByPhone());
 }
 
 TEST_F(PingManagerImplTest, OnPhoneStatusUpdateReceivedPingNotSupported) {
@@ -129,9 +180,9 @@
   expected_update.set_allocated_properties(expected_phone_properties.release());
 
   // Simulate receiving a message
-  fake_message_receiver_.NotifyPhoneStatusUpdateReceived(expected_update);
+  NotifyPhoneStatusUpdateReceived(expected_update);
 
-  EXPECT_FALSE(ping_manager_->is_ping_supported_by_phone());
+  EXPECT_FALSE(IsPingSupportedByPhone());
 }
 
 TEST_F(PingManagerImplTest, OnPhoneStatusUpdateReceivedNoFeatureSetupConfig) {
@@ -141,107 +192,141 @@
   expected_update.set_allocated_properties(expected_phone_properties.release());
 
   // Simulate receiving a message
-  fake_message_receiver_.NotifyPhoneStatusUpdateReceived(expected_update);
+  NotifyPhoneStatusUpdateReceived(expected_update);
 
-  EXPECT_FALSE(ping_manager_->is_ping_supported_by_phone());
+  EXPECT_FALSE(IsPingSupportedByPhone());
+}
+
+TEST_F(PingManagerImplTest, OnFeatureStatusChanged) {
+  ping_manager()->SendPingRequest();
+  EXPECT_TRUE(IsWaitingForResponse());
+  EXPECT_TRUE(ping_manager()->IsPingTimeoutTimerRunning());
+
+  SetFeatureStatus(FeatureStatus::kEnabledAndConnected);
+
+  EXPECT_TRUE(IsWaitingForResponse());
+  EXPECT_TRUE(ping_manager()->IsPingTimeoutTimerRunning());
+
+  SetFeatureStatus(FeatureStatus::kEnabledButDisconnected);
+
+  EXPECT_FALSE(IsWaitingForResponse());
+  EXPECT_FALSE(ping_manager()->IsPingTimeoutTimerRunning());
+
+  ping_manager()->SendPingRequest();
+  EXPECT_TRUE(IsWaitingForResponse());
+  EXPECT_TRUE(ping_manager()->IsPingTimeoutTimerRunning());
+
+  SetFeatureStatus(FeatureStatus::kEnabledAndConnecting);
+
+  EXPECT_FALSE(IsWaitingForResponse());
+  EXPECT_FALSE(ping_manager()->IsPingTimeoutTimerRunning());
+
+  ping_manager()->SendPingRequest();
+  EXPECT_TRUE(IsWaitingForResponse());
+  EXPECT_TRUE(ping_manager()->IsPingTimeoutTimerRunning());
+
+  SetFeatureStatus(FeatureStatus::kEnabledAndConnected);
+
+  EXPECT_TRUE(IsWaitingForResponse());
+  EXPECT_TRUE(ping_manager()->IsPingTimeoutTimerRunning());
 }
 
 TEST_F(PingManagerImplTest, OnPingResponseReceived) {
   base::HistogramTester histogram_tester;
 
-  ping_manager_->set_is_waiting_for_response(true);
-  EXPECT_TRUE(ping_manager_->is_waiting_for_response());
+  SetIsWaitingForResponse(true);
+  EXPECT_TRUE(IsWaitingForResponse());
 
   // Simulate receiving a message
-  fake_message_receiver_.NotifyPingResponseReceived();
+  NotifyPingResponseReceived();
 
   histogram_tester.ExpectBucketCount(kPingManagerPingResultHistogramName, true,
                                      1);
 
-  EXPECT_FALSE(ping_manager_->is_waiting_for_response());
-  EXPECT_FALSE(ping_manager_->IsPingTimeoutTimerRunning());
+  EXPECT_FALSE(IsWaitingForResponse());
+  EXPECT_FALSE(ping_manager()->IsPingTimeoutTimerRunning());
 }
 
 TEST_F(PingManagerImplTest, SendPingRequest) {
   proto::PingRequest request;
 
-  ping_manager_->SendPingRequest();
+  ping_manager()->SendPingRequest();
 
-  EXPECT_EQ(1u, fake_message_sender_.GetPingRequestCallCount());
-  EXPECT_TRUE(ping_manager_->is_waiting_for_response());
-  EXPECT_TRUE(ping_manager_->IsPingTimeoutTimerRunning());
+  EXPECT_EQ(1u, GetPingRequestCallCount());
+  EXPECT_TRUE(IsWaitingForResponse());
+  EXPECT_TRUE(ping_manager()->IsPingTimeoutTimerRunning());
 }
 
 TEST_F(PingManagerImplTest, SendPingRequestNotSupported) {
-  ping_manager_->set_is_ping_supported_by_phone(false);
+  SetIsPingSupportedByPhone(false);
 
-  ping_manager_->SendPingRequest();
+  ping_manager()->SendPingRequest();
 
-  EXPECT_EQ(0u, fake_message_sender_.GetPingRequestCallCount());
-  EXPECT_FALSE(ping_manager_->is_waiting_for_response());
-  EXPECT_FALSE(ping_manager_->IsPingTimeoutTimerRunning());
+  EXPECT_EQ(0u, GetPingRequestCallCount());
+  EXPECT_FALSE(IsWaitingForResponse());
+  EXPECT_FALSE(ping_manager()->IsPingTimeoutTimerRunning());
 }
 
 TEST_F(PingManagerImplTest, SendPingRequestWaitingForResponse) {
-  ping_manager_->set_is_waiting_for_response(true);
+  SetIsWaitingForResponse(true);
 
-  ping_manager_->SendPingRequest();
+  ping_manager()->SendPingRequest();
 
-  EXPECT_EQ(0u, fake_message_sender_.GetPingRequestCallCount());
-  EXPECT_TRUE(ping_manager_->is_waiting_for_response());
-  EXPECT_FALSE(ping_manager_->IsPingTimeoutTimerRunning());
+  EXPECT_EQ(0u, GetPingRequestCallCount());
+  EXPECT_TRUE(IsWaitingForResponse());
+  EXPECT_FALSE(ping_manager()->IsPingTimeoutTimerRunning());
 }
 
 TEST_F(PingManagerImplTest, OnPingTimerFired) {
   base::HistogramTester histogram_tester;
 
-  EXPECT_EQ(0u, fake_connection_manager_->num_disconnect_calls());
-  EXPECT_FALSE(ping_manager_->is_waiting_for_response());
-  EXPECT_FALSE(ping_manager_->IsPingTimeoutTimerRunning());
+  EXPECT_EQ(0u, GetNumDisconnectCalls());
+  EXPECT_FALSE(IsWaitingForResponse());
+  EXPECT_FALSE(ping_manager()->IsPingTimeoutTimerRunning());
 
-  ping_manager_->SendPingRequest();
+  ping_manager()->SendPingRequest();
 
-  EXPECT_EQ(0u, fake_connection_manager_->num_disconnect_calls());
-  EXPECT_EQ(1u, fake_message_sender_.GetPingRequestCallCount());
-  EXPECT_TRUE(ping_manager_->is_waiting_for_response());
-  EXPECT_TRUE(ping_manager_->IsPingTimeoutTimerRunning());
+  EXPECT_EQ(0u, GetNumDisconnectCalls());
+  EXPECT_EQ(1u, GetPingRequestCallCount());
+  EXPECT_TRUE(IsWaitingForResponse());
+  EXPECT_TRUE(ping_manager()->IsPingTimeoutTimerRunning());
 
   task_environment_.FastForwardBy(base::Minutes(2));
 
   histogram_tester.ExpectBucketCount(kPingManagerPingResultHistogramName, false,
                                      1);
 
-  EXPECT_EQ(1u, fake_connection_manager_->num_disconnect_calls());
-  EXPECT_FALSE(ping_manager_->is_waiting_for_response());
-  EXPECT_FALSE(ping_manager_->IsPingTimeoutTimerRunning());
+  EXPECT_EQ(1u, GetNumDisconnectCalls());
+  EXPECT_FALSE(IsWaitingForResponse());
+  EXPECT_FALSE(ping_manager()->IsPingTimeoutTimerRunning());
 }
 
 TEST_F(PingManagerImplTest, SendAndReceivePing) {
   base::HistogramTester histogram_tester;
 
-  EXPECT_FALSE(ping_manager_->is_waiting_for_response());
-  EXPECT_FALSE(ping_manager_->IsPingTimeoutTimerRunning());
+  EXPECT_FALSE(IsWaitingForResponse());
+  EXPECT_FALSE(ping_manager()->IsPingTimeoutTimerRunning());
 
-  ping_manager_->SendPingRequest();
+  ping_manager()->SendPingRequest();
 
-  EXPECT_EQ(0u, fake_connection_manager_->num_disconnect_calls());
-  EXPECT_EQ(1u, fake_message_sender_.GetPingRequestCallCount());
-  EXPECT_TRUE(ping_manager_->is_waiting_for_response());
-  EXPECT_TRUE(ping_manager_->IsPingTimeoutTimerRunning());
+  EXPECT_EQ(0u, GetNumDisconnectCalls());
+  EXPECT_EQ(1u, GetPingRequestCallCount());
+  EXPECT_TRUE(IsWaitingForResponse());
+  EXPECT_TRUE(ping_manager()->IsPingTimeoutTimerRunning());
 
   task_environment_.FastForwardBy(kLatencyDelta);
 
   // Simulate receiving a message.
-  fake_message_receiver_.NotifyPingResponseReceived();
+  NotifyPingResponseReceived();
 
   histogram_tester.ExpectTimeBucketCount(kPingManagerLatencyHistogramName,
                                          kLatencyDelta, 1);
   histogram_tester.ExpectBucketCount(kPingManagerPingResultHistogramName, true,
                                      1);
 
-  EXPECT_FALSE(ping_manager_->is_waiting_for_response());
-  EXPECT_FALSE(ping_manager_->IsPingTimeoutTimerRunning());
-  EXPECT_EQ(0u, fake_connection_manager_->num_disconnect_calls());
+  EXPECT_FALSE(IsWaitingForResponse());
+  EXPECT_FALSE(ping_manager()->IsPingTimeoutTimerRunning());
+  EXPECT_EQ(0u, GetNumDisconnectCalls());
 }
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl.cc b/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl.cc
index 33a44d81..ce836ab 100644
--- a/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl.cc
+++ b/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl.cc
@@ -61,6 +61,31 @@
     device::BluetoothAdapter* adapter,
     bool powered) {
   NotifyAdapterStateChanged();
+
+  // No action is required if the adapter state changed without
+  // AdapterStateController interaction.
+  if (in_progress_state_change_ == PowerStateChange::kNoChange) {
+    return;
+  }
+
+  // No action is required if the state change is unrelated to the in-progress
+  // state change request.
+  if (powered != (in_progress_state_change_ == PowerStateChange::kEnable)) {
+    return;
+  }
+
+  // The adapter state changed to that requested by the in-progress state
+  // change. Handle the change here rather than the SetPowered() success
+  // callback to avoid timing issues (b/270447662).
+  BLUETOOTH_LOG(EVENT) << "Bluetooth " << (powered ? "enabled" : "disabled")
+                       << " successfully";
+  in_progress_state_change_ = PowerStateChange::kNoChange;
+  device::PoweredStateOperation power_operation =
+      powered ? device::PoweredStateOperation::kEnable
+              : device::PoweredStateOperation::kDisable;
+  device::RecordPoweredStateOperationResult(power_operation, /*success=*/true);
+
+  AttemptQueuedStateChange();
 }
 
 void AdapterStateControllerImpl::AttemptQueuedStateChange() {
@@ -118,8 +143,9 @@
                        << " Bluetooth";
   bluetooth_adapter_->SetPowered(
       enabled,
-      base::BindOnce(&AdapterStateControllerImpl::OnSetPoweredSuccess,
-                     weak_ptr_factory_.GetWeakPtr(), enabled),
+      // Power state successfully updating is handled in AdapterPoweredChanged()
+      // (see b/274973520).
+      base::DoNothing(),
       base::BindOnce(&AdapterStateControllerImpl::OnSetPoweredError,
                      weak_ptr_factory_.GetWeakPtr(), enabled));
   device::RecordPoweredState(enabled);
@@ -127,18 +153,6 @@
   NotifyAdapterStateChanged();
 }
 
-void AdapterStateControllerImpl::OnSetPoweredSuccess(bool enabled) {
-  BLUETOOTH_LOG(EVENT) << "Bluetooth " << (enabled ? "enabled" : "disabled")
-                       << " successfully";
-  in_progress_state_change_ = PowerStateChange::kNoChange;
-  device::PoweredStateOperation power_operation =
-      enabled ? device::PoweredStateOperation::kEnable
-              : device::PoweredStateOperation::kDisable;
-  device::RecordPoweredStateOperationResult(power_operation, /*success=*/true);
-
-  AttemptQueuedStateChange();
-}
-
 void AdapterStateControllerImpl::OnSetPoweredError(bool enabled) {
   BLUETOOTH_LOG(ERROR) << "Error attempting to "
                        << (enabled ? "enable" : "disable") << " Bluetooth";
diff --git a/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl.h b/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl.h
index 8fb211b..5ef19b3 100644
--- a/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl.h
+++ b/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl.h
@@ -43,7 +43,6 @@
   void AttemptQueuedStateChange();
   void AttemptSetEnabled(bool enabled);
 
-  void OnSetPoweredSuccess(bool enabled);
   void OnSetPoweredError(bool enabled);
 
   scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_;
diff --git a/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl_unittest.cc b/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl_unittest.cc
index 7847d37..b85cb2a 100644
--- a/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl_unittest.cc
+++ b/chromeos/ash/services/bluetooth_config/adapter_state_controller_impl_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/containers/queue.h"
 #include "base/functional/callback.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
@@ -35,7 +36,9 @@
 
 }  // namespace
 
-class AdapterStateControllerImplTest : public testing::Test {
+class AdapterStateControllerImplTest
+    : public testing::Test,
+      public testing::WithParamInterface<bool> {
  protected:
   AdapterStateControllerImplTest() = default;
   AdapterStateControllerImplTest(const AdapterStateControllerImplTest&) =
@@ -60,8 +63,9 @@
                    base::OnceClosure error_callback) {
               EXPECT_FALSE(pending_power_state_.has_value());
               pending_power_state_ = powered;
-              set_powered_success_callback_ = std::move(success_callback);
-              set_powered_error_callback_ = std::move(error_callback);
+              set_powered_success_callbacks_.emplace(
+                  std::move(success_callback));
+              set_powered_error_callbacks_.emplace(std::move(error_callback));
             }));
 
     adapter_state_controller_ =
@@ -107,15 +111,33 @@
     EXPECT_EQ(expected_pending_state, *pending_power_state_);
     pending_power_state_.reset();
 
+    base::OnceClosure success_callback =
+        std::move(set_powered_success_callbacks_.front());
+    set_powered_success_callbacks_.pop();
+    base::OnceClosure error_callback =
+        std::move(set_powered_error_callbacks_.front());
+    set_powered_error_callbacks_.pop();
+
     if (success) {
-      SetAdapterPoweredState(expected_pending_state);
-      std::move(set_powered_success_callback_).Run();
-      set_powered_error_callback_.Reset();
+      // Depending on if BlueZ or Floss is being used, SetAdapterPoweredState()
+      // gets called before or after the success callback. Add coverage to test
+      // both cases (b/274973520).
+      bool is_floss_enabled = GetParam();
+      if (!is_floss_enabled) {
+        SetAdapterPoweredState(expected_pending_state);
+      }
+
+      std::move(success_callback).Run();
+      error_callback.Reset();
+
+      if (is_floss_enabled) {
+        SetAdapterPoweredState(expected_pending_state);
+      }
       return;
     }
 
-    std::move(set_powered_error_callback_).Run();
-    set_powered_success_callback_.Reset();
+    std::move(error_callback).Run();
+    success_callback.Reset();
   }
 
   size_t GetNumObserverEvents() const { return fake_observer_.num_calls(); }
@@ -129,8 +151,8 @@
   bool is_adapter_powered_ = true;
 
   absl::optional<bool> pending_power_state_;
-  base::OnceClosure set_powered_success_callback_;
-  base::OnceClosure set_powered_error_callback_;
+  base::queue<base::OnceClosure> set_powered_success_callbacks_;
+  base::queue<base::OnceClosure> set_powered_error_callbacks_;
 
   scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
   FakeObserver fake_observer_;
@@ -138,7 +160,11 @@
   std::unique_ptr<AdapterStateController> adapter_state_controller_;
 };
 
-TEST_F(AdapterStateControllerImplTest, StateChangesFromOutsideClass) {
+// Boolean parameter indicating whether to simulate Floss
+// (floss::features::IsFlossEnabled()) adapter behavior or not.
+INSTANTIATE_TEST_SUITE_P(All, AdapterStateControllerImplTest, testing::Bool());
+
+TEST_P(AdapterStateControllerImplTest, StateChangesFromOutsideClass) {
   EXPECT_EQ(mojom::BluetoothSystemState::kEnabled, GetAdapterState());
 
   SetAdapterPoweredState(/*powered=*/false);
@@ -150,7 +176,7 @@
   EXPECT_EQ(2u, GetNumObserverEvents());
 }
 
-TEST_F(AdapterStateControllerImplTest, SetBluetoothEnabledState) {
+TEST_P(AdapterStateControllerImplTest, SetBluetoothEnabledState) {
   EXPECT_EQ(mojom::BluetoothSystemState::kEnabled, GetAdapterState());
 
   histogram_tester.ExpectBucketCount("Bluetooth.ChromeOS.PoweredState", false,
@@ -195,7 +221,7 @@
       "Bluetooth.ChromeOS.PoweredState.Enable.Result", true, 1);
 }
 
-TEST_F(AdapterStateControllerImplTest, SetBluetoothEnabledState_Error) {
+TEST_P(AdapterStateControllerImplTest, SetBluetoothEnabledState_Error) {
   EXPECT_EQ(mojom::BluetoothSystemState::kEnabled, GetAdapterState());
 
   histogram_tester.ExpectBucketCount("Bluetooth.ChromeOS.PoweredState", false,
@@ -222,7 +248,7 @@
       "Bluetooth.ChromeOS.PoweredState.Enable.Result", true, 0);
 }
 
-TEST_F(AdapterStateControllerImplTest, MultiplePowerChanges_SameChange) {
+TEST_P(AdapterStateControllerImplTest, MultiplePowerChanges_SameChange) {
   EXPECT_EQ(mojom::BluetoothSystemState::kEnabled, GetAdapterState());
 
   histogram_tester.ExpectBucketCount("Bluetooth.ChromeOS.PoweredState", false,
@@ -270,7 +296,7 @@
       "Bluetooth.ChromeOS.PoweredState.Enable.Result", true, 0);
 }
 
-TEST_F(AdapterStateControllerImplTest, MultiplePowerChanges_DifferentChange) {
+TEST_P(AdapterStateControllerImplTest, MultiplePowerChanges_DifferentChange) {
   EXPECT_EQ(mojom::BluetoothSystemState::kEnabled, GetAdapterState());
 
   histogram_tester.ExpectBucketCount("Bluetooth.ChromeOS.PoweredState", false,
@@ -326,7 +352,7 @@
 }
 
 // Regression test for b/219596007.
-TEST_F(AdapterStateControllerImplTest,
+TEST_P(AdapterStateControllerImplTest,
        MultiplePowerChanges_AdapterChangesAvailability) {
   EXPECT_EQ(mojom::BluetoothSystemState::kEnabled, GetAdapterState());
 
diff --git a/chromeos/ui/frame/BUILD.gn b/chromeos/ui/frame/BUILD.gn
index 77c567e..e0903b0 100644
--- a/chromeos/ui/frame/BUILD.gn
+++ b/chromeos/ui/frame/BUILD.gn
@@ -70,6 +70,7 @@
 
   deps = [
     "//base",
+    "//chromeos/constants/",
     "//chromeos/strings:strings_grit",
     "//chromeos/ui/base",
     "//chromeos/ui/vector_icons",
diff --git a/chromeos/ui/frame/highlight_border_overlay.cc b/chromeos/ui/frame/highlight_border_overlay.cc
index 601ccc0..69a111f7 100644
--- a/chromeos/ui/frame/highlight_border_overlay.cc
+++ b/chromeos/ui/frame/highlight_border_overlay.cc
@@ -5,6 +5,7 @@
 #include "chromeos/ui/frame/highlight_border_overlay.h"
 
 #include "base/memory/raw_ptr.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "chromeos/ui/base/chromeos_ui_constants.h"
 #include "chromeos/ui/base/tablet_state.h"
 #include "chromeos/ui/base/window_properties.h"
@@ -25,8 +26,11 @@
 // sources for highlight border.
 constexpr size_t kMaxImageSourceNum = 6;
 
-constexpr views::HighlightBorder::Type kBorderType =
-    views::HighlightBorder::Type::kHighlightBorder3;
+views::HighlightBorder::Type GetBorderType() {
+  return chromeos::features::IsJellyrollEnabled()
+             ? views::HighlightBorder::Type::kHighlightBorderOnShadow
+             : views::HighlightBorder::Type::kHighlightBorder3;
+}
 
 int GetRoundedCornerRadius(chromeos::WindowStateType type) {
   if (type == chromeos::WindowStateType::kPip)
@@ -55,7 +59,7 @@
   void Draw(gfx::Canvas* canvas) override {
     views::HighlightBorder::PaintBorderToCanvas(
         canvas, highlight_color_, border_color_, gfx::Rect(size()),
-        gfx::RoundedCornersF(corner_radius_), kBorderType,
+        gfx::RoundedCornersF(corner_radius_), GetBorderType(),
         /*use_light_colors=*/false);
   }
 
@@ -182,9 +186,9 @@
   // Get the highlight border features.
   const views::View& view = *(widget_->GetContentsView());
   SkColor highlight_color = views::HighlightBorder::GetHighlightColor(
-      view, kBorderType, /*use_light_colors=*/false);
+      view, GetBorderType(), /*use_light_colors=*/false);
   SkColor border_color = views::HighlightBorder::GetBorderColor(
-      view, kBorderType, /*use_light_colors=*/false);
+      view, GetBorderType(), /*use_light_colors=*/false);
   HighlightBorderFeatureKey key(highlight_color, border_color,
                                 rounded_corner_radius_);
 
diff --git a/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.cc b/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.cc
index 59b509a..bc33d04 100644
--- a/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.cc
+++ b/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.cc
@@ -5,6 +5,7 @@
 #include "chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.h"
 
 #include "base/metrics/user_metrics.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "chromeos/ui/base/tablet_state.h"
 #include "chromeos/ui/wm/features.h"
@@ -96,7 +97,10 @@
   contents_view->SetBackground(views::CreateThemedRoundedRectBackground(
       ui::kColorSysSurface3, corner_radius));
   contents_view->SetBorder(std::make_unique<views::HighlightBorder>(
-      corner_radius, views::HighlightBorder::Type::kHighlightBorder1,
+      corner_radius,
+      chromeos::features::IsJellyrollEnabled()
+          ? views::HighlightBorder::Type::kHighlightBorderOnShadow
+          : views::HighlightBorder::Type::kHighlightBorder1,
       /*use_light_colors=*/false));
 
   widget->SetContentsView(std::move(contents_view));
diff --git a/components/browser_sync/sync_api_component_factory_impl.cc b/components/browser_sync/sync_api_component_factory_impl.cc
index 20e68c3..60e415b8 100644
--- a/components/browser_sync/sync_api_component_factory_impl.cc
+++ b/components/browser_sync/sync_api_component_factory_impl.cc
@@ -483,6 +483,18 @@
         CreateForwardingControllerDelegate(syncer::USER_CONSENTS)));
   }
 
+#if !BUILDFLAG(IS_ANDROID) || !BUILDFLAG(IS_IOS)
+  if (base::FeatureList::IsEnabled(syncer::kSyncWebauthnCredentials) &&
+      !disabled_types.Has(syncer::WEBAUTHN_CREDENTIAL)) {
+    controllers.push_back(std::make_unique<ModelTypeController>(
+        syncer::WEBAUTHN_CREDENTIAL,
+        /*delegate_for_full_sync_mode=*/
+        CreateForwardingControllerDelegate(syncer::WEBAUTHN_CREDENTIAL),
+        /*delegate_for_transport_mode=*/
+        CreateForwardingControllerDelegate(syncer::WEBAUTHN_CREDENTIAL)));
+  }
+#endif
+
   return controllers;
 }
 
diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp
index c9fe9f3..c4666f75 100644
--- a/components/browser_ui/strings/android/site_settings.grdp
+++ b/components/browser_ui/strings/android/site_settings.grdp
@@ -586,8 +586,8 @@
   <message name="IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED" desc="Summary text explaining that desktop view of sites will be requested by default.">
     Request desktop view
   </message>
-  <message name="IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED" desc="Summary text explaining that mobile view of sites will be requested by default and that it is the recommended setting.">
-    Request mobile view (recommended)
+  <message name="IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED" desc="Summary text explaining that mobile view of sites will be requested by default.">
+    Request mobile view
   </message>
   <message name="IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED_LIST" desc="Summary text explaining that desktop view of sites will be requested by default. To be shown in the list of permission categories.">
     On
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED.png.sha1
index e3d945b..fba8a28 100644
--- a/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED.png.sha1
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_ALLOWED.png.sha1
@@ -1 +1 @@
-496bb20affed17683e8757f17db4426a9f825999
\ No newline at end of file
+e078669437c8e14254999b3096a75bff3b327474
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED.png.sha1
index 58a4e24..882235ed 100644
--- a/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED.png.sha1
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_WEBSITE_SETTINGS_CATEGORY_DESKTOP_SITE_BLOCKED.png.sha1
@@ -1 +1 @@
-d1b79e79eb5cc87b9bb97ab79469a0c8bcc5f2b6
\ No newline at end of file
+15e510476e8df1bbe40cd6a725e1724c8c197706
\ No newline at end of file
diff --git a/components/enterprise/common/proto/connectors.proto b/components/enterprise/common/proto/connectors.proto
index a53feaf..8a78c35d 100644
--- a/components/enterprise/common/proto/connectors.proto
+++ b/components/enterprise/common/proto/connectors.proto
@@ -58,6 +58,19 @@
 
   // URL of the tab. Only different from `url` for downloads.
   optional string tab_url = 10;
+
+  // Empty for non-print actions.
+  message PrintMetadata {
+    optional string printer_name = 1;
+
+    enum PrinterType {
+      UNKNOWN = 0;
+      CLOUD = 1;
+      LOCAL = 2;
+    }
+    optional PrinterType printer_type = 2;
+  }
+  optional PrintMetadata print_metadata = 11;
 }
 
 message ClientMetadata {
diff --git a/components/enterprise/common/proto/connectors_unittest.cc b/components/enterprise/common/proto/connectors_unittest.cc
index 267442f..32bba78da 100644
--- a/components/enterprise/common/proto/connectors_unittest.cc
+++ b/components/enterprise/common/proto/connectors_unittest.cc
@@ -56,4 +56,19 @@
   EXPECT_EQ((int)ChromiumRule::BLOCK, (int)SdkRule::BLOCK);
 }
 
+using ChromiumPrintMetadata =
+    enterprise_connectors::ContentMetaData::PrintMetadata;
+using SdkPrintMetadata = content_analysis::sdk::ContentMetaData::PrintMetadata;
+
+TEST(EnterpriseConnectorsProtoTest, PrintTypeEnum) {
+  EXPECT_EQ(ChromiumPrintMetadata::PrinterType_ARRAYSIZE, 3);
+  EXPECT_EQ(ChromiumPrintMetadata::PrinterType_ARRAYSIZE,
+            SdkPrintMetadata::PrinterType_ARRAYSIZE);
+
+  EXPECT_EQ((int)ChromiumPrintMetadata::UNKNOWN,
+            (int)SdkPrintMetadata::UNKNOWN);
+  EXPECT_EQ((int)ChromiumPrintMetadata::CLOUD, (int)SdkPrintMetadata::CLOUD);
+  EXPECT_EQ((int)ChromiumPrintMetadata::LOCAL, (int)SdkPrintMetadata::LOCAL);
+}
+
 }  // namespace enterprise_connectors
diff --git a/components/history_clusters/core/config.cc b/components/history_clusters/core/config.cc
index 51b8d1f..b3e4305 100644
--- a/components/history_clusters/core/config.cc
+++ b/components/history_clusters/core/config.cc
@@ -245,7 +245,7 @@
     DCHECK_LE(entity_relevance_threshold, 100);
 
     content_visibility_threshold = GetFieldTrialParamByFeatureAsDouble(
-        features::kOnDeviceClustering, "content_visibility_threshold", 0.7);
+        features::kOnDeviceClustering, "content_visibility_threshold", 0.5);
     // Ensure that the value is [0.0 and 1.0].
     DCHECK_GE(content_visibility_threshold, 0.0f);
     DCHECK_LE(content_visibility_threshold, 1.0f);
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java
index 456d404..dc857a23 100644
--- a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java
+++ b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java
@@ -224,7 +224,7 @@
         queueManager.enqueueMessage(m3, m3, SCOPE_INSTANCE_ID_A, false);
 
         var dismissed = HistogramWatcher.newBuilder()
-                                .expectIntRecords("Android.Messages.Dismissed.TestMessage",
+                                .expectIntRecordTimes("Android.Messages.Dismissed.TestMessage",
                                         DismissReason.ACTIVITY_DESTROYED, 3)
                                 .build();
         queueManager.dismissAllMessages(DismissReason.ACTIVITY_DESTROYED);
diff --git a/components/metrics/serialization/serialization_utils.cc b/components/metrics/serialization/serialization_utils.cc
index c14c75c..62c64683 100644
--- a/components/metrics/serialization/serialization_utils.cc
+++ b/components/metrics/serialization/serialization_utils.cc
@@ -89,6 +89,9 @@
 
 }  // namespace
 
+// This value is used as a max value in a histogram,
+// Platform.ExternalMetrics.SamplesRead. If it changes, the histogram will need
+// to be renamed.
 const int SerializationUtils::kMaxMessagesPerRead = 100000;
 
 std::unique_ptr<MetricSample> SerializationUtils::ParseSample(
@@ -171,6 +174,10 @@
       metrics->push_back(std::move(sample));
   }
 
+  base::UmaHistogramCustomCounts("Platform.ExternalMetrics.SamplesRead",
+                                 metrics->size(), 1, kMaxMessagesPerRead - 1,
+                                 50);
+
   result = ftruncate(fd.get(), 0);
   if (result < 0)
     DPLOG(ERROR) << "truncate metrics log: " << filename;
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc
index c342a3e..1bb66fab 100644
--- a/components/optimization_guide/core/optimization_guide_features.cc
+++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -43,8 +43,10 @@
 // language users from any locale and Spanish language users from the Spain
 // es-ES locale. A feature param containing "" is unrestricted by locale and any
 // user may load it.
-bool IsSupportedLocaleForFeature(const std::string locale,
-                                 const base::Feature& feature) {
+bool IsSupportedLocaleForFeature(
+    const std::string locale,
+    const base::Feature& feature,
+    const std::string& default_value = "de,en,es,fr,it,nl,pt,tr") {
   if (!base::FeatureList::IsEnabled(feature)) {
     return false;
   }
@@ -53,7 +55,7 @@
       base::GetFieldTrialParamValueByFeature(feature, "supported_locales");
   if (value.empty()) {
     // The default list of supported locales for optimization guide features.
-    value = "de,en,es,fr,it,nl,pt,tr";
+    value = default_value;
   } else if (value == "*") {
     // Still provide a way to enable all locales remotely via the '*' character.
     return true;
@@ -528,7 +530,8 @@
 bool ShouldExecutePageVisibilityModelOnPageContent(const std::string& locale) {
   return base::FeatureList::IsEnabled(kPageVisibilityPageContentAnnotations) &&
          IsSupportedLocaleForFeature(locale,
-                                     kPageVisibilityPageContentAnnotations);
+                                     kPageVisibilityPageContentAnnotations,
+                                     /*default_value=*/"en");
 }
 
 bool RemotePageMetadataEnabled() {
diff --git a/components/optimization_guide/core/optimization_guide_features_unittest.cc b/components/optimization_guide/core/optimization_guide_features_unittest.cc
index 2c73287..71abb1b 100644
--- a/components/optimization_guide/core/optimization_guide_features_unittest.cc
+++ b/components/optimization_guide/core/optimization_guide_features_unittest.cc
@@ -123,7 +123,17 @@
   scoped_feature_list.InitAndEnableFeature(
       features::kPageVisibilityPageContentAnnotations);
 
+  // These are the default enabled values.
+  EXPECT_TRUE(features::ShouldExecutePageVisibilityModelOnPageContent("en"));
+  EXPECT_TRUE(features::ShouldExecutePageVisibilityModelOnPageContent("en-AU"));
+  EXPECT_TRUE(features::ShouldExecutePageVisibilityModelOnPageContent("en-CA"));
+  EXPECT_TRUE(features::ShouldExecutePageVisibilityModelOnPageContent("en-GB"));
   EXPECT_TRUE(features::ShouldExecutePageVisibilityModelOnPageContent("en-US"));
+
+  EXPECT_FALSE(
+      features::ShouldExecutePageVisibilityModelOnPageContent("zh-CN"));
+  EXPECT_FALSE(features::ShouldExecutePageVisibilityModelOnPageContent("fr"));
+  EXPECT_FALSE(features::ShouldExecutePageVisibilityModelOnPageContent(""));
 }
 
 TEST(OptimizationGuideFeaturesTest,
diff --git a/components/password_manager/core/browser/password_form.h b/components/password_manager/core/browser/password_form.h
index b09b3fd..edb060b 100644
--- a/components/password_manager/core/browser/password_form.h
+++ b/components/password_manager/core/browser/password_form.h
@@ -374,9 +374,9 @@
   autofill::mojom::SubmissionIndicatorEvent submission_event =
       autofill::mojom::SubmissionIndicatorEvent::NONE;
 
-  // True iff heuristics declined this form for normal saving or filling (e.g.
-  // only credit card fields were found). But this form can be saved or filled
-  // only with the fallback.
+  // True iff heuristics declined this form for normal saving, updating, or
+  // filling (e.g. only credit card fields were found). But this form can be
+  // saved or filled only with the fallback.
   bool only_for_fallback = false;
 
   // True iff the new password field was found with server hints or autocomplete
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index 0c6609f..6a99bc7c 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -490,7 +490,7 @@
   }
 
   PasswordForm MakeSimpleForm() {
-    auto form = MakeSavedForm();
+    PasswordForm form = MakeSavedForm();
     form.form_data = MakeSimpleFormData();
     return form;
   }
@@ -3466,6 +3466,122 @@
   task_environment_.RunUntilIdle();
 }
 
+// Check that on a single field OTP form, update bubble is not shown
+// automatically, but is available on manual trigger.
+TEST_P(PasswordManagerTest, FillingAndSavingFallbacksOnOtpFormWithoutUsername) {
+  PasswordFormManager::set_wait_for_server_predictions_for_filling(false);
+  EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
+      .WillRepeatedly(Return(true));
+
+  PasswordForm saved_match(MakeSimpleForm());
+  store_->AddLogin(saved_match);
+
+  // Create form with an OTP field only.
+  PasswordForm one_time_code_form;
+  one_time_code_form.url = test_form_url_;
+  one_time_code_form.only_for_fallback = true;
+  one_time_code_form.password_value = u"123456";
+  one_time_code_form.password_element = u"one-time-code";
+  one_time_code_form.form_data.url = one_time_code_form.url;
+  FormFieldData field;
+  field.name_attribute = one_time_code_form.password_element;
+  field.value = one_time_code_form.password_value;
+  field.form_control_type = "password";
+  one_time_code_form.form_data.fields.push_back(field);
+
+  PasswordFormFillData form_data;
+  EXPECT_CALL(driver_, SetPasswordFillData)
+      .WillRepeatedly(SaveArg<0>(&form_data));
+
+  manager()->OnPasswordFormsParsed(&driver_, {one_time_code_form.form_data});
+  task_environment_.RunUntilIdle();
+
+  // Check that manual filling fallback available.
+  EXPECT_EQ(saved_match.username_value,
+            form_data.preferred_login.username_value);
+  EXPECT_EQ(saved_match.password_value,
+            form_data.preferred_login.password_value);
+  // Check that no automatic filling available.
+  EXPECT_TRUE(form_data.username_element_renderer_id.is_null());
+  EXPECT_TRUE(form_data.password_element_renderer_id.is_null());
+
+  // Check that saving fallback is available.
+  std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+  EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true))
+      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+  manager()->OnInformAboutUserInput(&driver_, one_time_code_form.form_data);
+  ASSERT_TRUE(form_manager_to_save);
+  PasswordForm expected_pending_form = saved_match;
+  // Only password value change is expected.
+  expected_pending_form.password_value = one_time_code_form.password_value;
+  EXPECT_THAT(form_manager_to_save->GetPendingCredentials(),
+              FormMatches(expected_pending_form));
+
+  // Check that no automatic save prompt is shown.
+  OnPasswordFormSubmitted(one_time_code_form.form_data);
+  EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
+  manager()->DidNavigateMainFrame(true);
+  manager()->OnPasswordFormsRendered(&driver_, {});
+  task_environment_.RunUntilIdle();
+}
+
+// Check that on non-password form, update bubble is not shown automatically,
+// but is available on manual trigger.
+TEST_P(PasswordManagerTest, FillingAndSavingFallbacksOnOtpFormWithUsername) {
+  PasswordFormManager::set_wait_for_server_predictions_for_filling(false);
+  EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
+      .WillRepeatedly(Return(true));
+
+  PasswordForm saved_match(MakeSimpleForm());
+  store_->AddLogin(saved_match);
+
+  PasswordForm one_time_code_form(MakeSimpleForm());
+  // Note that the username value was initialized in |MakeSimpleForm| and
+  // coincides with the username of the saved match.
+  one_time_code_form.only_for_fallback = true;
+  one_time_code_form.password_value = u"379 390";
+  one_time_code_form.password_element = u"one-time-code";
+  one_time_code_form.form_data.fields[1].value =
+      one_time_code_form.password_value;
+  one_time_code_form.form_data.fields[1].name_attribute =
+      one_time_code_form.password_element;
+
+  PasswordFormFillData form_data;
+  EXPECT_CALL(driver_, SetPasswordFillData)
+      .WillRepeatedly(SaveArg<0>(&form_data));
+
+  manager()->OnPasswordFormsParsed(&driver_, {one_time_code_form.form_data});
+  task_environment_.RunUntilIdle();
+
+  // Check that manual filling fallback available.
+  EXPECT_EQ(saved_match.username_value,
+            form_data.preferred_login.username_value);
+  EXPECT_EQ(saved_match.password_value,
+            form_data.preferred_login.password_value);
+  // Check that no automatic filling available.
+  EXPECT_TRUE(form_data.username_element_renderer_id.is_null());
+  EXPECT_TRUE(form_data.password_element_renderer_id.is_null());
+
+  // Check that saving fallback is available.
+  std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+  EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true))
+      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+  manager()->OnInformAboutUserInput(&driver_, one_time_code_form.form_data);
+  ASSERT_TRUE(form_manager_to_save);
+  PasswordForm expected_pending_form = saved_match;
+  // Only password value change is expected.
+  expected_pending_form.password_value = one_time_code_form.password_value;
+  EXPECT_THAT(form_manager_to_save->GetPendingCredentials(),
+              FormMatches(expected_pending_form));
+
+  // Check that no automatic save prompt is shown.
+  OnPasswordFormSubmitted(one_time_code_form.form_data);
+  EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
+  manager()->DidNavigateMainFrame(true);
+  manager()->OnPasswordFormsRendered(&driver_, {});
+  task_environment_.RunUntilIdle();
+}
+
 // Check that on successful login the credentials are checked for leak.
 TEST_P(PasswordManagerTest, StartLeakDetection) {
   auto mock_factory =
diff --git a/components/password_manager/core/browser/password_save_manager_impl.cc b/components/password_manager/core/browser/password_save_manager_impl.cc
index 97da383..e465ab80 100644
--- a/components/password_manager/core/browser/password_save_manager_impl.cc
+++ b/components/password_manager/core/browser/password_save_manager_impl.cc
@@ -136,8 +136,9 @@
   // "canonical" one according to the following hierarchy:
   // AUTOMATIC_SAVE > EQUAL_TO_SAVED_MATCH > UPDATE > NEW_LOGIN
   // Note that UPDATE or NEW_LOGIN will result in an Update or Save bubble to
-  // be shown, while AUTOMATIC_SAVE and EQUAL_TO_SAVED_MATCH will result in a
-  // silent save/update.
+  // be shown (unless heuristics determined that we see non-password fields),
+  // while AUTOMATIC_SAVE and EQUAL_TO_SAVED_MATCH will result in a silent
+  // save/update.
   // Some interesting cases:
   // NEW_LOGIN means that store doesn't know about the credential yet. If the
   // other store knows anything at all, then that always wins.
@@ -544,9 +545,14 @@
           parsed_submitted_form, observed_form, password_to_save.second,
           is_http_auth, is_credential_api_save);
       break;
-    case PendingCredentialsState::EQUAL_TO_SAVED_MATCH:
     case PendingCredentialsState::UPDATE:
       pending_credentials = *similar_saved_form;
+      // Propagate heuristics decision on whether to show update bubble.
+      pending_credentials.only_for_fallback =
+          parsed_submitted_form.only_for_fallback;
+      break;
+    case PendingCredentialsState::EQUAL_TO_SAVED_MATCH:
+      pending_credentials = *similar_saved_form;
       break;
     case PendingCredentialsState::AUTOMATIC_SAVE:
       pending_credentials = *similar_saved_form;
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java b/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java
index cf1b8d5..b6a33f7 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java
@@ -147,13 +147,6 @@
     }
 
     /**
-     * Called by the payment app to let Chrome know that the payment app's UI is now hidden, but
-     * the payment details have not been returned yet. This is a good time to show a "loading"
-     * progress indicator UI.
-     */
-    default void onInstrumentDetailsLoading() {}
-
-    /**
      * Called after retrieving payment details.
      */
     default void onInstrumentDetailsReady() {}
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentApp.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentApp.java
index ca99150..ce39e084 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentApp.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentApp.java
@@ -46,8 +46,10 @@
          * Called by the payment app to let Chrome know that the payment app's UI is now hidden, but
          * the payment details have not been returned yet. This is a good time to show a "loading"
          * progress indicator UI.
+         *
+         * TODO(smcgruer): Remove once Clank-internal code no longer overrides this.
          */
-        void onInstrumentDetailsLoadingWithoutUI();
+        default void onInstrumentDetailsLoadingWithoutUI() {}
 
         /**
          * Called after retrieving payment details.
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
index 40887fbd..e3eeb40 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
@@ -1821,13 +1821,6 @@
 
     // Implements PaymentApp.InstrumentDetailsCallback:
     @Override
-    public void onInstrumentDetailsLoadingWithoutUI() {
-        if (mPaymentResponseHelper == null || mBrowserPaymentRequest == null) return;
-        mBrowserPaymentRequest.onInstrumentDetailsLoading();
-    }
-
-    // Implements PaymentApp.InstrumentDetailsCallback:
-    @Override
     public void onInstrumentDetailsReady(
             String methodName, String stringifiedDetails, PayerData payerData) {
         assert methodName != null;
diff --git a/components/payments/content/android/javatests/src/org/chromium/components/payments/AndroidPaymentAppUnitTest.java b/components/payments/content/android/javatests/src/org/chromium/components/payments/AndroidPaymentAppUnitTest.java
index e35ebc2..ecf065b 100644
--- a/components/payments/content/android/javatests/src/org/chromium/components/payments/AndroidPaymentAppUnitTest.java
+++ b/components/payments/content/android/javatests/src/org/chromium/components/payments/AndroidPaymentAppUnitTest.java
@@ -118,9 +118,6 @@
                 /*displayItems=*/new ArrayList<PaymentItem>(), modifiers, new PaymentOptions(),
                 new ArrayList<PaymentShippingOption>(), new PaymentApp.InstrumentDetailsCallback() {
                     @Override
-                    public void onInstrumentDetailsLoadingWithoutUI() {}
-
-                    @Override
                     public void onInstrumentDetailsReady(
                             String methodName, String stringifiedDetails, PayerData payerData) {
                         mPaymentMethodName = methodName;
diff --git a/components/payments_strings.grdp b/components/payments_strings.grdp
index 983ec556..77106a0 100644
--- a/components/payments_strings.grdp
+++ b/components/payments_strings.grdp
@@ -28,21 +28,9 @@
     <message name="IDS_PAYMENTS_ADD_CARD_LABEL" desc="The title of the dialog for user to add new payment card. Sentence-cased.">
       Add card
     </message>
-    <message name="IDS_PAYMENTS_ADD_BILLING_ADDRESS" desc="The title of the dialog for user to add billing address to payment card. Sentence-cased." formatter_data="android_java">
-      Add billing address
-    </message>
-    <message name="IDS_PAYMENTS_ADD_NAME_ON_CARD" desc="The title of the dialog for user to add name on card to payment card. Sentence-cased." formatter_data="android_java">
-      Add name on card
-    </message>
-    <message name="IDS_PAYMENTS_ADD_VALID_CARD_NUMBER" desc="The title of the dialog for user to add valid payment card number. Sentence-cased." formatter_data="android_java">
-      Add valid card number
-    </message>
     <message name="IDS_PAYMENTS_ADD_MORE_INFORMATION" desc="The title in the Android app title bar for user to add more information to payment card or shipping address or contact info. Sentence-cased." formatter_data="android_java">
       Add more information
     </message>
-    <message name="IDS_PAYMENTS_EDIT_CARD" desc="The title of the dialog for user to edit payment card. Sentence-cased." formatter_data="android_java">
-      Edit card
-    </message>
     <message name="IDS_PAYMENTS_ADD_PHONE_NUMBER" desc="The title of the dialog for user to add phone number to the shipping address or contact info. This phone number can be used, for example, if there's a problem with shipping a package to its destination. Sentence-cased." formatter_data="android_java">
       Add phone number
     </message>
@@ -94,21 +82,9 @@
     <message name="IDS_PAYMENTS_ADD_CARD_LABEL" desc="The title of the dialog for user to add new payment card. Title-Cased.">
       Add Card
     </message>
-    <message name="IDS_PAYMENTS_ADD_BILLING_ADDRESS" desc="The title of the dialog for user to add billing address to payment card. Title-Cased.">
-      Add Billing Address
-    </message>
-    <message name="IDS_PAYMENTS_ADD_NAME_ON_CARD" desc="The title of the dialog for user to add name on card to payment card. Title-Cased.">
-      Add Name on Card
-    </message>
-    <message name="IDS_PAYMENTS_ADD_VALID_CARD_NUMBER" desc="The title of the dialog for user to add valid payment card number. Title-Cased.">
-      Add Valid Card Number
-    </message>
     <message name="IDS_PAYMENTS_ADD_MORE_INFORMATION" desc="The title in the Android app title bar for user to add more information to payment card or shipping address or contact info. Title-Cased.">
       Add More Information
     </message>
-    <message name="IDS_PAYMENTS_EDIT_CARD" desc="The title of the dialog for user to edit payment card. Title-Cased.">
-      Edit Card
-    </message>
     <message name="IDS_PAYMENTS_ADD_PHONE_NUMBER" desc="The title of the dialog for user to add phone number to the shipping address or contact info. This phone number can be used, for example, if there's a problem with shipping a package to its destination. Title-Cased.">
       Add Phone Number
     </message>
@@ -421,12 +397,9 @@
   <message name="IDS_PAYMENTS_INVALID_ADDRESS" desc="The label to indicate the shipping address is invalid. For example, missing state or city name." formatter_data="android_java">
     Enter a valid address
   </message>
-  <message name="IDS_PAYMENTS_BILLING_ADDRESS_REQUIRED" desc="The label to indicate billing address is required for payment card." formatter_data="android_java">
+  <message name="IDS_PAYMENTS_BILLING_ADDRESS_REQUIRED" desc="The label to indicate billing address is required for payment card.">
     Billing address required
   </message>
-  <message name="IDS_PAYMENTS_NAME_ON_CARD_REQUIRED" desc="The label to indicate the cardholder name (the name of the owner or 'holder' of the credit card)  must be entered." formatter_data="android_java">
-    Cardholder name required
-  </message>
   <message name="IDS_PAYMENTS_CARD_BILLING_ADDRESS_REQUIRED" desc="The label to indicate the billing address of the credit card  must be entered.">
     Card billing address required
   </message>
diff --git a/components/permissions/features.cc b/components/permissions/features.cc
index 7e32984..18d7e85c 100644
--- a/components/permissions/features.cc
+++ b/components/permissions/features.cc
@@ -94,7 +94,7 @@
 
 BASE_FEATURE(kPermissionOnDeviceGeolocationPredictions,
              "PermissionOnDeviceGeolocationPredictions",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 #if BUILDFLAG(IS_ANDROID)
 
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/AlternateErrorPagesEnabled.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/AlternateErrorPagesEnabled.yaml
index 1289a1b..4f654e38 100644
--- a/components/policy/resources/templates/policy_definitions/Miscellaneous/AlternateErrorPagesEnabled.yaml
+++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/AlternateErrorPagesEnabled.yaml
@@ -16,8 +16,8 @@
 - caption: Disable alternate error pages
   value: false
 owners:
-- file://components/policy/OWNERS
-- pastarmovj@chromium.org
+- file://net/OWNERS
+- bashi@chromium.org
 schema:
   type: boolean
 supported_on:
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/UserAvatarCustomizationSelectorsEnabled.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/UserAvatarCustomizationSelectorsEnabled.yaml
index 792a4394aa..42ffe34 100644
--- a/components/policy/resources/templates/policy_definitions/Miscellaneous/UserAvatarCustomizationSelectorsEnabled.yaml
+++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/UserAvatarCustomizationSelectorsEnabled.yaml
@@ -19,7 +19,7 @@
 - cowmoo@google.com
 schema:
   type: boolean
-future_on:
-- chrome_os
+supported_on:
+- chrome_os:114-
 tags: []
 type: main
diff --git a/components/safe_browsing/content/browser/client_side_detection_service.cc b/components/safe_browsing/content/browser/client_side_detection_service.cc
index 1252bdf..a65dca67 100644
--- a/components/safe_browsing/content/browser/client_side_detection_service.cc
+++ b/components/safe_browsing/content/browser/client_side_detection_service.cc
@@ -413,7 +413,9 @@
 }
 
 bool ClientSideDetectionService::OverPhishingReportLimit() {
+  // `delegate_` and prefs can be null in unit tests.
   if (base::FeatureList::IsEnabled(kSafeBrowsingDailyPhishingReportsLimit) &&
+      (delegate_ && delegate_->GetPrefs()) &&
       IsEnhancedProtectionEnabled(*delegate_->GetPrefs())) {
     return GetPhishingNumReports() >
            kSafeBrowsingDailyPhishingReportsLimitESB.Get();
@@ -561,7 +563,7 @@
     base::UmaHistogramEnumeration(
         "SBClientPhishing.ClassifyThresholdsResult",
         SBClientDetectionClassifyThresholdsResult::kModelSizeMismatch);
-    DVLOG(0)
+    VLOG(0)
         << "Model is misconfigured. Size is mismatched. Verdict scores size is "
         << static_cast<int>(verdict->tflite_model_scores().size())
         << " and model thresholds size is "
diff --git a/components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.cc b/components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.cc
index 715b89eb..3aeffa50 100644
--- a/components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.cc
+++ b/components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.cc
@@ -9,6 +9,23 @@
 
 namespace safe_browsing {
 
+const char kTailoredSecurityDisabledDialogShown[] =
+    "SafeBrowsing.AccountIntegration.DisabledDialog.Shown";
+const char kTailoredSecurityDisabledDialogOkButtonClicked[] =
+    "SafeBrowsing.AccountIntegration.DisabledDialog.OkButtonClicked";
+const char kTailoredSecurityDisabledDialogSettingsButtonClicked[] =
+    "SafeBrowsing.AccountIntegration.DisabledDialog.SettingsButtonClicked";
+const char kTailoredSecurityDisabledDialogDismissed[] =
+    "SafeBrowsing.AccountIntegration.DisabledDialog.Dismissed";
+const char kTailoredSecurityEnabledDialogShown[] =
+    "SafeBrowsing.AccountIntegration.EnabledDialog.Shown";
+const char kTailoredSecurityEnabledDialogOkButtonClicked[] =
+    "SafeBrowsing.AccountIntegration.EnabledDialog.OkButtonClicked";
+const char kTailoredSecurityEnabledDialogSettingsButtonClicked[] =
+    "SafeBrowsing.AccountIntegration.EnabledDialog.SettingsButtonClicked";
+const char kTailoredSecurityEnabledDialogDismissed[] =
+    "SafeBrowsing.AccountIntegration.EnabledDialog.Dismissed";
+
 void RecordEnabledNotificationResult(
     TailoredSecurityNotificationResult result) {
   base::UmaHistogramEnumeration(
@@ -16,4 +33,4 @@
       result);
 }
 
-}  // namespace safe_browsing
\ No newline at end of file
+}  // namespace safe_browsing
diff --git a/components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.h b/components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.h
index ef2fe5c..51a933d 100644
--- a/components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.h
+++ b/components/safe_browsing/core/browser/tailored_security_service/tailored_security_service_util.h
@@ -9,6 +9,15 @@
 
 namespace safe_browsing {
 
+extern const char kTailoredSecurityDisabledDialogShown[];
+extern const char kTailoredSecurityDisabledDialogOkButtonClicked[];
+extern const char kTailoredSecurityDisabledDialogSettingsButtonClicked[];
+extern const char kTailoredSecurityDisabledDialogDismissed[];
+extern const char kTailoredSecurityEnabledDialogShown[];
+extern const char kTailoredSecurityEnabledDialogOkButtonClicked[];
+extern const char kTailoredSecurityEnabledDialogSettingsButtonClicked[];
+extern const char kTailoredSecurityEnabledDialogDismissed[];
+
 // Records an UMA Histogram value to count the result of trying to notify a sync
 // user about enhanced protection for the enable case.
 void RecordEnabledNotificationResult(TailoredSecurityNotificationResult result);
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h
index e61f640..63e684f 100644
--- a/components/search_engines/template_url_service.h
+++ b/components/search_engines/template_url_service.h
@@ -18,6 +18,7 @@
 #include "base/functional/callback.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/observer_list.h"
 #include "base/time/default_clock.h"
 #include "base/time/time.h"
@@ -105,7 +106,9 @@
 
   // Search metadata that's often used to persist into History.
   struct SearchMetadata {
-    const TemplateURL* template_url;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #union
+    RAW_PTR_EXCLUSION const TemplateURL* template_url;
     GURL normalized_url;
     std::u16string search_terms;
   };
diff --git a/components/segmentation_platform/public/features.cc b/components/segmentation_platform/public/features.cc
index f534b95..5cf0173 100644
--- a/components/segmentation_platform/public/features.cc
+++ b/components/segmentation_platform/public/features.cc
@@ -72,10 +72,6 @@
              "ContextualPageActionShareModel",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kSegmentationPlatformSegmentInfoCache,
-             "SegmentationPlatformSegmentInfoCache",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kSegmentationDefaultReportingSegments,
              "SegmentationDefaultReportingSegments",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/segmentation_platform/public/features.h b/components/segmentation_platform/public/features.h
index c3e9275..5bb24e3 100644
--- a/components/segmentation_platform/public/features.h
+++ b/components/segmentation_platform/public/features.h
@@ -56,9 +56,6 @@
 // Feature flag for enabling shopping user segment feature.
 BASE_DECLARE_FEATURE(kShoppingUserSegmentFeature);
 
-// Feature flag for enabling `SegmentInfoCache` for `SegmentInfoDatabase`.
-BASE_DECLARE_FEATURE(kSegmentationPlatformSegmentInfoCache);
-
 // Feature flag for enabling default reporting segments.
 BASE_DECLARE_FEATURE(kSegmentationDefaultReportingSegments);
 
diff --git a/components/services/storage/dom_storage/local_storage_impl.cc b/components/services/storage/dom_storage/local_storage_impl.cc
index 8274bcc..3782ff4e 100644
--- a/components/services/storage/dom_storage/local_storage_impl.cc
+++ b/components/services/storage/dom_storage/local_storage_impl.cc
@@ -389,7 +389,7 @@
     return;  // Keep everything.
   }
 
-  if (!storage_keys_to_purge_on_shutdown_.empty()) {
+  if (!origins_to_purge_on_shutdown_.empty()) {
     RetrieveStorageUsage(
         base::BindOnce(&LocalStorageImpl::OnGotStorageUsageForShutdown,
                        base::Unretained(this)));
@@ -412,14 +412,11 @@
 void LocalStorageImpl::ApplyPolicyUpdates(
     std::vector<mojom::StoragePolicyUpdatePtr> policy_updates) {
   for (const auto& update : policy_updates) {
-    // TODO(https://crbug.com/1199077): Pass the real StorageKey when
-    // StoragePolicyUpdate is converted.
-    const blink::StorageKey storage_key =
-        blink::StorageKey::CreateFirstParty(update->origin);
+    const url::Origin origin = update->origin;
     if (!update->purge_on_shutdown)
-      storage_keys_to_purge_on_shutdown_.erase(storage_key);
+      origins_to_purge_on_shutdown_.erase(origin);
     else
-      storage_keys_to_purge_on_shutdown_.insert(std::move(storage_key));
+      origins_to_purge_on_shutdown_.insert(std::move(origin));
   }
 }
 
@@ -753,8 +750,13 @@
     std::vector<mojom::StorageUsageInfoPtr> usage) {
   std::vector<blink::StorageKey> storage_keys_to_delete;
   for (const auto& info : usage) {
-    if (base::Contains(storage_keys_to_purge_on_shutdown_, info->storage_key))
-      storage_keys_to_delete.push_back(info->storage_key);
+    const blink::StorageKey& storage_key = info->storage_key;
+    if (storage_key.IsFirstPartyContext()) {
+      const url::Origin& origin = storage_key.origin();
+      if (base::Contains(origins_to_purge_on_shutdown_, origin)) {
+        storage_keys_to_delete.push_back(storage_key);
+      }
+    }
   }
 
   if (!storage_keys_to_delete.empty()) {
diff --git a/components/services/storage/dom_storage/local_storage_impl.h b/components/services/storage/dom_storage/local_storage_impl.h
index afb8299..39b96594 100644
--- a/components/services/storage/dom_storage/local_storage_impl.h
+++ b/components/services/storage/dom_storage/local_storage_impl.h
@@ -169,8 +169,10 @@
   int commit_error_count_ = 0;
   bool tried_to_recover_from_commit_errors_ = false;
 
-  // The set of StorageKeys whose storage should be cleared on shutdown.
-  std::set<blink::StorageKey> storage_keys_to_purge_on_shutdown_;
+  // The set of Origins which should be cleared on shutdown.
+  // this is used by ApplyPolicyUpdates to store which origin
+  // to clear based on the provided StoragePolicyUpdate.
+  std::set<url::Origin> origins_to_purge_on_shutdown_;
 
   mojo::Receiver<mojom::LocalStorageControl> control_receiver_{this};
 
diff --git a/components/sync/base/features.cc b/components/sync/base/features.cc
index aabcd26..4c3a85f 100644
--- a/components/sync/base/features.cc
+++ b/components/sync/base/features.cc
@@ -149,4 +149,10 @@
              base::FEATURE_DISABLED_BY_DEFAULT);
 #endif  // BUILDFLAG(IS_IOS)
 
+#if !BUILDFLAG(IS_ANDROID) || !BUILDFLAG(IS_IOS)
+BASE_FEATURE(kSyncWebauthnCredentials,
+             "SyncWebauthnCredentials",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+#endif  // !BUILDFLAG(IS_ANDROID) || !BUILDFLAG(IS_IOS)
+
 }  // namespace syncer
diff --git a/components/sync/base/features.h b/components/sync/base/features.h
index 3bd0343..dad1c95 100644
--- a/components/sync/base/features.h
+++ b/components/sync/base/features.h
@@ -188,6 +188,11 @@
 BASE_DECLARE_FEATURE(kIndicateAccountStorageErrorInAccountCell);
 #endif  // BUILDFLAG(IS_IOS)
 
+#if !BUILDFLAG(IS_ANDROID) || !BUILDFLAG(IS_IOS)
+// Enables syncing the WEBAUTHN_CREDENTIAL data type.
+BASE_DECLARE_FEATURE(kSyncWebauthnCredentials);
+#endif  // !BUILDFLAG(IS_ANDROID) || !BUILDFLAG(IS_IOS)
+
 }  // namespace syncer
 
 #endif  // COMPONENTS_SYNC_BASE_FEATURES_H_
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.cc b/components/sync_bookmarks/bookmark_model_type_processor.cc
index 4cbbd2c..238a031 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor.cc
@@ -47,22 +47,7 @@
 
 namespace {
 
-#if BUILDFLAG(IS_IOS) or BUILDFLAG(IS_ANDROID)
-// Set a lower limit for mobile platforms.
-// 1. There are not many users of bookmarks on mobiles.
-// 2. Prevents creation of an overly huge sync metadata file to be stored on
-// the disk.
-// 3. Reduced memory consumption and processing, noticeable especially during
-// an initial merge.
-// 4. A lower limit for mobile platforms reflects the lower
-// capacity/processing power of mobile devices.
-//
-// Since the bookmark model thread is the UI thread, a smoother user
-// experience outweighs the resulting downsides.
-constexpr size_t kDefaultMaxBookmarksTillSyncEnabled = 20000;
-#else
 constexpr size_t kDefaultMaxBookmarksTillSyncEnabled = 100000;
-#endif
 
 class ScopedRemoteUpdateBookmarks {
  public:
diff --git a/components/sync_preferences/dual_layer_user_pref_store.h b/components/sync_preferences/dual_layer_user_pref_store.h
index ae8f102..97842bb 100644
--- a/components/sync_preferences/dual_layer_user_pref_store.h
+++ b/components/sync_preferences/dual_layer_user_pref_store.h
@@ -130,7 +130,7 @@
 
   base::ObserverList<PrefStore::Observer, true>::Unchecked observers_;
 
-  const PrefModelAssociatorClient* const pref_model_associator_client_ =
+  const raw_ptr<const PrefModelAssociatorClient> pref_model_associator_client_ =
       nullptr;
 };
 
diff --git a/components/sync_preferences/pref_model_associator.cc b/components/sync_preferences/pref_model_associator.cc
index 98664cf..d36977d 100644
--- a/components/sync_preferences/pref_model_associator.cc
+++ b/components/sync_preferences/pref_model_associator.cc
@@ -196,28 +196,40 @@
 
     if (user_pref_value) {
       DVLOG(1) << "Found user pref value for " << pref_name;
-      // We have both server and local values. Merge them.
-      base::Value new_value(
-          MergePreference(pref_name, *user_pref_value, sync_value));
-
-      // Update the local preference based on what we got from the sync server.
-      if (new_value.is_none()) {
-        LOG(WARNING) << "Sync has null value for pref " << pref_name.c_str();
-        user_prefs_->RemoveValue(pref_name, GetWriteFlags(pref_name));
-      } else if (*user_pref_value != new_value) {
-        SetPrefWithTypeCheck(pref_name, new_value);
-      }
-
-      // If the merge resulted in an updated value, inform the syncer.
-      if (sync_value != new_value) {
-        syncer::SyncData sync_data;
-        if (!CreatePrefSyncData(pref_name, new_value, &sync_data)) {
-          LOG(ERROR) << "Failed to update preference.";
-          return;
+      if (base::FeatureList::IsEnabled(
+              syncer::kEnablePreferencesAccountStorage)) {
+        // Overwrite updates to the account store.
+        if (sync_value.is_none()) {
+          LOG(WARNING) << "Sync has null value for pref " << pref_name.c_str();
+          user_prefs_->RemoveValue(pref_name, GetWriteFlags(pref_name));
+        } else if (*user_pref_value != sync_value) {
+          SetPrefWithTypeCheck(pref_name, sync_value);
+        }
+      } else {
+        // We have both server and local values. Merge them if account storage
+        // is not supported.
+        base::Value new_value(
+            MergePreference(pref_name, *user_pref_value, sync_value));
+        // Update the local preference based on what we got from the sync
+        // server.
+        if (new_value.is_none()) {
+          LOG(WARNING) << "Sync has null value for pref " << pref_name.c_str();
+          user_prefs_->RemoveValue(pref_name, GetWriteFlags(pref_name));
+        } else if (*user_pref_value != new_value) {
+          SetPrefWithTypeCheck(pref_name, new_value);
         }
 
-        sync_changes->push_back(syncer::SyncChange(
-            FROM_HERE, syncer::SyncChange::ACTION_UPDATE, sync_data));
+        // If the merge resulted in an updated value, inform the syncer.
+        if (sync_value != new_value) {
+          syncer::SyncData sync_data;
+          if (!CreatePrefSyncData(pref_name, new_value, &sync_data)) {
+            LOG(ERROR) << "Failed to update preference.";
+            return;
+          }
+
+          sync_changes->push_back(syncer::SyncChange(
+              FROM_HERE, syncer::SyncChange::ACTION_UPDATE, sync_data));
+        }
       }
     } else if (!sync_value.is_none()) {
       // Only a server value exists. Just set the local user value.
diff --git a/components/tracing/common/background_tracing_state_manager.cc b/components/tracing/common/background_tracing_state_manager.cc
index 25dcbdc..d1c195a 100644
--- a/components/tracing/common/background_tracing_state_manager.cc
+++ b/components/tracing/common/background_tracing_state_manager.cc
@@ -152,11 +152,10 @@
 }
 
 bool BackgroundTracingStateManager::DidRecentlyUploadForScenario(
-    const content::BackgroundTracingConfig& config) const {
+    const std::string& scenario_name) const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(initialized_);
-  std::string stripped_scenario_name =
-      StripScenarioName(config.scenario_name());
+  std::string stripped_scenario_name = StripScenarioName(scenario_name);
   auto it = scenario_last_upload_timestamp_.find(stripped_scenario_name);
   if (it != scenario_last_upload_timestamp_.end()) {
     return (base::Time::Now() - it->second) <=
diff --git a/components/tracing/common/background_tracing_state_manager.h b/components/tracing/common/background_tracing_state_manager.h
index e2ff7eb2..16d4b97 100644
--- a/components/tracing/common/background_tracing_state_manager.h
+++ b/components/tracing/common/background_tracing_state_manager.h
@@ -16,10 +16,6 @@
 class AwTracingDelegateTest;
 }
 
-namespace content {
-class BackgroundTracingConfig;
-}
-
 namespace tracing {
 
 class BackgroundTracingStateManagerTest;
@@ -60,8 +56,7 @@
 
   // True if the embedder uploaded a trace for the given |config| recently, and
   // uploads should be throttled for the |config|.
-  bool DidRecentlyUploadForScenario(
-      const content::BackgroundTracingConfig& config) const;
+  bool DidRecentlyUploadForScenario(const std::string& scenario_name) const;
 
   // The embedder should call this method every time background tracing starts
   // so that the state in prefs is updated. Posts a timer task to the current
diff --git a/components/tracing/common/background_tracing_state_manager_unittest.cc b/components/tracing/common/background_tracing_state_manager_unittest.cc
index 7fb524e..62edb2f 100644
--- a/components/tracing/common/background_tracing_state_manager_unittest.cc
+++ b/components/tracing/common/background_tracing_state_manager_unittest.cc
@@ -147,7 +147,7 @@
       content::BackgroundTracingConfig::FromDict(std::move(dict)));
 
   EXPECT_FALSE(tracing::BackgroundTracingStateManager::GetInstance()
-                   .DidRecentlyUploadForScenario(*config));
+                   .DidRecentlyUploadForScenario(config->scenario_name()));
 }
 
 TEST_F(BackgroundTracingStateManagerTest, UploadedRecently) {
@@ -174,7 +174,7 @@
       content::BackgroundTracingConfig::FromDict(std::move(dict)));
 
   EXPECT_TRUE(tracing::BackgroundTracingStateManager::GetInstance()
-                  .DidRecentlyUploadForScenario(*config));
+                  .DidRecentlyUploadForScenario(config->scenario_name()));
 }
 
 TEST_F(BackgroundTracingStateManagerTest, NotifyTracingStarted) {
diff --git a/components/webauthn/DEPS b/components/webauthn/DEPS
index 42ff5a58..9673d758 100644
--- a/components/webauthn/DEPS
+++ b/components/webauthn/DEPS
@@ -1,4 +1,6 @@
 include_rules = [
+  "+components/keyed_service",
+  "+components/sync",
   "+content/public/browser",
   "+mojo/public/cpp/bindings",
   "+third_party/blink/public/mojom/webauthn",
diff --git a/components/webauthn/core/browser/BUILD.gn b/components/webauthn/core/browser/BUILD.gn
index 3049ef2..fda97cf 100644
--- a/components/webauthn/core/browser/BUILD.gn
+++ b/components/webauthn/core/browser/BUILD.gn
@@ -14,6 +14,18 @@
       "//url",
     ]
   }
+
+  if (!is_ios && !is_android) {
+    sources += [
+      "passkey_model.h",
+      "passkey_sync_bridge.cc",
+      "passkey_sync_bridge.h",
+    ]
+    deps += [
+      "//base",
+      "//components/sync",
+    ]
+  }
 }
 
 static_library("test_support") {
diff --git a/components/webauthn/core/browser/passkey_model.h b/components/webauthn/core/browser/passkey_model.h
new file mode 100644
index 0000000..6b9fd6a
--- /dev/null
+++ b/components/webauthn/core/browser/passkey_model.h
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_WEBAUTHN_CORE_BROWSER_PASSKEY_MODEL_H_
+#define COMPONENTS_WEBAUTHN_CORE_BROWSER_PASSKEY_MODEL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/sync/model/model_type_store.h"
+
+namespace syncer {
+class ModelTypeControllerDelegate;
+}
+
+// PasskeyModel provides access to passkeys, which are represented as
+// WebauthnCredentialSpecifics in Sync.
+//
+// By design, non-syncing passkeys are not supported (unlike passwords e.g.,
+// which can be created on the local device only, without uploading them to
+// Sync).
+//
+// Aside from Sync passkeys, there might be other WebAuthn platform credentials
+// on the device. E.g., non-passkey credentials in the browser-provided
+// authenticators on CrOS (u2fd) and macOS (//device/fido/mac); or platform
+// credentials owned by Windows Hello or iCloud Keychain. None of these are
+// accessible though PasskeyModel.
+class PasskeyModel : public KeyedService {
+ public:
+  // Returns the sync ModelTypeControllerDelegate for the WEBAUTHN_CREDENTIAL
+  // data type.
+  virtual base::WeakPtr<syncer::ModelTypeControllerDelegate>
+  GetModelTypeControllerDelegate() = 0;
+};
+
+#endif  // COMPONENTS_WEBAUTHN_CORE_BROWSER_PASSKEY_MODEL_H_
diff --git a/components/webauthn/core/browser/passkey_sync_bridge.cc b/components/webauthn/core/browser/passkey_sync_bridge.cc
new file mode 100644
index 0000000..47a30bf
--- /dev/null
+++ b/components/webauthn/core/browser/passkey_sync_bridge.cc
@@ -0,0 +1,77 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/webauthn/core/browser/passkey_sync_bridge.h"
+
+#include <memory>
+#include <string>
+
+#include "base/feature_list.h"
+#include "base/functional/callback_helpers.h"
+#include "base/notreached.h"
+#include "components/sync/base/features.h"
+#include "components/sync/base/model_type.h"
+#include "components/sync/model/client_tag_based_model_type_processor.h"
+#include "components/sync/model/entity_change.h"
+#include "components/sync/model/metadata_change_list.h"
+#include "components/sync/model/model_type_controller_delegate.h"
+#include "components/sync/model/model_type_store.h"
+#include "components/sync/model/mutable_data_batch.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+PasskeySyncBridge::PasskeySyncBridge(
+    syncer::OnceModelTypeStoreFactory store_factory)
+    : syncer::ModelTypeSyncBridge(
+          std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
+              syncer::WEBAUTHN_CREDENTIAL,
+              /*dump_stack=*/base::DoNothing())) {
+  DCHECK(base::FeatureList::IsEnabled(syncer::kSyncWebauthnCredentials));
+  NOTIMPLEMENTED();  // Run `store_factory`.
+}
+
+PasskeySyncBridge::~PasskeySyncBridge() = default;
+
+std::unique_ptr<syncer::MetadataChangeList>
+PasskeySyncBridge::CreateMetadataChangeList() {
+  return syncer::ModelTypeStore::WriteBatch::CreateMetadataChangeList();
+}
+
+absl::optional<syncer::ModelError> PasskeySyncBridge::MergeSyncData(
+    std::unique_ptr<syncer::MetadataChangeList> metadata_changes,
+    syncer::EntityChangeList entity_changes) {
+  NOTIMPLEMENTED();
+  return absl::nullopt;
+}
+
+absl::optional<syncer::ModelError> PasskeySyncBridge::ApplySyncChanges(
+    std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+    syncer::EntityChangeList entity_changes) {
+  NOTIMPLEMENTED();
+  return absl::nullopt;
+}
+
+void PasskeySyncBridge::GetData(StorageKeyList storage_keys,
+                                DataCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+void PasskeySyncBridge::GetAllDataForDebugging(DataCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+std::string PasskeySyncBridge::GetClientTag(
+    const syncer::EntityData& entity_data) {
+  return GetStorageKey(entity_data);
+}
+
+std::string PasskeySyncBridge::GetStorageKey(
+    const syncer::EntityData& entity_data) {
+  DCHECK(entity_data.specifics.has_webauthn_credential());
+  return entity_data.specifics.webauthn_credential().sync_id();
+}
+
+base::WeakPtr<syncer::ModelTypeControllerDelegate>
+PasskeySyncBridge::GetModelTypeControllerDelegate() {
+  return change_processor()->GetControllerDelegate();
+}
diff --git a/components/webauthn/core/browser/passkey_sync_bridge.h b/components/webauthn/core/browser/passkey_sync_bridge.h
new file mode 100644
index 0000000..fa896ab
--- /dev/null
+++ b/components/webauthn/core/browser/passkey_sync_bridge.h
@@ -0,0 +1,50 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_WEBAUTHN_CORE_BROWSER_PASSKEY_SYNC_BRIDGE_H_
+#define COMPONENTS_WEBAUTHN_CORE_BROWSER_PASSKEY_SYNC_BRIDGE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "components/sync/model/model_type_store.h"
+#include "components/sync/model/model_type_sync_bridge.h"
+#include "components/webauthn/core/browser/passkey_model.h"
+
+namespace syncer {
+struct EntityData;
+class MetadataChangeList;
+class ModelError;
+}  // namespace syncer
+
+// Sync bridge implementation for WEBAUTHN_CREDENTIAL model type.
+class PasskeySyncBridge : public syncer::ModelTypeSyncBridge,
+                          public PasskeyModel {
+ public:
+  explicit PasskeySyncBridge(syncer::OnceModelTypeStoreFactory store_factory);
+  PasskeySyncBridge(const PasskeySyncBridge&) = delete;
+  PasskeySyncBridge& operator=(const PasskeySyncBridge&) = delete;
+  ~PasskeySyncBridge() override;
+
+  // syncer::ModelTypeSyncBridge:
+  std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
+      override;
+  absl::optional<syncer::ModelError> MergeSyncData(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityChangeList entity_data) override;
+  absl::optional<syncer::ModelError> ApplySyncChanges(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityChangeList entity_changes) override;
+  void GetData(StorageKeyList storage_keys, DataCallback callback) override;
+  void GetAllDataForDebugging(DataCallback callback) override;
+  std::string GetClientTag(const syncer::EntityData& entity_data) override;
+  std::string GetStorageKey(const syncer::EntityData& entity_data) override;
+
+  // PasskeyModel:
+  base::WeakPtr<syncer::ModelTypeControllerDelegate>
+  GetModelTypeControllerDelegate() override;
+};
+
+#endif  // COMPONENTS_WEBAUTHN_CORE_BROWSER_PASSKEY_SYNC_BRIDGE_H_
diff --git a/components/webxr/android/BUILD.gn b/components/webxr/android/BUILD.gn
index e97e7593..0df2353 100644
--- a/components/webxr/android/BUILD.gn
+++ b/components/webxr/android/BUILD.gn
@@ -150,7 +150,17 @@
   # Also includes any cardboard-specific java runtime dependencies that the
   # native files in this folder may depend upon.
   if (enable_cardboard) {
+    sources += [
+      "//components/webxr/android/java/src/org/chromium/components/webxr/CardboardClassProvider.java",
+      "//components/webxr/android/java/src/org/chromium/components/webxr/CardboardOverlayDelegate.java",
+    ]
     deps += [ "//third_party/cardboard:cardboard_java" ]
+  } else if (enable_arcore) {
+    # These stub classes are needed for the general Xr infrastructure code, but
+    # are not needed for the more broad always-available code. So we check that
+    # the non-cardboard parts of the "general xr" sources are still true before
+    # we attempt to compile these bits in.
+    sources += [ "//components/webxr/android/stubs/java/src/org/chromium/components/webxr/CardboardClassProvider.java" ]
   }
 
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/components/webxr/android/java/src/org/chromium/components/webxr/CardboardClassProvider.java b/components/webxr/android/java/src/org/chromium/components/webxr/CardboardClassProvider.java
new file mode 100644
index 0000000..a9c98f8
--- /dev/null
+++ b/components/webxr/android/java/src/org/chromium/components/webxr/CardboardClassProvider.java
@@ -0,0 +1,23 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.webxr;
+
+import android.app.Activity;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * This "real" version of CardboardClassProvider is only built if |enable_cardboard| is true, which
+ * means that all of our dependent types are also compiled in and we can directly create them here.
+ * Any method that you add or update the signature of here needs to also be updated in the
+ * corresponding /stubs/ version of this class.
+ */
+/*package*/ class CardboardClassProvider {
+    /*package*/ static @Nullable XrImmersiveOverlay.Delegate getOverlayDelegate(
+            @NonNull Activity activity) {
+        return new CardboardOverlayDelegate(activity);
+    }
+}
diff --git a/components/webxr/android/java/src/org/chromium/components/webxr/CardboardOverlayDelegate.java b/components/webxr/android/java/src/org/chromium/components/webxr/CardboardOverlayDelegate.java
new file mode 100644
index 0000000..c459b65
--- /dev/null
+++ b/components/webxr/android/java/src/org/chromium/components/webxr/CardboardOverlayDelegate.java
@@ -0,0 +1,85 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.webxr;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.view.MotionEvent;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import org.chromium.base.Log;
+
+/**
+ * Provides a fullscreen overlay for immersive Cardboard (VR) mode.
+ */
+public class CardboardOverlayDelegate implements XrImmersiveOverlay.Delegate {
+    private static final String TAG = "CardboardOverlay";
+    private static final boolean DEBUG_LOGS = false;
+    static final int VR_SYSTEM_UI_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN
+            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+
+    private Activity mActivity;
+
+    public CardboardOverlayDelegate(@NonNull Activity activity) {
+        if (DEBUG_LOGS) {
+            Log.i(TAG, "constructor");
+        }
+
+        mActivity = activity;
+    }
+
+    @Override
+    public void prepareToCreateSurfaceView() {}
+
+    @Override
+    public void configureSurfaceView(SurfaceView surfaceView) {}
+
+    @Override
+    public void parentAndShowSurfaceView(SurfaceView surfaceView) {
+        if (DEBUG_LOGS) {
+            Log.i(TAG, "Parenting Surface for AR");
+        }
+
+        int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility();
+        mActivity.getWindow().getDecorView().setSystemUiVisibility(flags | VR_SYSTEM_UI_FLAGS);
+
+        ViewGroup parent = (ViewGroup) mActivity.getWindow().findViewById(android.R.id.content);
+        parent.addView(surfaceView);
+    }
+
+    @Override
+    public void onStopUsingSurfaceView() {}
+
+    @Override
+    public void removeAndHideSurfaceView(SurfaceView surfaceView) {
+        if (surfaceView == null) {
+            return;
+        }
+
+        int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility();
+        mActivity.getWindow().getDecorView().setSystemUiVisibility(flags & ~VR_SYSTEM_UI_FLAGS);
+
+        ViewGroup parent = (ViewGroup) surfaceView.getParent();
+        if (parent != null) {
+            // Remove the surfaceView before changing the parent's visibility, so that we
+            // don't trigger any duplicate destruction events.
+            parent.removeView(surfaceView);
+        }
+    }
+
+    @Override
+    public void maybeForwardTouchEvent(MotionEvent ev) {}
+
+    @Override
+    public int getDesiredOrientation() {
+        return Configuration.ORIENTATION_LANDSCAPE;
+    }
+}
diff --git a/components/webxr/android/java/src/org/chromium/components/webxr/XrSessionCoordinator.java b/components/webxr/android/java/src/org/chromium/components/webxr/XrSessionCoordinator.java
index 2ea1c9c2..68e39c93 100644
--- a/components/webxr/android/java/src/org/chromium/components/webxr/XrSessionCoordinator.java
+++ b/components/webxr/android/java/src/org/chromium/components/webxr/XrSessionCoordinator.java
@@ -10,7 +10,6 @@
 
 import androidx.annotation.IntDef;
 
-import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.annotations.CalledByNative;
@@ -60,6 +59,8 @@
 
     private @SessionType int mActiveSessionType = SessionType.NONE;
 
+    private static WebContents sWebContents;
+
     /** Whether there is a non-null valid {@link #sActiveSessionInstance}. */
     private static XrSessionTypeSupplier sActiveSessionAvailableSupplier =
             new XrSessionTypeSupplier(SessionType.NONE);
@@ -81,13 +82,18 @@
     }
 
     /**
-     * Gets the current application context.
+     * Gets the current application context. Should not be called until after a start*Session call
+     * has succeeded, but if called after an endSession call may return null.
      *
      * @return Context The application context.
      */
     @CalledByNative
     private static Context getApplicationContext() {
-        return ContextUtils.getApplicationContext();
+        if (sWebContents == null) {
+            return null;
+        }
+
+        return getActivity(sWebContents);
     }
 
     private XrSessionCoordinator(long nativeXrSessionCoordinator) {
@@ -105,6 +111,7 @@
         mImmersiveOverlay = new XrImmersiveOverlay();
         mImmersiveOverlay.show(overlayDelegate, webContents, this);
 
+        sWebContents = webContents;
         sActiveSessionInstance = this;
         mActiveSessionType = sessionType;
         sActiveSessionAvailableSupplier.set(sessionType);
@@ -124,6 +131,18 @@
     }
 
     @CalledByNative
+    private void startVrSession(final WebContents webContents) {
+        if (DEBUG_LOGS) Log.i(TAG, "startVrSession");
+        // The higher levels should have guaranteed that we're only called if there isn't any other
+        // active session going on.
+        assert (sActiveSessionInstance == null);
+
+        XrImmersiveOverlay.Delegate overlayDelegate =
+                CardboardClassProvider.getOverlayDelegate(getActivity(webContents));
+        startSession(SessionType.VR, overlayDelegate, webContents);
+    }
+
+    @CalledByNative
     private void endSession() {
         if (DEBUG_LOGS) Log.i(TAG, "endSession");
         if (mImmersiveOverlay == null) return;
@@ -131,8 +150,9 @@
 
         mImmersiveOverlay.cleanupAndExit();
         mImmersiveOverlay = null;
-        sActiveSessionInstance = null;
         mActiveSessionType = SessionType.NONE;
+        sActiveSessionInstance = null;
+        sWebContents = null;
         sActiveSessionAvailableSupplier.set(SessionType.NONE);
     }
 
diff --git a/components/webxr/android/stubs/java/src/org/chromium/components/webxr/CardboardClassProvider.java b/components/webxr/android/stubs/java/src/org/chromium/components/webxr/CardboardClassProvider.java
new file mode 100644
index 0000000..82afd12
--- /dev/null
+++ b/components/webxr/android/stubs/java/src/org/chromium/components/webxr/CardboardClassProvider.java
@@ -0,0 +1,23 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.webxr;
+
+import android.app.Activity;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * This "stub" version of CardboardClassProvider is only built if |enable_cardboard| is false. As
+ * such, none of the concrete implementations for the exposed interfaces are present, and this just
+ * returns null for all of the types. Any method signatures updated in the "real" version need to
+ * also be updated here as well.
+ */
+/*package*/ class CardboardClassProvider {
+    /*package*/ static @Nullable XrImmersiveOverlay.Delegate getOverlayDelegate(
+            @NonNull Activity activity) {
+        return null;
+    }
+}
diff --git a/components/webxr/android/xr_session_coordinator.cc b/components/webxr/android/xr_session_coordinator.cc
index d7e287d..7711010 100644
--- a/components/webxr/android/xr_session_coordinator.cc
+++ b/components/webxr/android/xr_session_coordinator.cc
@@ -68,6 +68,24 @@
       use_overlay, can_render_dom_content);
 }
 
+void XrSessionCoordinator::RequestVrSession(
+    int render_process_id,
+    int render_frame_id,
+    device::SurfaceReadyCallback ready_callback,
+    device::SurfaceTouchCallback touch_callback,
+    device::SurfaceDestroyedCallback destroyed_callback) {
+  DVLOG(1) << __func__;
+  JNIEnv* env = AttachCurrentThread();
+
+  surface_ready_callback_ = std::move(ready_callback);
+  surface_touch_callback_ = std::move(touch_callback);
+  surface_destroyed_callback_ = std::move(destroyed_callback);
+
+  Java_XrSessionCoordinator_startVrSession(
+      env, j_xr_session_coordinator_,
+      webxr::GetJavaWebContents(render_process_id, render_frame_id));
+}
+
 void XrSessionCoordinator::EndSession() {
   DVLOG(1) << __func__;
   JNIEnv* env = AttachCurrentThread();
diff --git a/components/webxr/android/xr_session_coordinator.h b/components/webxr/android/xr_session_coordinator.h
index c915b392..0862916c 100644
--- a/components/webxr/android/xr_session_coordinator.h
+++ b/components/webxr/android/xr_session_coordinator.h
@@ -28,6 +28,12 @@
       device::SurfaceReadyCallback ready_callback,
       device::SurfaceTouchCallback touch_callback,
       device::SurfaceDestroyedCallback destroyed_callback) override;
+  void RequestVrSession(
+      int render_process_id,
+      int render_frame_id,
+      device::SurfaceReadyCallback ready_callback,
+      device::SurfaceTouchCallback touch_callback,
+      device::SurfaceDestroyedCallback destroyed_callback) override;
   void EndSession() override;
   bool EnsureARCoreLoaded() override;
   base::android::ScopedJavaLocalRef<jobject> GetApplicationContext() override;
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 71b6c24..9eb604c 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -16,6 +16,7 @@
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/strings/string_split.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
@@ -239,8 +240,12 @@
       const BrowserAccessibility* operator*();
 
      private:
-      const BrowserAccessibility* const parent_;
-      const BrowserAccessibility* const child_tree_root_;
+      // This field is not a raw_ptr<> because it was filtered by the rewriter
+      // for: #constexpr-ctor-field-initializer
+      RAW_PTR_EXCLUSION const BrowserAccessibility* const parent_;
+      // This field is not a raw_ptr<> because it was filtered by the rewriter
+      // for: #constexpr-ctor-field-initializer
+      RAW_PTR_EXCLUSION const BrowserAccessibility* const child_tree_root_;
       unsigned int index_;
     };
 
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 1e2b5e76..2caf52a 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -46,7 +46,18 @@
 
 namespace {
 
-bool ShouldHaveChildTree(const ui::AXNode& node) {
+bool SkipUrlMatch(const std::vector<std::string>& skip_urls,
+                  const std::string& url) {
+  for (auto& skip_url : skip_urls) {
+    if (url.find(skip_url) != std::string::npos) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool ShouldHaveChildTree(const ui::AXNode& node,
+                         const std::vector<std::string>& skip_urls) {
   const ui::AXNodeData& data = node.data();
   if (data.GetRestriction() == ax::mojom::Restriction::kDisabled) {
     DCHECK(!data.HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId));
@@ -59,26 +70,72 @@
   // If has a child tree owner role or a child tree id, then expect some
   // child tree content. In some cases IsChildTreeOwner(role) will be false,
   // if an ARIA role was used, e.g. <iframe role="region">.
-  return ui::IsChildTreeOwner(node.GetRole()) ||
-         data.HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId);
+  if (data.HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) {
+    return true;
+  }
+  if (!ui::IsChildTreeOwner(node.GetRole())) {
+    return false;
+  }
+  std::string url = node.GetStringAttribute(ax::mojom::StringAttribute::kUrl);
+  return (!url.empty() && !SkipUrlMatch(skip_urls, url));
 }
 
-bool AccessibilityTreeContainsAllChildTrees(const ui::AXNode& node) {
-  size_t num_children = node.GetChildCountCrossingTreeBoundary();
-  if (!num_children) {
-    // No children. All content is contained unless there is supposed to be
-    // a child tree for this node.
-    return !ShouldHaveChildTree(node);
-  }
+class AXTreeChangeWaiter : public ui::AXTreeObserver {
+ public:
+  AXTreeChangeWaiter()
+      : loop_runner_(std::make_unique<base::RunLoop>()),
+        loop_runner_quit_closure_(loop_runner_->QuitClosure()) {}
 
-  for (size_t i = 0; i < num_children; i++) {
-    if (!AccessibilityTreeContainsAllChildTrees(
-            *node.GetChildAtIndexCrossingTreeBoundary(i))) {
-      return false;
+  void OnStringAttributeChanged(ui::AXTree* tree,
+                                ui::AXNode* node,
+                                ax::mojom::StringAttribute attr,
+                                const std::string& old_value,
+                                const std::string& new_value) override {
+    if (attr == ax::mojom::StringAttribute::kChildTreeId) {
+      tree->RemoveObserver(this);
+      loop_runner_quit_closure_.Run();
     }
   }
 
-  return true;
+  void OnChildTreeConnectionChanged(ui::AXNode* host_node) override {
+    host_node->tree()->RemoveObserver(this);
+    loop_runner_quit_closure_.Run();
+  }
+
+  void WaitForChange(ui::AXTree* tree) {
+    tree->AddObserver(this);
+    loop_runner_->Run();
+    loop_runner_.reset();
+    loop_runner_quit_closure_.Reset();
+  }
+
+ private:
+  std::unique_ptr<base::RunLoop> loop_runner_;
+  base::RepeatingClosure loop_runner_quit_closure_;
+};
+
+void WaitForChildTrees(const ui::AXNode& node,
+                       const std::vector<std::string>& skip_urls) {
+  while (true) {
+    size_t num_children = node.GetChildCountCrossingTreeBoundary();
+    if (!num_children && ShouldHaveChildTree(node, skip_urls)) {
+      AXTreeChangeWaiter waiter;
+      waiter.WaitForChange(node.tree());
+      continue;
+    }
+
+    // Any node that is the connection point for a child tree should have
+    // exactly one child.
+    DCHECK(!ShouldHaveChildTree(node, skip_urls) || num_children == 1u)
+        << "AXNode (" << node << ") has an unexpected number of "
+        << "children :" << num_children;
+
+    for (size_t i = 0; i < num_children; i++) {
+      WaitForChildTrees(*node.GetChildAtIndexCrossingTreeBoundary(i),
+                        skip_urls);
+    }
+    break;
+  }
 }
 
 bool IsLoadedDocWithUrl(const BrowserAccessibility* node,
@@ -302,11 +359,14 @@
   // is complete.
   PerformAndWaitForDefaultActions(mode);
 
-  // Wait for expected text from @WAIT-FOR.
-  WaitForExpectedText(mode);
-
-  // Wait until all accessibility events and dirty objects have been processed.
-  WaitForEndOfTest(mode);
+  if (scenario_.wait_for.size()) {
+    // Wait for expected text from @WAIT-FOR.
+    WaitForExpectedText(mode);
+  } else {
+    // Wait until all accessibility events and dirty objects have been
+    // processed.
+    WaitForEndOfTest(mode);
+  }
 }
 
 void DumpAccessibilityTestBase::RunTestForPlatform(
@@ -444,16 +504,8 @@
     // WebContents as the node doesn't have a url set.
 
     std::string url = node->current_url().spec();
-
-    // sometimes we expect a url to never load, in these cases, don't wait.
-    bool skip_url = false;
-    for (std::string no_load_url : skip_urls) {
-      if (url.find(no_load_url) != std::string::npos) {
-        skip_url = true;
-        break;
-      }
-    }
-    if (!skip_url && url != url::kAboutBlankURL && !url.empty() &&
+    if (url != url::kAboutBlankURL && !url.empty() &&
+        !SkipUrlMatch(skip_urls, url) &&
         node->frame_owner_element_type() !=
             blink::FrameOwnerElementType::kPortal) {
       all_frame_urls[url] += 1;
@@ -479,16 +531,10 @@
       BrowserAccessibility* accessibility_root =
           manager->GetBrowserAccessibilityRoot();
 
-      // Check to see if all frames have loaded. If not, we invoke
-      // WaitForEndOfTest to listen for a kEndOfTest signal which will be
-      // fired for each loaded child tree.
-      if (!AccessibilityTreeContainsAllChildTrees(
-              *accessibility_root->node())) {
-        WaitForEndOfTest(mode);
-        continue;
-      }
+      WaitForChildTrees(*accessibility_root->node(),
+                        scenario_.no_load_expected);
 
-      bool all_frames_loaded = true;
+      bool all_expected_urls_loaded = true;
       // A test may change the url for a frame, for example by setting
       // window.location.href, so collect the current list of urls.
       const std::map<std::string, unsigned> all_frame_urls =
@@ -498,13 +544,13 @@
                 accessibility_root, url, num_expected)) {
           VLOG(1) << "Still waiting on " << num_remaining
                   << " frame(s) to load: " << url;
-          all_frames_loaded = false;
+          all_expected_urls_loaded = false;
           break;
         }
       }
-      // If all frames have loaded, we're done.
-      if (all_frames_loaded)
+      if (all_expected_urls_loaded) {
         break;
+      }
     }
 
     // Block until the next accessibility notification in any frame.
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.h b/content/browser/accessibility/dump_accessibility_browsertest_base.h
index c532fbdd..9cccbe27 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.h
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.h
@@ -229,6 +229,9 @@
       const char* attr,
       const std::string& value) const;
 
+  // The entries in skip_urls will be omitted from the result. This is used,
+  // e.g., in support of the @NO-LOAD-EXPECTED directive, when an element has an
+  // invalid src attribute.
   std::map<std::string, unsigned> CollectAllFrameUrls(
       const std::vector<std::string>& skip_urls);
 
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 94fff05c..ab6a041 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -2788,6 +2788,10 @@
   RunHtmlTest(FILE_PATH_LITERAL("popover-collapsed.html"));
 }
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityPopoverHint) {
+  RunPopoverHintTest(FILE_PATH_LITERAL("popover-hint.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityPre) {
   RunHtmlTest(FILE_PATH_LITERAL("pre.html"));
 }
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.h b/content/browser/accessibility/dump_accessibility_tree_browsertest.h
index a0db3236..6200d1e 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.h
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.h
@@ -8,6 +8,7 @@
 #include "content/browser/accessibility/dump_accessibility_browsertest_base.h"
 
 #include "base/command_line.h"
+#include "content/public/common/content_switches.h"
 #include "ui/accessibility/accessibility_features.h"
 #include "ui/accessibility/accessibility_switches.h"
 
@@ -75,6 +76,14 @@
     RunTypedTest<kHTML>(file_path);
   }
 
+  // TODO(accessibility): Replace all tests using RunPopoverHintTest to just
+  // RunHtmlTest when Popover hints are enabled by default.
+  void RunPopoverHintTest(const base::FilePath::CharType* file_path) {
+    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+        switches::kEnableBlinkFeatures, "HTMLPopoverHint");
+    RunTypedTest<kHTML>(file_path);
+  }
+
   void RunMathMLTest(const base::FilePath::CharType* file_path) {
     RunTypedTest<kMathML>(file_path);
   }
diff --git a/content/browser/aggregation_service/report_scheduler_timer.cc b/content/browser/aggregation_service/report_scheduler_timer.cc
index 47aa1de..5488f55 100644
--- a/content/browser/aggregation_service/report_scheduler_timer.cc
+++ b/content/browser/aggregation_service/report_scheduler_timer.cc
@@ -41,10 +41,15 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
+network::mojom::ConnectionType ReportSchedulerTimer::connection_type() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return connection_type_;
+}
+
 void ReportSchedulerTimer::MaybeSet(absl::optional<base::Time> reporting_time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!reporting_time.has_value() || offline_) {
+  if (!reporting_time.has_value() || IsOffline()) {
     return;
   }
   if (!reporting_time_reached_timer_.IsRunning() ||
@@ -55,7 +60,7 @@
 }
 
 void ReportSchedulerTimer::Refresh(base::Time now) {
-  if (offline_) {
+  if (IsOffline()) {
     return;
   }
 
@@ -76,10 +81,10 @@
     network::mojom::ConnectionType connection_type) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  bool was_offline = offline_;
-  offline_ = connection_type == network::mojom::ConnectionType::CONNECTION_NONE;
+  bool was_offline = IsOffline();
+  connection_type_ = connection_type;
 
-  if (offline_) {
+  if (IsOffline()) {
     reporting_time_reached_timer_.Stop();
     if (!was_offline) {
       delegate_->OnReportingPaused();
@@ -95,4 +100,8 @@
   }
 }
 
+bool ReportSchedulerTimer::IsOffline() const {
+  return connection_type_ == network::mojom::ConnectionType::CONNECTION_NONE;
+}
+
 }  // namespace content
diff --git a/content/browser/aggregation_service/report_scheduler_timer.h b/content/browser/aggregation_service/report_scheduler_timer.h
index 4986335..640d863 100644
--- a/content/browser/aggregation_service/report_scheduler_timer.h
+++ b/content/browser/aggregation_service/report_scheduler_timer.h
@@ -15,6 +15,7 @@
 #include "base/timer/wall_clock_timer.h"
 #include "content/common/content_export.h"
 #include "services/network/public/cpp/network_connection_tracker.h"
+#include "services/network/public/mojom/network_change_manager.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
@@ -72,6 +73,8 @@
 
   ~ReportSchedulerTimer() override;
 
+  network::mojom::ConnectionType connection_type() const;
+
   // Schedules `reporting_time_reached_timer_` to fire at that time, unless the
   // timer is already set to fire earlier.
   void MaybeSet(absl::optional<base::Time> reporting_time);
@@ -83,6 +86,8 @@
   // network::NetworkConnectionTracker::NetworkConnectionObserver:
   void OnConnectionChanged(network::mojom::ConnectionType) override;
 
+  bool IsOffline() const VALID_CONTEXT_REQUIRED(sequence_checker_);
+
   // Fires whenever a reporting time is reached for a report. Must be updated
   // whenever the next report time changes.
   base::WallClockTimer reporting_time_reached_timer_
@@ -91,7 +96,8 @@
   const std::unique_ptr<Delegate> delegate_
       GUARDED_BY_CONTEXT(sequence_checker_);
 
-  bool offline_ GUARDED_BY_CONTEXT(sequence_checker_) = true;
+  network::mojom::ConnectionType connection_type_ GUARDED_BY_CONTEXT(
+      sequence_checker_) = network::mojom::ConnectionType::CONNECTION_NONE;
 
   base::ScopedObservation<
       network::NetworkConnectionTracker,
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager.h b/content/browser/attribution_reporting/attribution_data_host_manager.h
index 75f1b36..a941ec7 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager.h
+++ b/content/browser/attribution_reporting/attribution_data_host_manager.h
@@ -53,7 +53,7 @@
 
   // Registers a new data host which is associated with a navigation. The
   // context origin will be provided at a later time in
-  // `NotifyNavigationForDataHost()` called with the same
+  // `NotifyNavigationStartedForDataHost()` called with the same
   // `attribution_src_token`. Returns `false` if `attribution_src_token` was
   // already registered.
   virtual bool RegisterNavigationDataHost(
@@ -75,20 +75,21 @@
       bool is_within_fenced_frame,
       GlobalRenderFrameHostId render_frame_id) = 0;
 
-  // Notifies the manager that we have received a navigation for a given data
-  // host. This may arrive before or after the attribution configuration is
-  // available for a given data host. Passes the topmost ancestor of the
-  // initiator render frame for obtaining the page access report.
-  virtual void NotifyNavigationForDataHost(
+  // Notifies the manager that we have received a navigation has started for a
+  // given data host. This may arrive before or after the attribution
+  // configuration is available for a given data host. Passes the topmost
+  // ancestor of the initiator render frame for obtaining the page access
+  // report.
+  virtual void NotifyNavigationStartedForDataHost(
       const blink::AttributionSrcToken& attribution_src_token,
       const attribution_reporting::SuitableOrigin& source_origin,
       blink::mojom::AttributionNavigationType nav_type,
       bool is_within_fenced_frame,
       GlobalRenderFrameHostId render_frame_id) = 0;
 
-  // Notifies the manager that a navigation associated with a data host failed
-  // and should no longer be tracked.
-  virtual void NotifyNavigationFailure(
+  // Notifies the manager that a navigation associated with
+  // `attribution_src_token` finished and should no longer be tracked.
+  virtual void NotifyNavigationFinished(
       const blink::AttributionSrcToken& attribution_src_token) = 0;
 
   // Notifies the manager that a fenced frame reporting beacon was initiated
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
index dce5112..fda2ec64 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
@@ -97,14 +97,16 @@
 enum class NavigationDataHostStatus {
   kRegistered = 0,
   kNotFound = 1,
-  kNavigationFailed = 2,
+  // Ineligible navigation data hosts (non top-level navigations, same document
+  // navigations, etc) are dropped.
+  kIneligible = 2,
   kProcessed = 3,
 
   kMaxValue = kProcessed,
 };
 
 void RecordNavigationDataHostStatus(NavigationDataHostStatus event) {
-  base::UmaHistogramEnumeration("Conversions.NavigationDataHostStatus2", event);
+  base::UmaHistogramEnumeration("Conversions.NavigationDataHostStatus3", event);
 }
 
 enum class Registrar {
@@ -500,12 +502,17 @@
   }
 }
 
-void AttributionDataHostManagerImpl::NotifyNavigationForDataHost(
+void AttributionDataHostManagerImpl::NotifyNavigationStartedForDataHost(
     const blink::AttributionSrcToken& attribution_src_token,
     const SuitableOrigin& source_origin,
     AttributionNavigationType nav_type,
     bool is_within_fenced_frame,
     GlobalRenderFrameHostId render_frame_id) {
+  // A navigation-associated interface is used for
+  // `blink::mojom::ConversionHost` and an `AssociatedReceiver` is used on the
+  // browser side, therefore it's guaranteed that
+  // `AttributionHost::RegisterNavigationHost()` is called before
+  // `AttributionHost::DidStartNavigation()`.
   if (auto it = navigation_data_host_map_.find(attribution_src_token);
       it != navigation_data_host_map_.end()) {
     receivers_.Add(
@@ -520,22 +527,22 @@
   } else {
     RecordNavigationDataHostStatus(NavigationDataHostStatus::kNotFound);
   }
-
-  if (auto it = registrations_.find(attribution_src_token);
-      it != registrations_.end()) {
-    it->CompleteRegistrations();
-    MaybeOnRegistrationsFinished(it);
-  }
 }
 
-void AttributionDataHostManagerImpl::NotifyNavigationFailure(
+void AttributionDataHostManagerImpl::NotifyNavigationFinished(
     const blink::AttributionSrcToken& attribution_src_token) {
+  // The eligible data host should have been bound in
+  // `NotifyNavigationStartedForDataHost()`.
+  // For non-top level navigation and same document navigation,
+  // `AttributionHost::RegisterNavigationDataHost()` will be called but not
+  // `NotifyNavigationStartedForDataHost()`, therefore these navigations would
+  // still be tracked.
   if (auto it = navigation_data_host_map_.find(attribution_src_token);
       it != navigation_data_host_map_.end()) {
     base::TimeTicks register_time = it->second.register_time;
     navigation_data_host_map_.erase(it);
     OnSourceEligibleDataHostFinished(register_time);
-    RecordNavigationDataHostStatus(NavigationDataHostStatus::kNavigationFailed);
+    RecordNavigationDataHostStatus(NavigationDataHostStatus::kIneligible);
   }
 
   // We are not guaranteed to be processing redirect registrations for a given
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.h b/content/browser/attribution_reporting/attribution_data_host_manager_impl.h
index c9b577a3..9eeb13b2 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.h
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.h
@@ -94,13 +94,13 @@
       blink::mojom::AttributionNavigationType nav_type,
       bool is_within_fenced_frame,
       GlobalRenderFrameHostId render_frame_id) override;
-  void NotifyNavigationForDataHost(
+  void NotifyNavigationStartedForDataHost(
       const blink::AttributionSrcToken& attribution_src_token,
       const attribution_reporting::SuitableOrigin& source_origin,
       blink::mojom::AttributionNavigationType nav_type,
       bool is_within_fenced_frame,
       GlobalRenderFrameHostId render_frame_id) override;
-  void NotifyNavigationFailure(
+  void NotifyNavigationFinished(
       const blink::AttributionSrcToken& attribution_src_token) override;
   void NotifyFencedFrameReportingBeaconStarted(
       BeaconId beacon_id,
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
index c316919..cda0e65 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
@@ -98,6 +98,9 @@
 constexpr char kRegisterSourceJson[] =
     R"json({"source_event_id":"5","destination":"https://destination.example"})json";
 
+constexpr char kNavigationDataHostStatusHistogram[] =
+    "Conversions.NavigationDataHostStatus3";
+
 const GlobalRenderFrameHostId kFrameId = {0, 1};
 
 constexpr BeaconId kBeaconId(123);
@@ -536,7 +539,7 @@
 
     task_environment_.FastForwardBy(base::Milliseconds(1));
 
-    data_host_manager_.NotifyNavigationForDataHost(
+    data_host_manager_.NotifyNavigationStartedForDataHost(
         attribution_src_token, page_origin,
         AttributionNavigationType::kContextMenu,
         /*is_within_fenced_frame=*/false, kFrameId);
@@ -566,8 +569,8 @@
                                    base::Milliseconds(1), 1);
 
   // kRegistered = 0, kProcessed = 3.
-  histograms.ExpectBucketCount("Conversions.NavigationDataHostStatus2", 0, 1);
-  histograms.ExpectBucketCount("Conversions.NavigationDataHostStatus2", 3, 1);
+  histograms.ExpectBucketCount(kNavigationDataHostStatusHistogram, 0, 1);
+  histograms.ExpectBucketCount(kNavigationDataHostStatusHistogram, 3, 1);
 
   // kContextMenu = 2.
   histograms.ExpectBucketCount(
@@ -740,7 +743,7 @@
 }
 
 TEST_F(AttributionDataHostManagerImplTest,
-       NavigationRedirectSource_NavigationFailed) {
+       NavigationRedirectSource_SourceRegisteredBeforeNav) {
   EXPECT_CALL(mock_manager_, HandleSource);
 
   auto reporter = *SuitableOrigin::Deserialize("https://report.test");
@@ -757,12 +760,6 @@
       /*is_within_fenced_frame=*/false, kFrameId);
   // Wait for parsing to finish.
   task_environment_.FastForwardBy(base::TimeDelta());
-
-  data_host_manager_.NotifyNavigationFailure(attribution_src_token);
-
-  data_host_manager_.NotifyNavigationForDataHost(
-      attribution_src_token, source_site, AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
 }
 
 #if BUILDFLAG(IS_ANDROID)
@@ -857,7 +854,7 @@
 }
 
 TEST_F(AttributionDataHostManagerImplTest,
-       NavigationRedirectSource_NavigationFailedBeforeParsing) {
+       NavigationRedirectSource_NavigationFinishesBeforeParsing) {
   EXPECT_CALL(mock_manager_, HandleSource);
 
   auto reporter = *SuitableOrigin::Deserialize("https://report.test");
@@ -872,7 +869,7 @@
       attribution_src_token, headers.get(), reporter, source_site,
       AttributionInputEvent(), AttributionNavigationType::kAnchor,
       /*is_within_fenced_frame=*/false, kFrameId);
-  data_host_manager_.NotifyNavigationFailure(attribution_src_token);
+  data_host_manager_.NotifyNavigationFinished(attribution_src_token);
 
   // Wait for parsing to finish.
   task_environment_.FastForwardBy(base::TimeDelta());
@@ -904,9 +901,7 @@
       AttributionInputEvent(), AttributionNavigationType::kAnchor,
       /*is_within_fenced_frame=*/false, kFrameId);
 
-  data_host_manager_.NotifyNavigationForDataHost(
-      attribution_src_token, source_site, AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
+  data_host_manager_.NotifyNavigationFinished(attribution_src_token);
 
   // Wait for parsing to finish.
   task_environment_.FastForwardBy(base::TimeDelta());
@@ -945,9 +940,7 @@
       AttributionInputEvent(), AttributionNavigationType::kAnchor,
       /*is_within_fenced_frame=*/false, kFrameId);
 
-  data_host_manager_.NotifyNavigationForDataHost(
-      attribution_src_token, source_site, AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
+  data_host_manager_.NotifyNavigationFinished(attribution_src_token);
 
   // Wait for parsing to finish.
   task_environment_.FastForwardBy(base::TimeDelta());
@@ -1043,9 +1036,7 @@
 
   // Wait for parsing.
   task_environment_.FastForwardBy(base::TimeDelta());
-  data_host_manager_.NotifyNavigationForDataHost(
-      attribution_src_token, source_site, AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
+  data_host_manager_.NotifyNavigationFinished(attribution_src_token);
 
   checkpoint.Call(1);
 
@@ -1096,9 +1087,7 @@
       /*is_within_fenced_frame=*/false, kFrameId);
 
   // Wait for parsing.
-  data_host_manager_.NotifyNavigationForDataHost(
-      attribution_src_token, source_site, AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
+  data_host_manager_.NotifyNavigationFinished(attribution_src_token);
 
   task_environment_.FastForwardBy(base::TimeDelta());
   checkpoint.Call(1);
@@ -1215,9 +1204,12 @@
       /*is_within_fenced_frame=*/false, RegistrationType::kSourceOrTrigger,
       kFrameId);
 
+  // `AttributionDataHostManager::NotifyNavigationStartedForDataHost()` is not
+  // called, therefore the data host is not bound.
+
   task_environment_.FastForwardBy(base::Milliseconds(1));
 
-  data_host_manager_.NotifyNavigationFailure(attribution_src_token);
+  data_host_manager_.NotifyNavigationFinished(attribution_src_token);
 
   trigger_data_host_remote->TriggerDataAvailable(
       /*reporting_origin=*/*SuitableOrigin::Deserialize("https://report.test"),
@@ -1230,9 +1222,9 @@
   histograms.ExpectTimeBucketCount("Conversions.SourceEligibleDataHostLifeTime",
                                    base::Milliseconds(1), 2);
 
-  // kRegistered = 0, kNavigationFailed = 2.
-  histograms.ExpectBucketCount("Conversions.NavigationDataHostStatus2", 0, 1);
-  histograms.ExpectBucketCount("Conversions.NavigationDataHostStatus2", 2, 1);
+  // kRegistered = 0, kIneligible = 2.
+  histograms.ExpectBucketCount(kNavigationDataHostStatusHistogram, 0, 1);
+  histograms.ExpectBucketCount(kNavigationDataHostStatusHistogram, 2, 1);
 }
 
 TEST_F(AttributionDataHostManagerImplTest,
@@ -1466,14 +1458,14 @@
   base::HistogramTester histograms;
 
   const blink::AttributionSrcToken attribution_src_token;
-  data_host_manager_.NotifyNavigationForDataHost(
+  data_host_manager_.NotifyNavigationStartedForDataHost(
       attribution_src_token,
       *SuitableOrigin::Deserialize("https://page.example"),
       AttributionNavigationType::kAnchor, /*is_within_fenced_frame=*/false,
       kFrameId);
 
   // kNotFound = 1.
-  histograms.ExpectUniqueSample("Conversions.NavigationDataHostStatus2", 1, 1);
+  histograms.ExpectUniqueSample(kNavigationDataHostStatusHistogram, 1, 1);
 }
 
 TEST_F(AttributionDataHostManagerImplTest,
@@ -1488,7 +1480,7 @@
       data_host_remote.BindNewPipeAndPassReceiver(), attribution_src_token,
       AttributionInputEvent());
 
-  data_host_manager_.NotifyNavigationForDataHost(
+  data_host_manager_.NotifyNavigationStartedForDataHost(
       attribution_src_token, *SuitableOrigin::Deserialize("https://s.test"),
       AttributionNavigationType::kAnchor, /*is_within_fenced_frame=*/false,
       kFrameId);
@@ -1531,14 +1523,13 @@
         AttributionInputEvent()));
 
     // kRegistered = 0.
-    histograms.ExpectUniqueSample("Conversions.NavigationDataHostStatus2", 0,
-                                  1);
+    histograms.ExpectUniqueSample(kNavigationDataHostStatusHistogram, 0, 1);
   }
 
   const auto destination_site =
       net::SchemefulSite::Deserialize("https://trigger.example");
 
-  data_host_manager_.NotifyNavigationForDataHost(
+  data_host_manager_.NotifyNavigationStartedForDataHost(
       attribution_src_token,
       *SuitableOrigin::Deserialize("https://page.example"),
       AttributionNavigationType::kAnchor, /*is_within_fenced_frame=*/false,
@@ -1630,7 +1621,7 @@
       data_host_remote.BindNewPipeAndPassReceiver(), attribution_src_token,
       AttributionInputEvent());
 
-  data_host_manager_.NotifyNavigationForDataHost(
+  data_host_manager_.NotifyNavigationStartedForDataHost(
       attribution_src_token,
       /*source_origin=*/*SuitableOrigin::Deserialize("https://source.test"),
       AttributionNavigationType::kAnchor, /*is_within_fenced_frame=*/true,
@@ -1664,7 +1655,7 @@
 }
 
 TEST_F(AttributionDataHostManagerImplTest,
-       NavigationBeaconSource_NavigationFailedBeforeAndAfterParsing) {
+       NavigationBeaconSource_NavigationFinishesBeforeAndAfterParsing) {
   EXPECT_CALL(mock_manager_, HandleSource).Times(2);
 
   auto reporting_origin = url::Origin::Create(GURL("https://report.test"));
@@ -1689,14 +1680,14 @@
       kBeaconId, std::move(reporting_origin), headers.get(),
       /*is_final_response=*/true);
 
-  data_host_manager_.NotifyNavigationFailure(blink::AttributionSrcToken());
+  data_host_manager_.NotifyNavigationFinished(blink::AttributionSrcToken());
 
   // Wait for parsing to finish.
   task_environment_.FastForwardBy(base::TimeDelta());
 }
 
 TEST_F(AttributionDataHostManagerImplTest,
-       NavigationBeaconSource_NavigationFailedBeforeAndAfterData) {
+       NavigationBeaconSource_NavigationFinishesBeforeAndAfterData) {
   EXPECT_CALL(mock_manager_, HandleSource).Times(2);
 
   auto reporting_origin = url::Origin::Create(GURL("https://report.test"));
@@ -1717,7 +1708,7 @@
   // Wait for parsing to finish.
   task_environment_.FastForwardBy(base::TimeDelta());
 
-  data_host_manager_.NotifyNavigationFailure(blink::AttributionSrcToken());
+  data_host_manager_.NotifyNavigationFinished(blink::AttributionSrcToken());
 
   data_host_manager_.NotifyFencedFrameReportingBeaconData(
       kBeaconId, std::move(reporting_origin), headers.get(),
@@ -1758,10 +1749,7 @@
       /*is_final_response=*/true);
 
   // This is irrelevant to beacon source registrations.
-  data_host_manager_.NotifyNavigationForDataHost(
-      blink::AttributionSrcToken(), source_origin,
-      AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
+  data_host_manager_.NotifyNavigationFinished(blink::AttributionSrcToken());
 
   // Wait for parsing to finish.
   task_environment_.FastForwardBy(base::TimeDelta());
@@ -1808,10 +1796,7 @@
       /*is_final_response=*/true);
 
   // This is irrelevant to beacon source registrations.
-  data_host_manager_.NotifyNavigationForDataHost(
-      blink::AttributionSrcToken(), source_origin,
-      AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
+  data_host_manager_.NotifyNavigationFinished(blink::AttributionSrcToken());
 
   // Wait for parsing to finish.
   task_environment_.FastForwardBy(base::TimeDelta());
@@ -1852,10 +1837,7 @@
       /*is_final_response=*/true);
 
   // This is irrelevant to beacon source registrations.
-  data_host_manager_.NotifyNavigationForDataHost(
-      blink::AttributionSrcToken(), source_origin,
-      AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
+  data_host_manager_.NotifyNavigationFinished(blink::AttributionSrcToken());
 
   // Wait for parsing to finish.
   task_environment_.FastForwardBy(base::TimeDelta());
@@ -1886,10 +1868,7 @@
   task_environment_.FastForwardBy(base::TimeDelta());
 
   // This is irrelevant to beacon source registrations.
-  data_host_manager_.NotifyNavigationForDataHost(
-      blink::AttributionSrcToken(), source_origin,
-      AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
+  data_host_manager_.NotifyNavigationFinished(blink::AttributionSrcToken());
 
   data_host_manager_.NotifyFencedFrameReportingBeaconData(
       kBeaconId, std::move(reporting_origin), headers.get(),
@@ -1923,10 +1902,7 @@
   task_environment_.FastForwardBy(base::TimeDelta());
 
   // This is irrelevant to beacon source registrations.
-  data_host_manager_.NotifyNavigationForDataHost(
-      blink::AttributionSrcToken(), source_origin,
-      AttributionNavigationType::kAnchor,
-      /*is_within_fenced_frame=*/false, kFrameId);
+  data_host_manager_.NotifyNavigationFinished(blink::AttributionSrcToken());
 }
 
 TEST_F(AttributionDataHostManagerImplTest,
diff --git a/content/browser/attribution_reporting/attribution_host.cc b/content/browser/attribution_reporting/attribution_host.cc
index 9c0d16cd..ae0ca2a 100644
--- a/content/browser/attribution_reporting/attribution_host.cc
+++ b/content/browser/attribution_reporting/attribution_host.cc
@@ -118,11 +118,25 @@
 }
 
 void AttributionHost::DidStartNavigation(NavigationHandle* navigation_handle) {
-  DCHECK(AttributionManager::FromWebContents(web_contents()));
+  auto* attribution_manager =
+      AttributionManager::FromWebContents(web_contents());
+  DCHECK(attribution_manager);
+
+  auto* data_host_manager = attribution_manager->GetDataHostManager();
+  if (!data_host_manager) {
+    return;
+  }
+
+  const auto& impression = navigation_handle->GetImpression();
+
+  // TODO(crbug.com/1428315): Consider checking for navigations taking place in
+  // a prerendered main frame.
 
   // Impression navigations need to navigate the primary main frame to be valid.
-  if (!navigation_handle->GetImpression() ||
-      !navigation_handle->IsInPrimaryMainFrame()) {
+  // Impressions should never be attached to same-document navigations but can
+  // be the result of a bad renderer.
+  if (!impression || !navigation_handle->IsInPrimaryMainFrame() ||
+      navigation_handle->IsSameDocument()) {
     return;
   }
   RenderFrameHostImpl* initiator_frame_host =
@@ -165,7 +179,7 @@
     return;
   }
 
-  navigation_info_map_.emplace(
+  auto [it, inserted] = navigation_info_map_.try_emplace(
       navigation_handle->GetNavigationId(),
       NavigationInfo{
           .source_origin = std::move(*initiator_root_frame_origin),
@@ -173,10 +187,16 @@
               AttributionHost::FromWebContents(
                   WebContents::FromRenderFrameHost(initiator_frame_host))
                   ->GetMostRecentNavigationInputEvent(),
-
           .is_within_fenced_frame =
               initiator_frame_host->IsNestedWithinFencedFrame(),
           .initiator_root_frame_id = initiator_root_frame->GetGlobalId()});
+  DCHECK(inserted);
+
+  const NavigationInfo& navigation_info = it->second;
+  data_host_manager->NotifyNavigationStartedForDataHost(
+      impression->attribution_src_token, navigation_info.source_origin,
+      impression->nav_type, navigation_info.is_within_fenced_frame,
+      navigation_info.initiator_root_frame_id);
 }
 
 void AttributionHost::DidRedirectNavigation(
@@ -186,7 +206,7 @@
     return;
   }
 
-  const auto impression = navigation_handle->GetImpression();
+  const auto& impression = navigation_handle->GetImpression();
   DCHECK(impression.has_value());
 
   auto* attribution_manager =
@@ -222,63 +242,17 @@
 }
 
 void AttributionHost::DidFinishNavigation(NavigationHandle* navigation_handle) {
+  ScopedMapDeleter<NavigationInfoMap> navigation_source_origin_it(
+      &navigation_info_map_, navigation_handle->GetNavigationId());
+
   // Observe only navigation toward a new document in the primary main frame.
   // Impressions should never be attached to same-document navigations but can
   // be the result of a bad renderer.
   if (!navigation_handle->IsInPrimaryMainFrame() ||
       navigation_handle->IsSameDocument()) {
-    MaybeNotifyFailedSourceNavigation(navigation_handle);
-    return;
+    DCHECK(!navigation_source_origin_it);
   }
 
-  ScopedMapDeleter<NavigationInfoMap> navigation_source_origin_it(
-      &navigation_info_map_, navigation_handle->GetNavigationId());
-
-  // Separate from above because we need to clear the navigation related state
-  if (!navigation_handle->HasCommitted()) {
-    MaybeNotifyFailedSourceNavigation(navigation_handle);
-    return;
-  }
-
-  // Don't observe error page navs, and don't let impressions be registered for
-  // error pages.
-  if (navigation_handle->IsErrorPage()) {
-    MaybeNotifyFailedSourceNavigation(navigation_handle);
-    return;
-  }
-
-  // If we were not able to access the impression origin, ignore the
-  // navigation.
-  if (!navigation_source_origin_it) {
-    MaybeNotifyFailedSourceNavigation(navigation_handle);
-    return;
-  }
-
-  AttributionManager* attribution_manager =
-      AttributionManager::FromWebContents(web_contents());
-  DCHECK(attribution_manager);
-
-  auto* data_host_manager = attribution_manager->GetDataHostManager();
-  if (!data_host_manager) {
-    return;
-  }
-
-  const NavigationInfo& navigation_info =
-      (*navigation_source_origin_it.get())->second;
-  const SuitableOrigin& source_origin = navigation_info.source_origin;
-
-  const absl::optional<blink::Impression>& impression =
-      navigation_handle->GetImpression();
-  DCHECK(impression);
-
-  data_host_manager->NotifyNavigationForDataHost(
-      impression->attribution_src_token, source_origin, impression->nav_type,
-      navigation_info.is_within_fenced_frame,
-      navigation_info.initiator_root_frame_id);
-}
-
-void AttributionHost::MaybeNotifyFailedSourceNavigation(
-    NavigationHandle* navigation_handle) {
   auto* attribution_manager =
       AttributionManager::FromWebContents(web_contents());
   DCHECK(attribution_manager);
@@ -288,13 +262,14 @@
     return;
   }
 
-  absl::optional<blink::Impression> impression =
+  const absl::optional<blink::Impression>& impression =
       navigation_handle->GetImpression();
   if (!impression) {
     return;
   }
 
-  data_host_manager->NotifyNavigationFailure(impression->attribution_src_token);
+  data_host_manager->NotifyNavigationFinished(
+      impression->attribution_src_token);
 }
 
 absl::optional<SuitableOrigin>
@@ -346,11 +321,12 @@
 void AttributionHost::RegisterDataHost(
     mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host,
     attribution_reporting::mojom::RegistrationType registration_type) {
-  // If there is no attribution manager available, ignore any registrations.
   AttributionManager* attribution_manager =
       AttributionManager::FromWebContents(web_contents());
   DCHECK(attribution_manager);
 
+  // If there is no attribution data host manager available, ignore any
+  // registrations.
   AttributionDataHostManager* data_host_manager =
       attribution_manager->GetDataHostManager();
   if (!data_host_manager) {
@@ -406,17 +382,17 @@
 
 // static
 void AttributionHost::BindReceiver(
-    mojo::PendingAssociatedReceiver<blink::mojom::ConversionHost> receiver,
+    mojo::PendingAssociatedReceiver<blink::mojom::AttributionHost> receiver,
     RenderFrameHost* rfh) {
   auto* web_contents = WebContents::FromRenderFrameHost(rfh);
   if (!web_contents) {
     return;
   }
-  auto* conversion_host = AttributionHost::FromWebContents(web_contents);
-  if (!conversion_host) {
+  auto* attribution_host = AttributionHost::FromWebContents(web_contents);
+  if (!attribution_host) {
     return;
   }
-  conversion_host->receivers_.Bind(rfh, std::move(receiver));
+  attribution_host->receivers_.Bind(rfh, std::move(receiver));
 }
 
 void AttributionHost::NotifyFencedFrameReportingBeaconStarted(
diff --git a/content/browser/attribution_reporting/attribution_host.h b/content/browser/attribution_reporting/attribution_host.h
index ba4e72a..77e9091 100644
--- a/content/browser/attribution_reporting/attribution_host.h
+++ b/content/browser/attribution_reporting/attribution_host.h
@@ -43,7 +43,7 @@
 class CONTENT_EXPORT AttributionHost
     : public WebContentsObserver,
       public WebContentsUserData<AttributionHost>,
-      public blink::mojom::ConversionHost {
+      public blink::mojom::AttributionHost {
  public:
   explicit AttributionHost(WebContents* web_contents);
   AttributionHost(const AttributionHost&) = delete;
@@ -53,7 +53,7 @@
   ~AttributionHost() override;
 
   static void BindReceiver(
-      mojo::PendingAssociatedReceiver<blink::mojom::ConversionHost> receiver,
+      mojo::PendingAssociatedReceiver<blink::mojom::AttributionHost> receiver,
       RenderFrameHost* rfh);
 
 #if BUILDFLAG(IS_ANDROID)
@@ -81,7 +81,7 @@
   friend class AttributionHostTestPeer;
   friend class WebContentsUserData<AttributionHost>;
 
-  // blink::mojom::ConversionHost:
+  // blink::mojom::AttributionHost:
   void RegisterDataHost(
       mojo::PendingReceiver<blink::mojom::AttributionDataHost>,
       attribution_reporting::mojom::RegistrationType) override;
@@ -101,10 +101,6 @@
   absl::optional<attribution_reporting::SuitableOrigin>
   TopFrameOriginForSecureContext();
 
-  // Notifies the `AttributionDataHostManager` that a navigation with an
-  // associated `AttributionDataHost` failed, if necessary.
-  void MaybeNotifyFailedSourceNavigation(NavigationHandle* navigation_handle);
-
   AttributionInputEvent GetMostRecentNavigationInputEvent() const;
 
   // Map which stores the top-frame origin an impression occurred on for all
@@ -123,7 +119,7 @@
   using NavigationInfoMap = base::flat_map<int64_t, NavigationInfo>;
   NavigationInfoMap navigation_info_map_;
 
-  RenderFrameHostReceiverSet<blink::mojom::ConversionHost> receivers_;
+  RenderFrameHostReceiverSet<blink::mojom::AttributionHost> receivers_;
 
 #if BUILDFLAG(IS_ANDROID)
   std::unique_ptr<AttributionInputEventTrackerAndroid>
diff --git a/content/browser/attribution_reporting/attribution_host_unittest.cc b/content/browser/attribution_reporting/attribution_host_unittest.cc
index 33eaa38..a6fce3a 100644
--- a/content/browser/attribution_reporting/attribution_host_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_host_unittest.cc
@@ -52,9 +52,9 @@
 class AttributionHostTestPeer {
  public:
   static void SetCurrentTargetFrameForTesting(
-      AttributionHost* conversion_host,
+      AttributionHost* attribution_host,
       RenderFrameHost* render_frame_host) {
-    conversion_host->receivers_.SetCurrentTargetFrameForTesting(
+    attribution_host->receivers_.SetCurrentTargetFrameForTesting(
         render_frame_host);
   }
 };
@@ -105,16 +105,16 @@
     return static_cast<TestWebContents*>(web_contents());
   }
 
-  blink::mojom::ConversionHost* conversion_host_mojom() {
-    return conversion_host();
+  blink::mojom::AttributionHost* attribution_host_mojom() {
+    return attribution_host();
   }
 
-  AttributionHost* conversion_host() {
+  AttributionHost* attribution_host() {
     return AttributionHost::FromWebContents(web_contents());
   }
 
   void SetCurrentTargetFrameForTesting(RenderFrameHost* render_frame_host) {
-    AttributionHostTestPeer::SetCurrentTargetFrameForTesting(conversion_host(),
+    AttributionHostTestPeer::SetCurrentTargetFrameForTesting(attribution_host(),
                                                              render_frame_host);
   }
 
@@ -140,7 +140,8 @@
 };
 
 TEST_F(AttributionHostTest, NavigationWithNoImpression_Ignored) {
-  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationForDataHost).Times(0);
+  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationStartedForDataHost)
+      .Times(0);
 
   contents()->NavigateAndCommit(GURL("https://secure_impression.com"));
   NavigationSimulatorImpl::NavigateAndCommitFromDocument(GURL(kConversionUrl),
@@ -152,7 +153,7 @@
   impression.nav_type = AttributionNavigationType::kWindowOpen;
 
   EXPECT_CALL(*mock_data_host_manager(),
-              NotifyNavigationForDataHost(
+              NotifyNavigationStartedForDataHost(
                   impression.attribution_src_token,
                   *SuitableOrigin::Deserialize("https://secure_impression.com"),
                   impression.nav_type,
@@ -167,7 +168,8 @@
 }
 
 TEST_F(AttributionHostTest, ImpressionInSubframe_Ignored) {
-  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationForDataHost).Times(0);
+  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationStartedForDataHost)
+      .Times(0);
 
   contents()->NavigateAndCommit(GURL("https://secure_impression.com"));
 
@@ -187,7 +189,8 @@
 // Test that if we cannot access the initiator frame of the navigation, we
 // ignore the associated impression.
 TEST_F(AttributionHostTest, ImpressionNavigationWithDeadInitiator_Ignored) {
-  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationForDataHost).Times(0);
+  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationStartedForDataHost)
+      .Times(0);
 
   base::HistogramTester histograms;
 
@@ -204,25 +207,12 @@
       "Conversions.ImpressionNavigationHasDeadInitiator", true, 1);
 }
 
-TEST_F(AttributionHostTest, ImpressionNavigationCommitsToErrorPage_Ignored) {
-  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationForDataHost).Times(0);
-
-  contents()->NavigateAndCommit(GURL("https://secure_impression.com"));
-
-  auto navigation = NavigationSimulatorImpl::CreateRendererInitiated(
-      GURL(kConversionUrl), main_rfh());
-  navigation->SetInitiatorFrame(main_rfh());
-  navigation->set_impression(blink::Impression());
-  navigation->Fail(net::ERR_FAILED);
-  navigation->CommitErrorPage();
-}
-
 TEST_F(AttributionHostTest,
-       AttributionSrcNavigationCommitsToErrorPage_Ignored) {
+       AttributionSrcNavigationCommitsToErrorPage_Notified) {
   blink::Impression impression;
 
   EXPECT_CALL(*mock_data_host_manager(),
-              NotifyNavigationFailure(impression.attribution_src_token));
+              NotifyNavigationFinished(impression.attribution_src_token));
 
   contents()->NavigateAndCommit(GURL("https://secure_impression.com"));
 
@@ -234,23 +224,11 @@
   navigation->CommitErrorPage();
 }
 
-TEST_F(AttributionHostTest, ImpressionNavigationAborts_Ignored) {
-  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationForDataHost).Times(0);
-
-  contents()->NavigateAndCommit(GURL("https://secure_impression.com"));
-
-  auto navigation = NavigationSimulatorImpl::CreateRendererInitiated(
-      GURL(kConversionUrl), main_rfh());
-  navigation->SetInitiatorFrame(main_rfh());
-  navigation->set_impression(blink::Impression());
-  navigation->AbortCommit();
-}
-
-TEST_F(AttributionHostTest, AttributionSrcNavigationAborts_Ignored) {
+TEST_F(AttributionHostTest, AttributionSrcNavigationAborts_Notified) {
   blink::Impression impression;
 
   EXPECT_CALL(*mock_data_host_manager(),
-              NotifyNavigationFailure(impression.attribution_src_token));
+              NotifyNavigationFinished(impression.attribution_src_token));
 
   contents()->NavigateAndCommit(GURL("https://secure_impression.com"));
 
@@ -262,8 +240,8 @@
 }
 
 TEST_F(AttributionHostTest,
-       CommittedOriginDiffersFromConversionDesintation_Propagated) {
-  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationForDataHost);
+       CommittedOriginDiffersFromConversionDesintation_Notified) {
+  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationFinished);
 
   contents()->NavigateAndCommit(GURL("https://secure_impression.com"));
 
@@ -311,11 +289,8 @@
        ImpressionNavigation_OriginTrustworthyChecksPerformed) {
   const OriginTrustworthyChecksTestCase& test_case = GetParam();
 
-  if (test_case.expected_valid) {
-    EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationForDataHost);
-  } else {
-    EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationFailure);
-  }
+  EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationStartedForDataHost)
+      .Times(test_case.expected_valid);
 
   contents()->NavigateAndCommit(GURL(test_case.source_origin));
   auto navigation = NavigationSimulatorImpl::CreateRendererInitiated(
@@ -346,7 +321,7 @@
   mojo::test::BadMessageObserver bad_message_observer;
 
   mojo::Remote<blink::mojom::AttributionDataHost> data_host_remote;
-  conversion_host_mojom()->RegisterDataHost(
+  attribution_host_mojom()->RegisterDataHost(
       data_host_remote.BindNewPipeAndPassReceiver(), RegistrationType::kSource);
 
   // Run loop to allow the bad message code to run if a bad message was
@@ -365,11 +340,11 @@
   mojo::test::BadMessageObserver bad_message_observer;
 
   mojo::Remote<blink::mojom::AttributionDataHost> data_host_remote;
-  conversion_host_mojom()->RegisterDataHost(
+  attribution_host_mojom()->RegisterDataHost(
       data_host_remote.BindNewPipeAndPassReceiver(), RegistrationType::kSource);
 
   EXPECT_EQ(
-      "blink.mojom.ConversionHost can only be used with a secure top-level "
+      "blink.mojom.AttributionHost can only be used with a secure top-level "
       "frame.",
       bad_message_observer.WaitForBadMessage());
 }
@@ -385,12 +360,12 @@
   mojo::test::BadMessageObserver bad_message_observer;
 
   mojo::Remote<blink::mojom::AttributionDataHost> data_host_remote;
-  conversion_host_mojom()->RegisterNavigationDataHost(
+  attribution_host_mojom()->RegisterNavigationDataHost(
       data_host_remote.BindNewPipeAndPassReceiver(),
       blink::AttributionSrcToken());
 
   EXPECT_EQ(
-      "blink.mojom.ConversionHost can only be used with a secure top-level "
+      "blink.mojom.AttributionHost can only be used with a secure top-level "
       "frame.",
       bad_message_observer.WaitForBadMessage());
 }
@@ -407,7 +382,7 @@
   mojo::test::BadMessageObserver bad_message_observer;
 
   mojo::Remote<blink::mojom::AttributionDataHost> data_host_remote;
-  conversion_host_mojom()->RegisterNavigationDataHost(
+  attribution_host_mojom()->RegisterNavigationDataHost(
       data_host_remote.BindNewPipeAndPassReceiver(),
       blink::AttributionSrcToken());
 
@@ -438,7 +413,7 @@
   mojo::test::BadMessageObserver bad_message_observer;
 
   mojo::Remote<blink::mojom::AttributionDataHost> data_host_remote;
-  conversion_host_mojom()->RegisterDataHost(
+  attribution_host_mojom()->RegisterDataHost(
       data_host_remote.BindNewPipeAndPassReceiver(), RegistrationType::kSource);
 
   // Run loop to allow the bad message code to run if a bad message was
@@ -464,11 +439,11 @@
   mojo::test::BadMessageObserver bad_message_observer;
 
   mojo::Remote<blink::mojom::AttributionDataHost> data_host_remote;
-  conversion_host_mojom()->RegisterDataHost(
+  attribution_host_mojom()->RegisterDataHost(
       data_host_remote.BindNewPipeAndPassReceiver(), RegistrationType::kSource);
 
   EXPECT_EQ(
-      "blink.mojom.ConversionHost can only be used with a secure top-level "
+      "blink.mojom.AttributionHost can only be used with a secure top-level "
       "frame.",
       bad_message_observer.WaitForBadMessage());
 }
@@ -495,7 +470,7 @@
   mojo::test::BadMessageObserver bad_message_observer;
 
   mojo::Remote<blink::mojom::AttributionDataHost> data_host_remote;
-  conversion_host_mojom()->RegisterDataHost(
+  attribution_host_mojom()->RegisterDataHost(
       data_host_remote.BindNewPipeAndPassReceiver(), RegistrationType::kSource);
 
   // Run loop to allow the bad message code to run if a bad message was
@@ -519,7 +494,7 @@
   fenced_frame = NavigationSimulatorImpl::NavigateAndCommitFromDocument(
       GURL("https://fencedframe.example"), fenced_frame);
 
-  conversion_host()->NotifyFencedFrameReportingBeaconStarted(
+  attribution_host()->NotifyFencedFrameReportingBeaconStarted(
       kBeaconId, kNavigationId,
       static_cast<RenderFrameHostImpl*>(fenced_frame));
 }
@@ -562,7 +537,7 @@
     fenced_frame = NavigationSimulatorImpl::NavigateAndCommitFromDocument(
         GURL("https://fencedframe.example"), fenced_frame);
 
-    conversion_host()->NotifyFencedFrameReportingBeaconStarted(
+    attribution_host()->NotifyFencedFrameReportingBeaconStarted(
         kBeaconId, kNavigationId,
         static_cast<RenderFrameHostImpl*>(fenced_frame));
   }
@@ -610,7 +585,7 @@
     simulator->Commit();
     fenced_frame = simulator->GetFinalRenderFrameHost();
 
-    conversion_host()->NotifyFencedFrameReportingBeaconStarted(
+    attribution_host()->NotifyFencedFrameReportingBeaconStarted(
         kBeaconId, /*navigation_id=*/absl::nullopt,
         static_cast<RenderFrameHostImpl*>(fenced_frame));
   }
@@ -631,7 +606,7 @@
   };
 
   for (const auto& test_case : kTestCases) {
-    EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationForDataHost)
+    EXPECT_CALL(*mock_data_host_manager(), NotifyNavigationStartedForDataHost)
         .Times(test_case.expected);
 
     auto simulator1 = NavigationSimulatorImpl::CreateRendererInitiated(
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.cc b/content/browser/attribution_reporting/attribution_manager_impl.cc
index af59d7d9..1322fac0 100644
--- a/content/browser/attribution_reporting/attribution_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_manager_impl.cc
@@ -73,6 +73,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
+#include "services/network/public/mojom/network_change_manager.mojom-forward.h"
 #include "storage/browser/quota/special_storage_policy.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/features.h"
@@ -218,6 +219,23 @@
   }
 }
 
+void RecordNetworkConnectionTypeOnFailure(
+    AttributionReport::Type report_type,
+    network::mojom::ConnectionType connection_type) {
+  switch (report_type) {
+    case AttributionReport::Type::kEventLevel:
+      base::UmaHistogramEnumeration(
+          "Conversions.EventLevelReport.NetworkConnectionTypeOnFailure",
+          connection_type);
+      break;
+    case AttributionReport::Type::kAggregatableAttribution:
+      base::UmaHistogramEnumeration(
+          "Conversions.AggregatableReport.NetworkConnectionTypeOnFailure",
+          connection_type);
+      break;
+  }
+}
+
 void RecordAssembleAggregatableReportStatus(
     AssembleAggregatableReportStatus status) {
   base::UmaHistogramEnumeration(
@@ -1019,6 +1037,12 @@
     }
   }
 
+  if (info.status == SendResult::Status::kTransientFailure ||
+      info.status == SendResult::Status::kFailure) {
+    RecordNetworkConnectionTypeOnFailure(report.GetReportType(),
+                                         scheduler_timer_.connection_type());
+  }
+
   base::OnceCallback then = base::BindOnce(
       [](base::OnceClosure done, base::WeakPtr<AttributionManagerImpl> manager,
          AttributionReport::Id report_id,
diff --git a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
index 9205c76..7408ddf 100644
--- a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
@@ -69,6 +69,7 @@
 #include "content/public/test/test_utils.h"
 #include "net/base/schemeful_site.h"
 #include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/network_change_manager.mojom.h"
 #include "services/network/test/test_network_connection_tracker.h"
 #include "storage/browser/test/mock_special_storage_policy.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -661,6 +662,9 @@
 
   checkpoint.Call(2);
 
+  SetConnectionTypeAndWaitForObserversToBeNotified(
+      network::mojom::ConnectionType::CONNECTION_2G);
+
   // Second report delay.
   task_environment_.FastForwardBy(base::Minutes(15));
 
@@ -669,6 +673,16 @@
 
   histograms.ExpectTotalCount(
       "Conversions.TimeFromTriggerToReportSentSuccessfully", 0);
+
+  static constexpr char kNetworkConnectionTypeOnFailureHistogram[] =
+      "Conversions.EventLevelReport.NetworkConnectionTypeOnFailure";
+
+  histograms.ExpectBucketCount(
+      kNetworkConnectionTypeOnFailureHistogram,
+      network::mojom::ConnectionType::CONNECTION_UNKNOWN, 2);
+  histograms.ExpectBucketCount(kNetworkConnectionTypeOnFailureHistogram,
+                               network::mojom::ConnectionType::CONNECTION_2G,
+                               1);
 }
 
 TEST_F(AttributionManagerImplTest, RetryLogicOverridesGetReportTimer) {
diff --git a/content/browser/attribution_reporting/test/mock_attribution_data_host_manager.h b/content/browser/attribution_reporting/test/mock_attribution_data_host_manager.h
index 64bdc09a..d665fe3a 100644
--- a/content/browser/attribution_reporting/test/mock_attribution_data_host_manager.h
+++ b/content/browser/attribution_reporting/test/mock_attribution_data_host_manager.h
@@ -62,7 +62,7 @@
               (override));
 
   MOCK_METHOD(void,
-              NotifyNavigationForDataHost,
+              NotifyNavigationStartedForDataHost,
               (const blink::AttributionSrcToken& attribution_src_token,
                const attribution_reporting::SuitableOrigin& source_origin,
                blink::mojom::AttributionNavigationType,
@@ -71,7 +71,7 @@
               (override));
 
   MOCK_METHOD(void,
-              NotifyNavigationFailure,
+              NotifyNavigationFinished,
               (const blink::AttributionSrcToken& attribution_src_token),
               (override));
 
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl_browsertest.cc b/content/browser/bluetooth/web_bluetooth_service_impl_browsertest.cc
index bf641af..e6995cc 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl_browsertest.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
 #include "content/browser/bluetooth/bluetooth_adapter_factory_wrapper.h"
@@ -251,7 +252,9 @@
 
  private:
   std::string device_to_select_;
-  FakeBluetoothScanningPrompt* prompt_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #constexpr-ctor-field-initializer
+  RAW_PTR_EXCLUSION FakeBluetoothScanningPrompt* prompt_ = nullptr;
   base::OnceClosure quit_on_scanning_prompt_;
   bool showed_bluetooth_scanning_prompt_ = false;
 };
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
index 31e6778..be59558 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/test/bind.h"
 #include "base/test/gmock_callback_support.h"
@@ -369,7 +370,9 @@
       FramePermissionObserver* observer) override {}
 
  private:
-  FakeBluetoothScanningPrompt* prompt_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #constexpr-ctor-field-initializer
+  RAW_PTR_EXCLUSION FakeBluetoothScanningPrompt* prompt_ = nullptr;
 };
 
 class TestContentBrowserClient : public ContentBrowserClient {
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index 21e72bb..e4a0c8a 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -142,8 +142,8 @@
 StoragePartition* BrowserContext::GetStoragePartitionForUrl(
     const GURL& url,
     bool can_create) {
-  auto storage_partition_config = SiteInfo::GetStoragePartitionConfigForUrl(
-      this, url, /*is_site_url=*/false);
+  auto storage_partition_config =
+      SiteInfo::GetStoragePartitionConfigForUrl(this, url);
 
   return GetStoragePartition(storage_partition_config, can_create);
 }
diff --git a/content/browser/cache_storage/cache_storage_context_impl.cc b/content/browser/cache_storage/cache_storage_context_impl.cc
index c45f9fc..55aad2d 100644
--- a/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -37,9 +37,9 @@
 CacheStorageContextImpl::~CacheStorageContextImpl() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!storage_keys_to_purge_on_shutdown_.empty()) {
-    cache_manager_->DeleteStorageKeyData(
-        storage_keys_to_purge_on_shutdown_,
+  if (!origins_to_purge_on_shutdown_.empty()) {
+    cache_manager_->DeleteOriginData(
+        origins_to_purge_on_shutdown_,
         storage::mojom::CacheStorageOwner::kCacheAPI,
 
         // Retain a reference to the manager until the deletion is
@@ -157,11 +157,9 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (const auto& update : policy_updates) {
     if (!update->purge_on_shutdown)
-      storage_keys_to_purge_on_shutdown_.erase(
-          blink::StorageKey::CreateFirstParty(update->origin));
+      origins_to_purge_on_shutdown_.erase(update->origin);
     else
-      storage_keys_to_purge_on_shutdown_.insert(
-          blink::StorageKey::CreateFirstParty(std::move(update->origin)));
+      origins_to_purge_on_shutdown_.insert(std::move(update->origin));
   }
 }
 
diff --git a/content/browser/cache_storage/cache_storage_context_impl.h b/content/browser/cache_storage/cache_storage_context_impl.h
index 1a31d8fc..34bf8327 100644
--- a/content/browser/cache_storage/cache_storage_context_impl.h
+++ b/content/browser/cache_storage/cache_storage_context_impl.h
@@ -27,6 +27,7 @@
 #include "storage/browser/quota/quota_manager_proxy.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-forward.h"
+#include "url/origin.h"
 
 namespace base {
 class FilePath;
@@ -104,7 +105,7 @@
       storage::QuotaErrorOr<storage::BucketInfo> result);
 
   // The set of storage keys whose storage should be cleared on shutdown.
-  std::set<blink::StorageKey> storage_keys_to_purge_on_shutdown_;
+  std::set<url::Origin> origins_to_purge_on_shutdown_;
 
   // Initialized in Init(); true if the user data directory is empty.
   bool is_incognito_ = false;
diff --git a/content/browser/cache_storage/cache_storage_manager.cc b/content/browser/cache_storage/cache_storage_manager.cc
index 5e12291c..fc65f3b 100644
--- a/content/browser/cache_storage/cache_storage_manager.cc
+++ b/content/browser/cache_storage/cache_storage_manager.cc
@@ -461,14 +461,12 @@
 // This function considers a bucket to match a storage key if either the
 // bucket's key's origin matches the storage key's origin or the bucket's key is
 // third-party and its top-level site matches the origin.
-bool BucketMatchesStorageKeysForDeletion(
+bool BucketMatchesOriginsForDeletion(
     const storage::BucketLocator& bucket_locator,
-    const std::set<blink::StorageKey>& storage_keys) {
+    const std::set<url::Origin>& origins) {
   auto& bucket_key = bucket_locator.storage_key;
 
-  for (auto& storage_key : storage_keys) {
-    // Only the origin from the storage key is relevant to deletion.
-    auto requested_origin = storage_key.origin();
+  for (auto& requested_origin : origins) {
     if (bucket_key.origin() == requested_origin ||
         (bucket_key.IsThirdPartyContext() &&
          bucket_key.top_level_site() == net::SchemefulSite(requested_origin))) {
@@ -829,8 +827,8 @@
                          weak_ptr_factory_.GetWeakPtr(), std::move(callback))));
 }
 
-void CacheStorageManager::DeleteStorageKeysDataGotAllBucketInfo(
-    const std::set<blink::StorageKey>& storage_keys,
+void CacheStorageManager::DeleteOriginsDataGotAllBucketInfo(
+    const std::set<url::Origin>& origins,
     storage::mojom::CacheStorageOwner owner,
     base::OnceCallback<void(std::vector<blink::mojom::QuotaStatusCode>)>
         callback,
@@ -850,7 +848,7 @@
                         storage::mojom::StorageUsageInfoPtr>& usage_tuple :
        usage_tuples) {
     const storage::BucketLocator bucket_locator = std::get<0>(usage_tuple);
-    if (!BucketMatchesStorageKeysForDeletion(bucket_locator, storage_keys)) {
+    if (!BucketMatchesOriginsForDeletion(bucket_locator, origins)) {
       continue;
     }
     instance_count += 1;
@@ -864,7 +862,7 @@
                         storage::mojom::StorageUsageInfoPtr>& usage_tuple :
        usage_tuples) {
     const storage::BucketLocator bucket_locator = std::get<0>(usage_tuple);
-    if (!BucketMatchesStorageKeysForDeletion(bucket_locator, storage_keys)) {
+    if (!BucketMatchesOriginsForDeletion(bucket_locator, origins)) {
       continue;
     }
     if (!bucket_locator.is_null()) {
@@ -897,17 +895,21 @@
     storage::mojom::QuotaClient::DeleteBucketDataCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  std::set<blink::StorageKey> storage_key_set{storage_key};
-  DeleteStorageKeyData(storage_key_set, owner, std::move(callback));
+  // TODO(https://crbug.com/1376071#c12): This function isn't
+  // actually deleting data for a single key, but rather for
+  // the origin of the key.
+
+  std::set<url::Origin> origin_set{storage_key.origin()};
+  DeleteOriginData(origin_set, owner, std::move(callback));
 }
 
-void CacheStorageManager::DeleteStorageKeyData(
-    const std::set<blink::StorageKey>& storage_keys,
+void CacheStorageManager::DeleteOriginData(
+    const std::set<url::Origin>& origins,
     storage::mojom::CacheStorageOwner owner,
     storage::mojom::QuotaClient::DeleteBucketDataCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (storage_keys.empty()) {
+  if (origins.empty()) {
     scheduler_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback),
                                   blink::mojom::QuotaStatusCode::kOk));
@@ -918,7 +920,7 @@
     std::vector<
         std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>>
         to_delete;
-    to_delete.reserve(storage_keys.size());
+    to_delete.reserve(origins.size());
 
     // Note: since the number of CacheStorage instances is usually small, just
     // search for the corresponding `storage::BucketLocator` keys, given a
@@ -927,7 +929,7 @@
       if (key_value.first.second != owner)
         continue;
       const storage::BucketLocator& bucket_locator = key_value.first.first;
-      if (!BucketMatchesStorageKeysForDeletion(bucket_locator, storage_keys)) {
+      if (!BucketMatchesOriginsForDeletion(bucket_locator, origins)) {
         continue;
       }
       to_delete.emplace_back(bucket_locator,
@@ -935,8 +937,8 @@
                                  bucket_locator.storage_key, 0, base::Time()));
     }
 
-    DeleteStorageKeysDataGotAllBucketInfo(
-        storage_keys, owner,
+    DeleteOriginsDataGotAllBucketInfo(
+        origins, owner,
         base::BindOnce(&DeleteStorageKeyDidDeleteAllData, std::move(callback)),
         std::move(to_delete));
     return;
@@ -957,8 +959,8 @@
           base::WrapRefCounted(scheduler_task_runner_.get()),
           std::move(usage_tuples), profile_path_, owner,
           base::BindOnce(
-              &CacheStorageManager::DeleteStorageKeysDataGotAllBucketInfo,
-              weak_ptr_factory_.GetWeakPtr(), storage_keys, owner,
+              &CacheStorageManager::DeleteOriginsDataGotAllBucketInfo,
+              weak_ptr_factory_.GetWeakPtr(), origins, owner,
               base::BindOnce(&DeleteStorageKeyDidDeleteAllData,
                              std::move(callback)))));
 }
diff --git a/content/browser/cache_storage/cache_storage_manager.h b/content/browser/cache_storage/cache_storage_manager.h
index 2d16c22..0e2d86f4 100644
--- a/content/browser/cache_storage/cache_storage_manager.h
+++ b/content/browser/cache_storage/cache_storage_manager.h
@@ -30,6 +30,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
+#include "url/origin.h"
 
 namespace base {
 class SequencedTaskRunner;
@@ -97,8 +98,8 @@
       const blink::StorageKey& storage_key,
       storage::mojom::CacheStorageOwner owner,
       storage::mojom::QuotaClient::DeleteBucketDataCallback callback);
-  void DeleteStorageKeyData(
-      const std::set<blink::StorageKey>& storage_keys,
+  void DeleteOriginData(
+      const std::set<url::Origin>& origins,
       storage::mojom::CacheStorageOwner owner,
       storage::mojom::QuotaClient::DeleteBucketDataCallback callback);
   void DeleteBucketData(
@@ -157,8 +158,8 @@
                              storage::mojom::StorageUsageInfoPtr>>
           usage_tuples);
 
-  void DeleteStorageKeysDataGotAllBucketInfo(
-      const std::set<blink::StorageKey>& storage_keys,
+  void DeleteOriginsDataGotAllBucketInfo(
+      const std::set<url::Origin>& origins,
       storage::mojom::CacheStorageOwner owner,
       base::OnceCallback<void(std::vector<blink::mojom::QuotaStatusCode>)>
           callback,
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc
index 535e5d8..95fa19e 100644
--- a/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -782,13 +782,12 @@
     return future.Get();
   }
 
-  blink::mojom::QuotaStatusCode DeleteStorageKeyData(
-      const std::set<blink::StorageKey>& storage_keys,
+  blink::mojom::QuotaStatusCode DeleteOriginData(
+      const std::set<url::Origin>& origins,
       storage::mojom::CacheStorageOwner owner =
           storage::mojom::CacheStorageOwner::kCacheAPI) {
     base::test::TestFuture<::blink::mojom::QuotaStatusCode> future;
-    cache_manager_->DeleteStorageKeyData(storage_keys, owner,
-                                         future.GetCallback());
+    cache_manager_->DeleteOriginData(origins, owner, future.GetCallback());
     return future.Get();
   }
 
@@ -2835,17 +2834,17 @@
   EXPECT_EQ(206, callback_cache_handle_response_->status_code);
 }
 
-TEST_P(CacheStorageManagerTestP, DeleteStorageKeyDataEmptyList) {
-  std::set<blink::StorageKey> empty_list;
+TEST_P(CacheStorageManagerTestP, DeleteOriginDataEmptyList) {
+  std::set<url::Origin> empty_list;
   for (const storage::mojom::CacheStorageOwner owner :
        {storage::mojom::CacheStorageOwner::kCacheAPI,
         storage::mojom::CacheStorageOwner::kBackgroundFetch}) {
-    EXPECT_EQ(DeleteStorageKeyData(empty_list, owner),
+    EXPECT_EQ(DeleteOriginData(empty_list, owner),
               blink::mojom::QuotaStatusCode::kOk);
   }
 }
 
-TEST_P(CacheStorageManagerTestP, BatchDeleteStorageKeyData) {
+TEST_P(CacheStorageManagerTestP, BatchDeleteOriginData) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
       net::features::kThirdPartyStoragePartitioning);
@@ -2874,10 +2873,10 @@
 
     EXPECT_EQ(3ULL, GetStorageKeys(owner).size());
 
-    std::set<blink::StorageKey> to_delete = {storage_key1_, storage_key2_,
-                                             partitioned_storage_key1};
+    std::set<url::Origin> to_delete = {storage_key1_.origin(),
+                                       storage_key2_.origin()};
 
-    EXPECT_EQ(DeleteStorageKeyData(to_delete, owner),
+    EXPECT_EQ(DeleteOriginData(to_delete, owner),
               blink::mojom::QuotaStatusCode::kOk);
 
     auto storage_keys = GetStorageKeys(owner);
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 7481ceaa..6d077266 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -469,8 +469,7 @@
 
 StoragePartitionConfig DownloadManagerImpl::GetStoragePartitionConfigForSiteUrl(
     const GURL& site_url) {
-  return SiteInfo::GetStoragePartitionConfigForUrl(browser_context_, site_url,
-                                                   /*is_site_url=*/true);
+  return SiteInfo::GetStoragePartitionConfigForUrl(browser_context_, site_url);
 }
 
 void DownloadManagerImpl::DetermineDownloadTarget(
diff --git a/content/browser/fenced_frame/fenced_frame_browsertest.cc b/content/browser/fenced_frame/fenced_frame_browsertest.cc
index 3becac58..4989932 100644
--- a/content/browser/fenced_frame/fenced_frame_browsertest.cc
+++ b/content/browser/fenced_frame/fenced_frame_browsertest.cc
@@ -4568,6 +4568,9 @@
     // Whether the navigation should be via a urn:uuid or a normal URL.
     // (This should always be false when `!is_embedder_initiated`.
     bool is_opaque = false;
+    // Whether attribution-reporting permission policy is expected to be
+    // allowed.
+    bool expect_attribution_reporting_allowed = true;
 
     struct Event {
       std::string type;
@@ -4700,7 +4703,8 @@
         std::string final_destination_origin =
             step.redirects.empty() ? step.destination.origin
                                    : step.redirects.back().origin;
-        if (final_destination_origin != reporting_origin) {
+        if (final_destination_origin != reporting_origin &&
+            step.expect_attribution_reporting_allowed) {
           // The reporting beacon is cross-origin. Two requests will be sent.
           // First is the preflight request, the second is the actual request.
           responses.emplace_back(
@@ -4880,7 +4884,8 @@
         std::string final_destination_origin =
             step.redirects.empty() ? step.destination.origin
                                    : step.redirects.back().origin;
-        if (final_destination_origin != reporting_origin) {
+        if (final_destination_origin != reporting_origin &&
+            step.expect_attribution_reporting_allowed) {
           auto& preflight_response = *responses[response_index];
           // Verify the preflight request contains the eligibility header under
           // "Access-Control-Request-Headers".
@@ -4905,9 +4910,14 @@
             response.http_request()->content,
             step.event.type + " " + base::NumberToString(navigation_index));
         // Verify the request contains the eligibility header.
-        EXPECT_EQ(response.http_request()->headers.at(
-                      "Attribution-Reporting-Eligible"),
-                  "event-source");
+        if (step.expect_attribution_reporting_allowed) {
+          EXPECT_EQ(response.http_request()->headers.at(
+                        "Attribution-Reporting-Eligible"),
+                    "event-source");
+        } else {
+          EXPECT_FALSE(base::Contains(response.http_request()->headers,
+                                      "Attribution-Reporting-Eligible"));
+        }
         EXPECT_FALSE(base::Contains(response.http_request()->headers,
                                     "Attribution-Reporting-Support"));
         response.Done();
@@ -5273,6 +5283,48 @@
   RunTest(config);
 }
 
+// Attribution Reporting headers are not set if attribution-reporting permission
+// policy is disallowed for the fenced frame.
+IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
+                       FencedFrameReportEventAttributionReportingDisallowed) {
+  std::vector<Step> config = {
+      {
+          .is_embedder_initiated = true,
+          .is_opaque = true,
+          .expect_attribution_reporting_allowed = false,
+          .destination =
+              {"a.test",
+               "/fenced_frames/attribution_reporting_disallowed.html"},
+          .report_event_result = Step::Result::kSuccess,
+      },
+  };
+  RunTest(config);
+}
+
+// Attribution Reporting headers are not set if attribution-reporting permission
+// policy is disallowed for the nested iframe.
+IN_PROC_BROWSER_TEST_F(
+    FencedFrameReportEventBrowserTest,
+    FencedFrameReportEventNestedIframeAttributionReportingDisallowed) {
+  std::vector<Step> config = {
+      {
+          .is_embedder_initiated = true,
+          .is_opaque = true,
+          .destination = {"a.test", "/fenced_frames/title1.html"},
+          .report_event_result = Step::Result::kSuccess,
+      },
+      {
+          .is_target_nested_iframe = true,
+          .expect_attribution_reporting_allowed = false,
+          .destination =
+              {"a.test",
+               "/fenced_frames/attribution_reporting_disallowed.html"},
+          .report_event_result = Step::Result::kSuccess,
+      },
+  };
+  RunTest(config);
+}
+
 // (Temporary test for FLEDGE iframe OT.)
 // Tests that an iframe with a urn:uuid commits the navigation with the
 // associated reporting metadata and `fence.reportEvent` sends the beacon to
diff --git a/content/browser/fenced_frame/fenced_frame_reporter.cc b/content/browser/fenced_frame/fenced_frame_reporter.cc
index 2d5aa16..237d8e6 100644
--- a/content/browser/fenced_frame/fenced_frame_reporter.cc
+++ b/content/browser/fenced_frame/fenced_frame_reporter.cc
@@ -136,13 +136,11 @@
     const std::string& type,
     const std::string& data,
     const url::Origin& request_initiator,
-    BeaconId beacon_id,
-    bool is_automatic_beacon)
+    absl::optional<AttributionReportingData> attribution_reporting_data)
     : type(type),
       data(data),
       request_initiator(request_initiator),
-      beacon_id(beacon_id),
-      is_automatic_beacon(is_automatic_beacon) {}
+      attribution_reporting_data(std::move(attribution_reporting_data)) {}
 
 FencedFrameReporter::PendingEvent::PendingEvent(const PendingEvent&) = default;
 
@@ -232,7 +230,8 @@
 FencedFrameReporter::~FencedFrameReporter() {
   for (const auto& [destination, destination_info] : reporting_metadata_) {
     for (const auto& pending_event : destination_info.pending_events) {
-      NotifyFencedFrameReportingBeaconFailed(pending_event.beacon_id);
+      NotifyFencedFrameReportingBeaconFailed(
+          pending_event.attribution_reporting_data);
     }
   }
 }
@@ -250,8 +249,7 @@
     std::string ignored_error_message;
     SendReportInternal(it->second, pending_event.type, pending_event.data,
                        reporting_destination, pending_event.request_initiator,
-                       pending_event.beacon_id,
-                       pending_event.is_automatic_beacon,
+                       pending_event.attribution_reporting_data,
                        ignored_error_message);
   }
 }
@@ -286,20 +284,20 @@
     return false;
   }
 
-  // Attribution Reporting is required to be enabled for an opaque-ads fenced
-  // frame to load, therefore it's fine to always add the Attribution Reporting
-  // headers in `SendReportInternal()`. This should be revisited if this
-  // restriction changes.
-  DCHECK(request_initiator_frame->IsFeatureEnabled(
-      blink::mojom::PermissionsPolicyFeature::kAttributionReporting));
-
   static base::AtomicSequenceNumber unique_id_counter;
 
-  BeaconId beacon_id(unique_id_counter.GetNext());
+  absl::optional<AttributionReportingData> attribution_reporting_data;
 
   auto* attribution_host = AttributionHost::FromWebContents(
       WebContents::FromRenderFrameHost(request_initiator_frame));
-  if (attribution_host) {
+  if (attribution_host &&
+      request_initiator_frame->IsFeatureEnabled(
+          blink::mojom::PermissionsPolicyFeature::kAttributionReporting)) {
+    BeaconId beacon_id(unique_id_counter.GetNext());
+    attribution_reporting_data.emplace(AttributionReportingData{
+        .beacon_id = beacon_id,
+        .is_automatic_beacon = navigation_id.has_value(),
+    });
     attribution_host->NotifyFencedFrameReportingBeaconStarted(
         beacon_id, navigation_id, request_initiator_frame);
   }
@@ -307,19 +305,17 @@
   const url::Origin& request_initiator =
       request_initiator_frame->GetLastCommittedOrigin();
 
-  const bool is_automatic_beacon = navigation_id.has_value();
-
   // If the reporting URL map is pending, queue the event.
   if (it->second.reporting_url_map == absl::nullopt) {
-    it->second.pending_events.emplace_back(event_type, event_data,
-                                           request_initiator, beacon_id,
-                                           is_automatic_beacon);
+    it->second.pending_events.emplace_back(
+        event_type, event_data, request_initiator,
+        std::move(attribution_reporting_data));
     return true;
   }
 
   return SendReportInternal(it->second, event_type, event_data,
-                            reporting_destination, request_initiator, beacon_id,
-                            is_automatic_beacon, error_message);
+                            reporting_destination, request_initiator,
+                            attribution_reporting_data, error_message);
 }
 
 bool FencedFrameReporter::SendReportInternal(
@@ -328,8 +324,7 @@
     const std::string& event_data,
     blink::FencedFrame::ReportingDestination reporting_destination,
     const url::Origin& request_initiator,
-    BeaconId beacon_id,
-    bool is_automatic_beacon,
+    const absl::optional<AttributionReportingData>& attribution_reporting_data,
     std::string& error_message) {
   // The URL map should not be pending at this point.
   DCHECK(reporting_destination_info.reporting_url_map);
@@ -342,7 +337,7 @@
         {"This frame did not register reporting url for destination '",
          ReportingDestinationAsString(reporting_destination),
          "' and event_type '", event_type, "'."});
-    NotifyFencedFrameReportingBeaconFailed(beacon_id);
+    NotifyFencedFrameReportingBeaconFailed(attribution_reporting_data);
     return false;
   }
 
@@ -353,7 +348,7 @@
         {"This frame registered invalid reporting url for destination '",
          ReportingDestinationAsString(reporting_destination),
          "' and event_type '", event_type, "'."});
-    NotifyFencedFrameReportingBeaconFailed(beacon_id);
+    NotifyFencedFrameReportingBeaconFailed(attribution_reporting_data);
     return false;
   }
 
@@ -369,10 +364,16 @@
   request->trusted_params->isolation_info =
       net::IsolationInfo::CreateTransient();
 
-  if (attribution_manager_) {
-    request->headers.SetHeader(
-        "Attribution-Reporting-Eligible",
-        is_automatic_beacon ? "navigation-source" : "event-source");
+  // `attribution_reporting_data` is guaranteed to be set iff attribution
+  // reporting is allowed in the initiator frame.
+  const bool is_attribution_reporting_allowed =
+      attribution_reporting_data.has_value();
+
+  if (attribution_manager_ && is_attribution_reporting_allowed) {
+    request->headers.SetHeader("Attribution-Reporting-Eligible",
+                               attribution_reporting_data->is_automatic_beacon
+                                   ? "navigation-source"
+                                   : "event-source");
 
     if (base::FeatureList::IsEnabled(
             blink::features::kAttributionReportingCrossAppWeb)) {
@@ -395,7 +396,7 @@
       attribution_manager_ ? attribution_manager_->GetDataHostManager()
                            : nullptr;
 
-  if (attribution_data_host_manager) {
+  if (attribution_data_host_manager && is_attribution_reporting_allowed) {
     // Notify Attribution Reporting API for the beacons.
     simple_url_loader_ptr->SetOnRedirectCallback(base::BindRepeating(
         [](base::WeakPtr<AttributionDataHostManager>
@@ -411,7 +412,8 @@
                 /*is_final_response=*/false);
           }
         },
-        attribution_data_host_manager->AsWeakPtr(), beacon_id));
+        attribution_data_host_manager->AsWeakPtr(),
+        attribution_reporting_data->beacon_id));
 
     // Send out the reporting beacon.
     simple_url_loader_ptr->DownloadHeadersOnly(
@@ -430,7 +432,8 @@
                         /*is_final_response=*/true);
               }
             },
-            attribution_data_host_manager->AsWeakPtr(), beacon_id,
+            attribution_data_host_manager->AsWeakPtr(),
+            attribution_reporting_data->beacon_id,
             std::move(simple_url_loader)));
   } else {
     // Send out the reporting beacon.
@@ -558,7 +561,12 @@
 }
 
 void FencedFrameReporter::NotifyFencedFrameReportingBeaconFailed(
-    BeaconId beacon_id) {
+    const absl::optional<AttributionReportingData>&
+        attribution_reporting_data) {
+  if (!attribution_reporting_data.has_value()) {
+    return;
+  }
+
   AttributionDataHostManager* attribution_data_host_manager =
       attribution_manager_ ? attribution_manager_->GetDataHostManager()
                            : nullptr;
@@ -567,7 +575,7 @@
   }
 
   attribution_data_host_manager->NotifyFencedFrameReportingBeaconData(
-      beacon_id,
+      attribution_reporting_data->beacon_id,
       /*reporting_origin=*/url::Origin(), /*headers=*/nullptr,
       /*is_final_response=*/true);
 }
diff --git a/content/browser/fenced_frame/fenced_frame_reporter.h b/content/browser/fenced_frame/fenced_frame_reporter.h
index d28269a..36374ef 100644
--- a/content/browser/fenced_frame/fenced_frame_reporter.h
+++ b/content/browser/fenced_frame/fenced_frame_reporter.h
@@ -190,12 +190,17 @@
   friend class base::RefCounted<FencedFrameReporter>;
   friend class FencedFrameURLMappingTestPeer;
 
+  struct AttributionReportingData {
+    BeaconId beacon_id;
+    bool is_automatic_beacon;
+  };
+
   struct PendingEvent {
-    PendingEvent(const std::string& type,
-                 const std::string& data,
-                 const url::Origin& request_initiator,
-                 BeaconId beacon_id,
-                 bool is_automatic_beacon);
+    PendingEvent(
+        const std::string& type,
+        const std::string& data,
+        const url::Origin& request_initiator,
+        absl::optional<AttributionReportingData> attribution_reporting_data);
 
     PendingEvent(const PendingEvent&);
     PendingEvent(PendingEvent&&);
@@ -208,8 +213,9 @@
     std::string type;
     std::string data;
     url::Origin request_initiator;
-    BeaconId beacon_id;
-    bool is_automatic_beacon;
+    // The data necessary for attribution reporting. Will be `absl::nullopt` if
+    // attribution reporting is disallowed in the initiator frame.
+    absl::optional<AttributionReportingData> attribution_reporting_data;
   };
 
   // The per-blink::FencedFrame::ReportingDestination reporting information.
@@ -241,8 +247,8 @@
       const std::string& event_data,
       blink::FencedFrame::ReportingDestination reporting_destination,
       const url::Origin& request_initiator,
-      BeaconId beacon_id,
-      bool is_automatic_beacon,
+      const absl::optional<AttributionReportingData>&
+          attribution_reporting_data,
       std::string& error_message);
 
   // Helper to send private aggregation requests in
@@ -264,7 +270,9 @@
 
   // Helper to notify `AttributionDataHostManager` if the report failed to be
   // sent.
-  void NotifyFencedFrameReportingBeaconFailed(BeaconId beacon_id);
+  void NotifyFencedFrameReportingBeaconFailed(
+      const absl::optional<AttributionReportingData>&
+          attribution_reporting_data);
 
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
diff --git a/content/browser/indexed_db/indexed_db_tombstone_sweeper.h b/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
index e637ee3..e4c86f88 100644
--- a/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
+++ b/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
@@ -12,6 +12,7 @@
 #include "base/feature_list.h"
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
@@ -63,7 +64,9 @@
   bool valid_ = false;
   size_t iterations_done_ = 0;
   typename T::const_iterator inner_;
-  const T* container_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION const T* container_ = nullptr;
 };
 
 // Sweeps the IndexedDB leveldb database looking for index tombstones. These
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index 4b5ff0fc..262c391 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -6282,6 +6282,48 @@
   }
 }
 
+// Test that the FLEDGE properly handles detached documents.
+IN_PROC_BROWSER_TEST_P(InterestGroupFencedFrameBrowserTest,
+                       DetachedDocumentDoesNotCrash) {
+  const char* kTestCases[] = {
+      R"(runAdAuction({
+        seller: "foo", // required
+        decisionLogicUrl: "foo", // required
+      }, 0.0)
+    )",
+      R"(joinAdInterestGroup({
+        owner: "foo", // required
+        name: "foo", // required
+      })
+    )",
+      "leaveAdInterestGroup()",
+      "updateAdInterestGroups()",
+      "adAuctionComponents(1)",
+      R"(deprecatedURNToURL("foo")
+    )",
+      R"(deprecatedReplaceInURN("foo", {}))",
+      "canLoadAdAuctionFencedFrame()"};
+
+  GURL main_url = https_server_->GetURL("b.test", "/page_with_iframe.html");
+
+  for (const auto* test_case : kTestCases) {
+    ASSERT_TRUE(NavigateToURL(shell(), main_url));
+
+    EvalJsResult result = EvalJs(shell(), base::StringPrintf(R"(
+        try {
+          let child = document.getElementById("test_iframe");
+          const detachedNavigator = child.contentWindow.navigator;
+          child.remove();
+          detachedNavigator.%s;
+        } catch(e) {
+        }
+        "Did not crash"
+      )",
+                                                             test_case));
+    EXPECT_EQ("Did not crash", result) << test_case;
+  }
+}
+
 // Runs auction just like test InterestGroupBrowserTest.RunAdAuctionWithWinner,
 // but runs with fenced frames enabled and expects to receive a URN URL to be
 // used. After the auction, loads the URL in a fenced frame, and expects the
diff --git a/content/browser/media/capture/desktop_capture_device_unittest.cc b/content/browser/media/capture/desktop_capture_device_unittest.cc
index 461fd586..391fb39 100644
--- a/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -16,6 +16,7 @@
 
 #include "base/command_line.h"
 #include "base/functional/bind.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/single_thread_task_runner.h"
@@ -220,7 +221,9 @@
     callback_->OnCaptureResult(result, std::move(frame));
   }
 
-  Callback* callback_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #constexpr-ctor-field-initializer
+  RAW_PTR_EXCLUSION Callback* callback_ = nullptr;
   int captured_frames_ = 0;
   bool generate_inverted_frames_ = false;
   bool generate_cropped_frames_ = false;
diff --git a/content/browser/media/media_license_storage_host_unittest.cc b/content/browser/media/media_license_storage_host_unittest.cc
index 4abe676..5139374 100644
--- a/content/browser/media/media_license_storage_host_unittest.cc
+++ b/content/browser/media/media_license_storage_host_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/logging.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/test/bind.h"
 #include "base/test/test_future.h"
 #include "content/browser/media/media_license_manager.h"
@@ -170,7 +171,9 @@
     return media_license_manager;
   }
 
-  RenderFrameHost* rfh_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION RenderFrameHost* rfh_ = nullptr;
   mojo::Remote<CdmStorage> cdm_storage_;
 };
 
diff --git a/content/browser/media/session/media_session_impl.h b/content/browser/media/session/media_session_impl.h
index 4fd6373..e6e5b5fa 100644
--- a/content/browser/media/session/media_session_impl.h
+++ b/content/browser/media/session/media_session_impl.h
@@ -15,6 +15,7 @@
 #include "base/containers/flat_set.h"
 #include "base/containers/id_map.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "content/browser/media/session/audio_focus_delegate.h"
@@ -372,8 +373,9 @@
     bool operator==(const PlayerIdentifier& other) const;
     bool operator!=(const PlayerIdentifier& other) const;
     bool operator<(const PlayerIdentifier& other) const;
-
-    MediaSessionPlayerObserver* observer;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #constexpr-ctor-field-initializer, #union
+    RAW_PTR_EXCLUSION MediaSessionPlayerObserver* observer;
     int player_id;
   };
 
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc
index 5882134..27b694e 100644
--- a/content/browser/portal/portal_browsertest.cc
+++ b/content/browser/portal/portal_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/functional/callback_helpers.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/run_loop.h"
 #include "base/strings/escape.h"
 #include "base/strings/strcat.h"
@@ -3048,7 +3049,9 @@
 
  private:
   base::OnceClosure quit_closure_;
-  RenderWidgetHostViewBase* view_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #constexpr-ctor-field-initializer
+  RAW_PTR_EXCLUSION RenderWidgetHostViewBase* view_ = nullptr;
 };
 
 // Tests that a RenderWidgetHostView for a fenced frame inside a portal should
diff --git a/content/browser/preloading/prefetch/prefetch_container.cc b/content/browser/preloading/prefetch/prefetch_container.cc
index d1c187d3..60759071 100644
--- a/content/browser/preloading/prefetch/prefetch_container.cc
+++ b/content/browser/preloading/prefetch/prefetch_container.cc
@@ -387,7 +387,7 @@
         .Run(is_eligible);
   }
 
-  if (url == prefetch_url_) {
+  if (url == prefetch_url_ && redirect_chain_.size() == 1) {
     // This case is for just the URL that was originally requested to be
     // prefetched.
     if (!is_eligible) {
@@ -404,7 +404,9 @@
       }
     }
 
-    prefetch_document_manager_->OnEligibilityCheckComplete(is_eligible);
+    if (prefetch_document_manager_) {
+      prefetch_document_manager_->OnEligibilityCheckComplete(is_eligible);
+    }
   } else {
     // This case is for any URLs from redirects.
     if (!is_eligible) {
diff --git a/content/browser/preloading/prefetch/prefetch_features.cc b/content/browser/preloading/prefetch/prefetch_features.cc
index 17d3e86..c0061cd3 100644
--- a/content/browser/preloading/prefetch/prefetch_features.cc
+++ b/content/browser/preloading/prefetch/prefetch_features.cc
@@ -10,4 +10,8 @@
              "PrefetchUseContentRefactor",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
+BASE_FEATURE(kPrefetchRedirects,
+             "PrefetchRedirects",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 }  // namespace content::features
diff --git a/content/browser/preloading/prefetch/prefetch_features.h b/content/browser/preloading/prefetch/prefetch_features.h
index 8de5f9c..c692545 100644
--- a/content/browser/preloading/prefetch/prefetch_features.h
+++ b/content/browser/preloading/prefetch/prefetch_features.h
@@ -15,6 +15,9 @@
 // chrome/browser/preloadingprefetch/prefetch_proxy/.
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kPrefetchUseContentRefactor);
 
+// IF enabled, then redirects will be followed when prefetching.
+CONTENT_EXPORT BASE_DECLARE_FEATURE(kPrefetchRedirects);
+
 }  // namespace content::features
 
 #endif  // CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_FEATURES_H_
diff --git a/content/browser/preloading/prefetch/prefetch_service.cc b/content/browser/preloading/prefetch/prefetch_service.cc
index f036e5b..c8914b7 100644
--- a/content/browser/preloading/prefetch/prefetch_service.cc
+++ b/content/browser/preloading/prefetch/prefetch_service.cc
@@ -952,7 +952,8 @@
     const network::mojom::URLResponseHead& response_head) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!prefetch_container) {
+  if (!prefetch_container ||
+      !base::FeatureList::IsEnabled(features::kPrefetchRedirects)) {
     return PrefetchStreamingURLLoaderStatus::kFailedInvalidRedirect;
   }
 
@@ -1314,6 +1315,12 @@
     return;
   }
 
+  if (prefetch_container->GetRedirectChainSize() > 1 &&
+      !base::FeatureList::IsEnabled(features::kPrefetchRedirects)) {
+    std::move(on_prefetch_to_serve_ready).Run(nullptr);
+    return;
+  }
+
   if (prefetch_container->IsPrefetchServable(PrefetchCacheableDuration())) {
     DVLOG(1) << "PrefetchService::GetPrefetchToServe(" << url
              << "): PrefetchContainer is servable";
diff --git a/content/browser/preloading/prefetch/prefetch_service_unittest.cc b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
index 2cc2bf69..63985f7 100644
--- a/content/browser/preloading/prefetch/prefetch_service_unittest.cc
+++ b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
@@ -2631,7 +2631,8 @@
     scoped_feature_list_.InitWithFeaturesAndParameters(
         {{features::kPrefetchUseContentRefactor,
           {{"ineligible_decoy_request_probability", "1"},
-           {"prefetch_container_lifetime_s", "-1"}}}},
+           {"prefetch_container_lifetime_s", "-1"}}},
+         {features::kPrefetchRedirects, {}}},
         {network::features::kPrefetchNoVarySearch});
   }
 };
@@ -3262,13 +3263,25 @@
                        PreloadingFailureReason::kUnspecified);
 }
 
+class PrefetchServiceAllowRedirectTest : public PrefetchServiceTest {
+ public:
+  void InitScopedFeatureList() override {
+    scoped_feature_list_.InitWithFeaturesAndParameters(
+        {{features::kPrefetchUseContentRefactor,
+          {{"ineligible_decoy_request_probability", "0"},
+           {"prefetch_container_lifetime_s", "-1"}}},
+         {features::kPrefetchRedirects, {}}},
+        {network::features::kPrefetchNoVarySearch});
+  }
+};
+
 // TODO(crbug.com/1396460): Test flaky on lacros trybots.
 #if BUILDFLAG(IS_CHROMEOS)
 #define MAYBE_PrefetchEligibleRedirect DISABLED_PrefetchEligibleRedirect
 #else
 #define MAYBE_PrefetchEligibleRedirect PrefetchEligibleRedirect
 #endif
-TEST_F(PrefetchServiceTest, MAYBE_PrefetchEligibleRedirect) {
+TEST_F(PrefetchServiceAllowRedirectTest, MAYBE_PrefetchEligibleRedirect) {
   base::HistogramTester histogram_tester;
 
   MakePrefetchService(
@@ -3354,7 +3367,7 @@
 #else
 #define MAYBE_IneligibleRedirectCookies IneligibleRedirectCookies
 #endif
-TEST_F(PrefetchServiceTest, MAYBE_IneligibleRedirectCookies) {
+TEST_F(PrefetchServiceAllowRedirectTest, MAYBE_IneligibleRedirectCookies) {
   base::HistogramTester histogram_tester;
 
   MakePrefetchService(
@@ -3435,7 +3448,8 @@
 #else
 #define MAYBE_IneligibleRedirectServiceWorker IneligibleRedirectServiceWorker
 #endif
-TEST_F(PrefetchServiceTest, MAYBE_IneligibleRedirectServiceWorker) {
+TEST_F(PrefetchServiceAllowRedirectTest,
+       MAYBE_IneligibleRedirectServiceWorker) {
   base::HistogramTester histogram_tester;
 
   MakePrefetchService(
@@ -3516,7 +3530,7 @@
 #else
 #define MAYBE_InvalidRedirect InvalidRedirect
 #endif
-TEST_F(PrefetchServiceTest, MAYBE_InvalidRedirect) {
+TEST_F(PrefetchServiceAllowRedirectTest, MAYBE_InvalidRedirect) {
   base::HistogramTester histogram_tester;
 
   MakePrefetchService(
diff --git a/content/browser/renderer_host/back_forward_cache_impl.h b/content/browser/renderer_host/back_forward_cache_impl.h
index b3ad355..f9a7e60 100644
--- a/content/browser/renderer_host/back_forward_cache_impl.h
+++ b/content/browser/renderer_host/back_forward_cache_impl.h
@@ -13,6 +13,7 @@
 #include "base/feature_list.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/raw_ref.h"
 #include "base/memory/weak_ptr.h"
 #include "base/task/single_thread_task_runner.h"
@@ -526,8 +527,12 @@
       EvictionInfo(RenderFrameHostImpl& rfh,
                    BackForwardCacheCanStoreDocumentResult* reasons)
           : rfh_to_be_evicted(&rfh), reasons(reasons) {}
-      RenderFrameHostImpl* const rfh_to_be_evicted;
-      const BackForwardCacheCanStoreDocumentResult* reasons;
+      // This field is not a raw_ptr<> because it was filtered by the rewriter
+      // for: #union
+      RAW_PTR_EXCLUSION RenderFrameHostImpl* const rfh_to_be_evicted;
+      // This field is not a raw_ptr<> because it was filtered by the rewriter
+      // for: #union
+      RAW_PTR_EXCLUSION const BackForwardCacheCanStoreDocumentResult* reasons;
     };
 
     NotRestoredReasonBuilder(RenderFrameHostImpl* root_rfh,
diff --git a/content/browser/renderer_host/clipboard_host_impl.cc b/content/browser/renderer_host/clipboard_host_impl.cc
index e9734be6..304a31a 100644
--- a/content/browser/renderer_host/clipboard_host_impl.cc
+++ b/content/browser/renderer_host/clipboard_host_impl.cc
@@ -11,6 +11,7 @@
 #include "base/functional/bind.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/notreached.h"
 #include "base/pickle.h"
 #include "base/ranges/algorithm.h"
@@ -56,7 +57,9 @@
 struct LastWriterInfo {
   // A pointer to the last ClipboardHostImpl that committed data to the
   // clipboard.
-  ClipboardHostImpl* writer = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #global-scope
+  RAW_PTR_EXCLUSION ClipboardHostImpl* writer = nullptr;
 
   // The sequence number of the last commit made by `writer`.
   ui::ClipboardSequenceNumberToken seqno;
diff --git a/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc b/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc
index 3e2e9fa..5feb70b 100644
--- a/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc
+++ b/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/functional/bind.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/read_only_shared_memory_region.h"
 #include "base/run_loop.h"
 #include "base/sync_socket.h"
@@ -134,7 +135,10 @@
   mojo::Receiver<blink::mojom::RendererAudioInputStreamFactoryClient>
       client_receiver_;
   StrictMock<MockDeleter> deleter_;
-  media::AudioInputDelegate::EventHandler* event_handler_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION media::AudioInputDelegate::EventHandler* event_handler_ =
+      nullptr;
   std::unique_ptr<AudioInputStreamHandle> handle_;
 
   base::ReadOnlySharedMemoryRegion shared_memory_region_;
diff --git a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.cc b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.cc
index 4d88eaa..029b852 100644
--- a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.cc
+++ b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.cc
@@ -4,7 +4,6 @@
 
 #include "content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h"
 
-#include <fuchsia/media/cpp/fidl.h>
 #include <fuchsia/mediacodec/cpp/fidl.h>
 #include <lib/fit/function.h>
 #include <lib/sys/cpp/component_context.h>
@@ -12,8 +11,8 @@
 #include "base/command_line.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/fuchsia/process_context.h"
+#include "media/base/media_switches.h"
 #include "media/base/supported_video_decoder_config.h"
-#include "media/base/video_codecs.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
@@ -48,93 +47,38 @@
   return absl::nullopt;
 }
 
-media::VideoCodecProfile ConvertToVideoCodecProfile(
-    const fuchsia::media::CodecProfile& profile) {
-  switch (profile) {
-    case fuchsia::media::CodecProfile::H264PROFILE_BASELINE:
-      return media::VideoCodecProfile::H264PROFILE_BASELINE;
-    case fuchsia::media::CodecProfile::H264PROFILE_MAIN:
-      return media::VideoCodecProfile::H264PROFILE_MAIN;
-    case fuchsia::media::CodecProfile::H264PROFILE_EXTENDED:
-      return media::VideoCodecProfile::H264PROFILE_EXTENDED;
-    case fuchsia::media::CodecProfile::H264PROFILE_HIGH:
-      return media::VideoCodecProfile::H264PROFILE_HIGH;
-    case fuchsia::media::CodecProfile::H264PROFILE_HIGH10PROFILE:
-      return media::VideoCodecProfile::H264PROFILE_HIGH10PROFILE;
-    case fuchsia::media::CodecProfile::H264PROFILE_HIGH422PROFILE:
-      return media::VideoCodecProfile::H264PROFILE_HIGH422PROFILE;
-    case fuchsia::media::CodecProfile::H264PROFILE_HIGH444PREDICTIVEPROFILE:
-      return media::VideoCodecProfile::H264PROFILE_HIGH444PREDICTIVEPROFILE;
-    case fuchsia::media::CodecProfile::H264PROFILE_SCALABLEBASELINE:
-      return media::VideoCodecProfile::H264PROFILE_SCALABLEBASELINE;
-    case fuchsia::media::CodecProfile::H264PROFILE_SCALABLEHIGH:
-      return media::VideoCodecProfile::H264PROFILE_SCALABLEHIGH;
-    case fuchsia::media::CodecProfile::H264PROFILE_STEREOHIGH:
-      return media::VideoCodecProfile::H264PROFILE_STEREOHIGH;
-    case fuchsia::media::CodecProfile::H264PROFILE_MULTIVIEWHIGH:
-      return media::VideoCodecProfile::H264PROFILE_MULTIVIEWHIGH;
-    case fuchsia::media::CodecProfile::VP8PROFILE_ANY:
-      return media::VideoCodecProfile::VP8PROFILE_ANY;
-    case fuchsia::media::CodecProfile::VP9PROFILE_PROFILE0:
-      return media::VideoCodecProfile::VP9PROFILE_PROFILE0;
-    case fuchsia::media::CodecProfile::VP9PROFILE_PROFILE1:
-      return media::VideoCodecProfile::VP9PROFILE_PROFILE1;
-    case fuchsia::media::CodecProfile::VP9PROFILE_PROFILE2:
-      return media::VideoCodecProfile::VP9PROFILE_PROFILE2;
-    case fuchsia::media::CodecProfile::VP9PROFILE_PROFILE3:
-      return media::VideoCodecProfile::VP9PROFILE_PROFILE3;
-    case fuchsia::media::CodecProfile::HEVCPROFILE_MAIN:
-      return media::VideoCodecProfile::HEVCPROFILE_MAIN;
-    case fuchsia::media::CodecProfile::HEVCPROFILE_MAIN10:
-      return media::VideoCodecProfile::HEVCPROFILE_MAIN10;
-    case fuchsia::media::CodecProfile::HEVCPROFILE_MAIN_STILL_PICTURE:
-      return media::VideoCodecProfile::HEVCPROFILE_MAIN_STILL_PICTURE;
-    default:
-      NOTIMPLEMENTED() << "Unknown codec profile: " << profile;
-      return media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
-  }
-}
-
+// fuchsia::mediacodec::CodecDescription does not provide enough codec info
+// to determine if a media::VideoDecoderConfig is supported. The constant and
+// the helper function below is to make a safe assumption that converts the type
+// to media::SupportedVideoDecoderConfigs.
+// TODO(fxbug.dev/85214): Remove the constant and the helper function below
+// after more details are added to mediacodec.CodecDescription.
+constexpr gfx::Size kFuchsiaDecodeSizeMax(1920, 1080);  // 1080p
 media::SupportedVideoDecoderConfigs GetSupportedVideoDecoderConfigsForCodecList(
-    const std::vector<fuchsia::mediacodec::DetailedCodecDescription>&
-        detailed_codec_list) {
+    const std::vector<fuchsia::mediacodec::CodecDescription>& codec_list) {
   media::SupportedVideoDecoderConfigs configs;
-
-  for (const auto& codec_description : detailed_codec_list) {
-    if (codec_description.codec_type() !=
-            fuchsia::mediacodec::CodecType::DECODER ||
-        // Only use platform codecs that are accelerated.
-        !codec_description.is_hw() ||
-        // Exclude non-video codecs.
-        codec_description.mime_type().find("video") != 0 ||
-        !codec_description.has_profile_descriptions() ||
-        !codec_description.profile_descriptions()
-             .is_decoder_profile_descriptions()) {
-      continue;
-    }
-
-    for (const auto& profile_description :
-         codec_description.profile_descriptions()
-             .decoder_profile_descriptions()) {
-      const auto video_codec_profile =
-          ConvertToVideoCodecProfile(profile_description.profile());
-      if (video_codec_profile ==
-          media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN) {
-        continue;
-      }
-
-      configs.emplace_back(
-          video_codec_profile, video_codec_profile,
-          gfx::Size(profile_description.min_image_size().width,
-                    profile_description.min_image_size().height),
-          gfx::Size(profile_description.max_image_size().width,
-                    profile_description.max_image_size().height),
-          profile_description.has_allow_encryption()
-              ? profile_description.allow_encryption()
-              : false,
-          profile_description.has_require_encryption()
-              ? profile_description.require_encryption()
-              : false);
+  for (const auto& codec_description : codec_list) {
+    if (codec_description.mime_type == "video/h264" ||
+        codec_description.mime_type == "video/h264-muti") {
+      configs.emplace_back(media::VideoCodecProfile::H264PROFILE_MIN,
+                           media::VideoCodecProfile::H264PROFILE_STEREOHIGH,
+                           media::kDefaultSwDecodeSizeMin,
+                           kFuchsiaDecodeSizeMax, codec_description.is_hw,
+                           false);
+    } else if (codec_description.mime_type == "video/vp8") {
+      configs.emplace_back(media::VideoCodecProfile::VP8PROFILE_MIN,
+                           media::VideoCodecProfile::VP8PROFILE_MAX,
+                           media::kDefaultSwDecodeSizeMin,
+                           kFuchsiaDecodeSizeMax, codec_description.is_hw,
+                           false);
+    } else if (codec_description.mime_type == "video/vp9") {
+      // Only SD profiles are supported for VP9. HDR profiles (2 and 3) are not
+      // supported.
+      configs.emplace_back(media::VideoCodecProfile::VP9PROFILE_MIN,
+                           media::VideoCodecProfile::VP9PROFILE_PROFILE1,
+                           media::kDefaultSwDecodeSizeMin,
+                           kFuchsiaDecodeSizeMax, codec_description.is_hw,
+                           false);
     }
   }
 
@@ -226,8 +170,8 @@
 
   codec_factory_.set_error_handler(fit::bind_member(
       this, &FuchsiaMediaCodecProviderImpl::OnCodecFactoryDisconnected));
-  codec_factory_->GetDetailedCodecDescriptions(fit::bind_member(
-      this, &FuchsiaMediaCodecProviderImpl::OnGetDetailedCodecDescriptions));
+  codec_factory_.events().OnCodecList =
+      fit::bind_member(this, &FuchsiaMediaCodecProviderImpl::OnCodecList);
 }
 
 void FuchsiaMediaCodecProviderImpl::OnCodecFactoryDisconnected(
@@ -238,11 +182,10 @@
   RunPendingGetSupportedVideoDecoderConfigsCallbacks();
 }
 
-void FuchsiaMediaCodecProviderImpl::OnGetDetailedCodecDescriptions(
-    fuchsia::mediacodec::CodecFactoryGetDetailedCodecDescriptionsResponse
-        response) {
+void FuchsiaMediaCodecProviderImpl::OnCodecList(
+    std::vector<::fuchsia::mediacodec::CodecDescription> codec_list) {
   supported_video_decoder_configs_.emplace(
-      GetSupportedVideoDecoderConfigsForCodecList(response.codecs()));
+      GetSupportedVideoDecoderConfigsForCodecList(codec_list));
   RunPendingGetSupportedVideoDecoderConfigsCallbacks();
 }
 
diff --git a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h
index a93e184..c83f706 100644
--- a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h
+++ b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h
@@ -48,8 +48,8 @@
 
   // Handlers for events on the codec factory API channel.
   void OnCodecFactoryDisconnected(zx_status_t status);
-  void OnGetDetailedCodecDescriptions(
-      fuchsia::mediacodec::CodecFactoryGetDetailedCodecDescriptionsResponse);
+  void OnCodecList(
+      std::vector<fuchsia::mediacodec::CodecDescription> codec_list);
 
   void RunPendingGetSupportedVideoDecoderConfigsCallbacks();
 
diff --git a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl_unittest.cc b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl_unittest.cc
index c473ccd30..9d691261e 100644
--- a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl_unittest.cc
+++ b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl_unittest.cc
@@ -4,13 +4,10 @@
 
 #include "content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h"
 
-#include <fuchsia/media/cpp/fidl.h>
-#include <fuchsia/mediacodec/cpp/fidl.h>
 #include <fuchsia/mediacodec/cpp/fidl_test_base.h>
 #include <lib/fidl/cpp/binding.h>
 #include <algorithm>
 #include <memory>
-#include <vector>
 
 #include "base/fuchsia/scoped_service_binding.h"
 #include "base/fuchsia/test_component_context_for_process.h"
@@ -26,297 +23,70 @@
 
 namespace {
 
-static const gfx::Size k320CodecSize(568, 320);
-static const gfx::Size k1080CodecSize(1920, 1080);
-static const gfx::Size k4kCodecSize(3840, 2160);
+static const gfx::Size kCodedSize(320, 240);
 static const gfx::Rect kVisibleRect(320, 240);
 static const gfx::Size kNaturalSize(320, 240);
 
-// Encrypted VideoDecoderConfig
-const media::VideoDecoderConfig kEncryptedH264Base1080Config(
+const media::VideoDecoderConfig kH264BaseConfig(
     media::VideoCodec::kH264,
     media::H264PROFILE_MIN,
     media::VideoDecoderConfig::AlphaMode::kIsOpaque,
     media::VideoColorSpace(),
     media::kNoTransformation,
-    k1080CodecSize,
+    kCodedSize,
     kVisibleRect,
     kNaturalSize,
     media::EmptyExtraData(),
-    media::EncryptionScheme::kCbcs);
+    media::EncryptionScheme::kUnencrypted);
 
-const media::VideoDecoderConfig kEncryptedVP9BaseConfig(
+const media::VideoDecoderConfig kVP9BaseConfig(
     media::VideoCodec::kVP9,
     media::VP9PROFILE_MIN,
     media::VideoDecoderConfig::AlphaMode::kIsOpaque,
     media::VideoColorSpace(),
     media::kNoTransformation,
-    k1080CodecSize,
-    kVisibleRect,
-    kNaturalSize,
-    media::EmptyExtraData(),
-    media::EncryptionScheme::kCbcs);
-
-const media::VideoDecoderConfig kEncryptedVP9MaxConfig(
-    media::VideoCodec::kVP9,
-    media::VP9PROFILE_MAX,
-    media::VideoDecoderConfig::AlphaMode::kIsOpaque,
-    media::VideoColorSpace(),
-    media::kNoTransformation,
-    k4kCodecSize,
-    kVisibleRect,
-    kNaturalSize,
-    media::EmptyExtraData(),
-    media::EncryptionScheme::kCbcs);
-
-// Unencrypted VideoDecoderConfig
-const media::VideoDecoderConfig kUnencryptedH264Base320Config(
-    media::VideoCodec::kH264,
-    media::H264PROFILE_MIN,
-    media::VideoDecoderConfig::AlphaMode::kIsOpaque,
-    media::VideoColorSpace(),
-    media::kNoTransformation,
-    k320CodecSize,
+    kCodedSize,
     kVisibleRect,
     kNaturalSize,
     media::EmptyExtraData(),
     media::EncryptionScheme::kUnencrypted);
 
-const media::VideoDecoderConfig kUnencryptedH264Base1080Config(
-    media::VideoCodec::kH264,
-    media::H264PROFILE_MIN,
-    media::VideoDecoderConfig::AlphaMode::kIsOpaque,
-    media::VideoColorSpace(),
-    media::kNoTransformation,
-    k1080CodecSize,
-    kVisibleRect,
-    kNaturalSize,
-    media::EmptyExtraData(),
-    media::EncryptionScheme::kUnencrypted);
-
-const media::VideoDecoderConfig kUnencryptedH264Base4kConfig(
-    media::VideoCodec::kH264,
-    media::H264PROFILE_MIN,
-    media::VideoDecoderConfig::AlphaMode::kIsOpaque,
-    media::VideoColorSpace(),
-    media::kNoTransformation,
-    k4kCodecSize,
-    kVisibleRect,
-    kNaturalSize,
-    media::EmptyExtraData(),
-    media::EncryptionScheme::kUnencrypted);
-
-const media::VideoDecoderConfig kUnencryptedH264High4kConfig(
-    media::VideoCodec::kH264,
-    media::H264PROFILE_HIGH,
-    media::VideoDecoderConfig::AlphaMode::kIsOpaque,
-    media::VideoColorSpace(),
-    media::kNoTransformation,
-    k4kCodecSize,
-    kVisibleRect,
-    kNaturalSize,
-    media::EmptyExtraData(),
-    media::EncryptionScheme::kUnencrypted);
-
-const media::VideoDecoderConfig kUnencryptedVP9BaseConfig(
-    media::VideoCodec::kVP9,
-    media::VP9PROFILE_MIN,
-    media::VideoDecoderConfig::AlphaMode::kIsOpaque,
-    media::VideoColorSpace(),
-    media::kNoTransformation,
-    k1080CodecSize,
-    kVisibleRect,
-    kNaturalSize,
-    media::EmptyExtraData(),
-    media::EncryptionScheme::kUnencrypted);
-
-const media::VideoDecoderConfig kUnknownConfig(
-    media::VideoCodec::kUnknown,
-    media::VIDEO_CODEC_PROFILE_UNKNOWN,
-    media::VideoDecoderConfig::AlphaMode::kIsOpaque,
-    media::VideoColorSpace(),
-    media::kNoTransformation,
-    k4kCodecSize,
-    kVisibleRect,
-    kNaturalSize,
-    media::EmptyExtraData(),
-    media::EncryptionScheme::kUnencrypted);
-
-const fuchsia::math::SizeU k320CodedSize = {
-    .width = 568,
-    .height = 320,
+const fuchsia::mediacodec::CodecDescription kH264DecoderCodec = {
+    .codec_type = fuchsia::mediacodec::CodecType::DECODER,
+    .mime_type = "video/h264",
+    .is_hw = true,
 };
 
-const fuchsia::math::SizeU k480CodedSize = {
-    .width = 852,
-    .height = 480,
+const fuchsia::mediacodec::CodecDescription kVP9DecoderCodec = {
+    .codec_type = fuchsia::mediacodec::CodecType::DECODER,
+    .mime_type = "video/vp9",
+    .is_hw = true,
 };
 
-const fuchsia::math::SizeU k1080CodedSize = {
-    .width = 1920,
-    .height = 1080,
-};
-
-const fuchsia::math::SizeU k4kCodedSize = {
-    .width = 3840,
-    .height = 2160,
-};
-
-class FakeCodecFactoryWithNoCodecs
+// Partial fake implementation of a CodecFactory
+class FakeCodecFactory
     : public fuchsia::mediacodec::testing::CodecFactory_TestBase {
  public:
-  explicit FakeCodecFactoryWithNoCodecs(
-      sys::OutgoingDirectory* outgoing_services)
+  explicit FakeCodecFactory(sys::OutgoingDirectory* outgoing_services)
       : binding_(outgoing_services, this) {}
-  FakeCodecFactoryWithNoCodecs(const FakeCodecFactoryWithNoCodecs&) = delete;
-  FakeCodecFactoryWithNoCodecs& operator=(const FakeCodecFactoryWithNoCodecs&) =
-      delete;
-  ~FakeCodecFactoryWithNoCodecs() override = default;
+  FakeCodecFactory(const FakeCodecFactory&) = delete;
+  FakeCodecFactory& operator=(const FakeCodecFactory&) = delete;
+  ~FakeCodecFactory() override = default;
 
-  void GetDetailedCodecDescriptions(
-      GetDetailedCodecDescriptionsCallback callback) override {
-    callback(std::move(
-        fuchsia::mediacodec::CodecFactoryGetDetailedCodecDescriptionsResponse()
-            .set_codecs({})));
+  void TriggerOnCodecListEvent(
+      std::vector<fuchsia::mediacodec::CodecDescription> codec_list) {
+    binding_.events().OnCodecList(codec_list);
   }
 
   void NotImplemented_(const std::string& name) override {
     ADD_FAILURE() << "Unimplemented function called: " << name;
   }
 
- protected:
+ private:
   base::ScopedSingleClientServiceBinding<fuchsia::mediacodec::CodecFactory>
       binding_;
 };
 
-// Partial fake implementation of a CodecFactory
-class FakeCodecFactory : FakeCodecFactoryWithNoCodecs {
- public:
-  explicit FakeCodecFactory(sys::OutgoingDirectory* outgoing_services)
-      : FakeCodecFactoryWithNoCodecs(outgoing_services) {}
-
-  void GetDetailedCodecDescriptions(
-      GetDetailedCodecDescriptionsCallback callback) override {
-    std::vector<fuchsia::mediacodec::DetailedCodecDescription> codec_list;
-    codec_list.push_back(GetAudioDetailedCodecDescription());
-    codec_list.push_back(GetSwDetailedCodecDescription());
-    codec_list.push_back(GetUnknownDetailedCodecDescription());
-    codec_list.push_back(GetUnencryptedH264DetailedCodecDescription());
-    codec_list.push_back(GetEncryptedVP9DetailedCodecDescription());
-    callback(std::move(
-        fuchsia::mediacodec::CodecFactoryGetDetailedCodecDescriptionsResponse()
-            .set_codecs(std::move(codec_list))));
-  }
-
- private:
-  fuchsia::mediacodec::DetailedCodecDescription
-  GetAudioDetailedCodecDescription() {
-    std::vector<fuchsia::mediacodec::DecoderProfileDescription> profile_list;
-
-    profile_list.push_back(
-        std::move(fuchsia::mediacodec::DecoderProfileDescription()
-                      .set_split_header_handling(false)));
-
-    return std::move(
-        fuchsia::mediacodec::DetailedCodecDescription()
-            .set_codec_type(fuchsia::mediacodec::CodecType::DECODER)
-            .set_mime_type("audio/aac")
-            .set_is_hw(true)
-            .set_profile_descriptions(
-                std::move(fuchsia::mediacodec::ProfileDescriptions()
-                              .set_decoder_profile_descriptions(
-                                  std::move(profile_list)))));
-  }
-
-  // Returns a software decoder codec that has a higher profile and a larger
-  // image size range than `GetUnencryptedH264DetailedCodecDescription` returns.
-  fuchsia::mediacodec::DetailedCodecDescription
-  GetSwDetailedCodecDescription() {
-    std::vector<fuchsia::mediacodec::DecoderProfileDescription> profile_list;
-
-    profile_list.push_back(std::move(
-        fuchsia::mediacodec::DecoderProfileDescription()
-            .set_profile(fuchsia::media::CodecProfile::H264PROFILE_HIGH)
-            .set_max_image_size(k4kCodedSize)
-            .set_min_image_size(k320CodedSize)));
-
-    return std::move(
-        fuchsia::mediacodec::DetailedCodecDescription()
-            .set_codec_type(fuchsia::mediacodec::CodecType::DECODER)
-            .set_mime_type("video/h264")
-            .set_is_hw(false)
-            .set_profile_descriptions(
-                std::move(fuchsia::mediacodec::ProfileDescriptions()
-                              .set_decoder_profile_descriptions(
-                                  std::move(profile_list)))));
-  }
-
-  fuchsia::mediacodec::DetailedCodecDescription
-  GetUnknownDetailedCodecDescription() {
-    std::vector<fuchsia::mediacodec::DecoderProfileDescription> profile_list;
-
-    profile_list.push_back(
-        std::move(fuchsia::mediacodec::DecoderProfileDescription()
-                      .set_profile(fuchsia::media::CodecProfile::MJPEG_BASELINE)
-                      .set_max_image_size(k4kCodedSize)
-                      .set_min_image_size(k320CodedSize)));
-
-    return std::move(
-        fuchsia::mediacodec::DetailedCodecDescription()
-            .set_codec_type(fuchsia::mediacodec::CodecType::DECODER)
-            .set_mime_type("video/unknown")
-            .set_is_hw(true)
-            .set_profile_descriptions(
-                std::move(fuchsia::mediacodec::ProfileDescriptions()
-                              .set_decoder_profile_descriptions(
-                                  std::move(profile_list)))));
-  }
-
-  fuchsia::mediacodec::DetailedCodecDescription
-  GetUnencryptedH264DetailedCodecDescription() {
-    std::vector<fuchsia::mediacodec::DecoderProfileDescription> profile_list;
-
-    profile_list.push_back(std::move(
-        fuchsia::mediacodec::DecoderProfileDescription()
-            .set_profile(fuchsia::media::CodecProfile::H264PROFILE_BASELINE)
-            .set_max_image_size(k1080CodedSize)
-            .set_min_image_size(k480CodedSize)));
-
-    return std::move(
-        fuchsia::mediacodec::DetailedCodecDescription()
-            .set_codec_type(fuchsia::mediacodec::CodecType::DECODER)
-            .set_mime_type("video/h264")
-            .set_is_hw(true)
-            .set_profile_descriptions(
-                std::move(fuchsia::mediacodec::ProfileDescriptions()
-                              .set_decoder_profile_descriptions(
-                                  std::move(profile_list)))));
-  }
-
-  fuchsia::mediacodec::DetailedCodecDescription
-  GetEncryptedVP9DetailedCodecDescription() {
-    std::vector<fuchsia::mediacodec::DecoderProfileDescription> profile_list;
-
-    profile_list.push_back(std::move(
-        fuchsia::mediacodec::DecoderProfileDescription()
-            .set_profile(fuchsia::media::CodecProfile::VP9PROFILE_PROFILE0)
-            .set_max_image_size(k1080CodedSize)
-            .set_min_image_size(k480CodedSize)
-            .set_allow_encryption(true)
-            .set_require_encryption(true)));
-
-    return std::move(
-        fuchsia::mediacodec::DetailedCodecDescription()
-            .set_codec_type(fuchsia::mediacodec::CodecType::DECODER)
-            .set_mime_type("video/vp9")
-            .set_is_hw(true)
-            .set_profile_descriptions(
-                std::move(fuchsia::mediacodec::ProfileDescriptions()
-                              .set_decoder_profile_descriptions(
-                                  std::move(profile_list)))));
-  }
-};
-
 }  // namespace
 
 class FuchsiaMediaCodecProviderImplTest : public testing::Test {
@@ -329,6 +99,13 @@
   ~FuchsiaMediaCodecProviderImplTest() override = default;
 
  protected:
+  std::unique_ptr<FuchsiaMediaCodecProviderImpl> CreateMediaCodecProvider() {
+    auto* media_codec_provider = new FuchsiaMediaCodecProviderImpl();
+    // Wait until event bindings are done.
+    task_enviornment_.RunUntilIdle();
+    return base::WrapUnique(media_codec_provider);
+  }
+
   base::test::SingleThreadTaskEnvironment task_enviornment_{
       base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
 
@@ -336,7 +113,7 @@
 };
 
 TEST_F(FuchsiaMediaCodecProviderImplTest, NoMediaCodecConnection) {
-  auto* media_codec_provider = new FuchsiaMediaCodecProviderImpl();
+  auto media_codec_provider = CreateMediaCodecProvider();
   base::test::TestFuture<const media::SupportedVideoDecoderConfigs&> future;
 
   media_codec_provider->GetSupportedVideoDecoderConfigs(future.GetCallback());
@@ -347,9 +124,13 @@
 TEST_F(FuchsiaMediaCodecProviderImplTest, DisconnectWhileGettingCodecList) {
   auto codec_factory_ptr = std::make_unique<FakeCodecFactory>(
       component_context_.additional_services());
-  auto* media_codec_provider = new FuchsiaMediaCodecProviderImpl();
+  auto media_codec_provider = CreateMediaCodecProvider();
   base::test::TestFuture<const media::SupportedVideoDecoderConfigs&> future;
 
+  codec_factory_ptr->TriggerOnCodecListEvent({kH264DecoderCodec});
+  // Wait until the event is handled.
+  task_enviornment_.RunUntilIdle();
+
   // Disconnect the service.
   codec_factory_ptr.reset();
 
@@ -358,79 +139,74 @@
   EXPECT_TRUE(future.Get().empty());
 }
 
-TEST_F(FuchsiaMediaCodecProviderImplTest, EmptyCodecList) {
-  FakeCodecFactoryWithNoCodecs codec_factory(
-      component_context_.additional_services());
-  auto* media_codec_provider = new FuchsiaMediaCodecProviderImpl();
-  base::test::TestFuture<const media::SupportedVideoDecoderConfigs&> future;
-
-  media_codec_provider->GetSupportedVideoDecoderConfigs(future.GetCallback());
-  EXPECT_TRUE(future.Wait());
-  EXPECT_TRUE(future.Get().empty());
-}
-
 TEST_F(FuchsiaMediaCodecProviderImplTest, GetSupportedVideoDecoderConfigs) {
   FakeCodecFactory codec_factory(component_context_.additional_services());
-  auto* media_codec_provider = new FuchsiaMediaCodecProviderImpl();
+  auto media_codec_provider = CreateMediaCodecProvider();
   base::test::TestFuture<const media::SupportedVideoDecoderConfigs&> future;
 
   media_codec_provider->GetSupportedVideoDecoderConfigs(future.GetCallback());
+  // Wait until the callback is queued up.
+  task_enviornment_.RunUntilIdle();
 
-  // Only the VP9 codec config from `GetEncryptedVP9DetailedCodecDescription`
-  // and the H264 codec config from `GetUnencryptedH264DetailedCodecDescription`
-  // are supported. Ensure that entries are not added for the audio, unknown and
-  // software codecs.
-  const size_t kExpectedNumSupportedConfigs = 2;
-  EXPECT_EQ(future.Get().size(), kExpectedNumSupportedConfigs);
+  codec_factory.TriggerOnCodecListEvent({kH264DecoderCodec});
+  // Wait until the event is handled.
+  task_enviornment_.RunUntilIdle();
 
-  // The H264 codec config from `GetUnencryptedH264DetailedCodecDescription`
-  // does not support encryption.
-  EXPECT_TRUE(media::IsVideoDecoderConfigSupported(
-      future.Get(), kUnencryptedH264Base1080Config));
-  EXPECT_FALSE(media::IsVideoDecoderConfigSupported(
-      future.Get(), kEncryptedH264Base1080Config));
-
-  // The VP9 codec config from `GetEncryptedVP9DetailedCodecDescription`
-  // requires (not just supports) encryption.
-  EXPECT_TRUE(media::IsVideoDecoderConfigSupported(future.Get(),
-                                                   kEncryptedVP9BaseConfig));
-  EXPECT_FALSE(media::IsVideoDecoderConfigSupported(future.Get(),
-                                                    kUnencryptedVP9BaseConfig));
-
-  // FakeCodecFactory does not support hardware-accelerated H264 High profile
-  // video codec or VP9 max codec is supported.
-  EXPECT_FALSE(media::IsVideoDecoderConfigSupported(
-      future.Get(), kUnencryptedH264High4kConfig));
-  EXPECT_FALSE(media::IsVideoDecoderConfigSupported(future.Get(),
-                                                    kEncryptedVP9MaxConfig));
-
-  // FakeCodecFactory only supports H264 Base profile from 480p to 1080p.
-  // It supports a software H264 Base profile from 320p to 4k, but it should be
-  // ignored.
-  EXPECT_FALSE(media::IsVideoDecoderConfigSupported(
-      future.Get(), kUnencryptedH264Base320Config));
-  EXPECT_FALSE(media::IsVideoDecoderConfigSupported(
-      future.Get(), kUnencryptedH264Base4kConfig));
-
-  // Unknown video decoder config should not be supported.
-  EXPECT_FALSE(
-      media::IsVideoDecoderConfigSupported(future.Get(), kUnknownConfig));
+  EXPECT_TRUE(
+      media::IsVideoDecoderConfigSupported(future.Get(), kH264BaseConfig));
 }
 
 TEST_F(FuchsiaMediaCodecProviderImplTest,
        GetSupportedVideoDecoderConfigsInAQueue) {
   FakeCodecFactory codec_factory(component_context_.additional_services());
-  auto* media_codec_provider = new FuchsiaMediaCodecProviderImpl();
+  auto media_codec_provider = CreateMediaCodecProvider();
   base::test::TestFuture<const media::SupportedVideoDecoderConfigs&> future_1;
   base::test::TestFuture<const media::SupportedVideoDecoderConfigs&> future_2;
 
   media_codec_provider->GetSupportedVideoDecoderConfigs(future_1.GetCallback());
   media_codec_provider->GetSupportedVideoDecoderConfigs(future_2.GetCallback());
+  // Wait until the callbacks are queued up.
+  task_enviornment_.RunUntilIdle();
 
-  EXPECT_TRUE(media::IsVideoDecoderConfigSupported(
-      future_1.Get(), kUnencryptedH264Base1080Config));
-  EXPECT_TRUE(media::IsVideoDecoderConfigSupported(
-      future_2.Get(), kUnencryptedH264Base1080Config));
+  codec_factory.TriggerOnCodecListEvent({kH264DecoderCodec});
+  // Wait until the event is handled.
+  task_enviornment_.RunUntilIdle();
+
+  EXPECT_TRUE(
+      media::IsVideoDecoderConfigSupported(future_1.Get(), kH264BaseConfig));
+  EXPECT_TRUE(
+      media::IsVideoDecoderConfigSupported(future_2.Get(), kH264BaseConfig));
+}
+
+TEST_F(FuchsiaMediaCodecProviderImplTest,
+       CodecListUpdatesWhileGettingSupportedVideoDecoderConfigs) {
+  FakeCodecFactory codec_factory(component_context_.additional_services());
+  auto media_codec_provider = CreateMediaCodecProvider();
+  base::test::TestFuture<const media::SupportedVideoDecoderConfigs&> future_1;
+  base::test::TestFuture<const media::SupportedVideoDecoderConfigs&> future_2;
+
+  media_codec_provider->GetSupportedVideoDecoderConfigs(future_1.GetCallback());
+  // Wait until the callback is queued up.
+  task_enviornment_.RunUntilIdle();
+
+  codec_factory.TriggerOnCodecListEvent({kH264DecoderCodec});
+  // Wait until the event is handled.
+  task_enviornment_.RunUntilIdle();
+
+  codec_factory.TriggerOnCodecListEvent({kVP9DecoderCodec});
+  // Wait until the event is handled.
+  task_enviornment_.RunUntilIdle();
+  media_codec_provider->GetSupportedVideoDecoderConfigs(future_2.GetCallback());
+  EXPECT_TRUE(future_2.Wait());
+
+  EXPECT_TRUE(
+      media::IsVideoDecoderConfigSupported(future_1.Get(), kH264BaseConfig));
+  EXPECT_FALSE(
+      media::IsVideoDecoderConfigSupported(future_1.Get(), kVP9BaseConfig));
+  EXPECT_TRUE(
+      media::IsVideoDecoderConfigSupported(future_2.Get(), kVP9BaseConfig));
+  EXPECT_FALSE(
+      media::IsVideoDecoderConfigSupported(future_2.Get(), kH264BaseConfig));
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 74d0598..ee22a922 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -4654,14 +4654,12 @@
   if (frame_tree_node_->IsErrorPageIsolationEnabled())
     return ErrorPageProcess::kIsolatedProcess;
 
-  // Site-isolated <webview> guests do not currently support committing
-  // error pages with an unknown URL scheme (such as when navigating a guest to
-  // an external protocol) in the process computed for the destination URL.
-  // Therefore, leave such cases in the original process. See
-  // https://crbug.com/1366450.
+  // <webview> guests do not currently support committing error pages with
+  // an unknown URL scheme (such as when navigating a guest to an external
+  // protocol) in the process computed for the destination URL. Therefore,
+  // leave such cases in the original process. See https://crbug.com/1366450.
   if (net_error == net::ERR_UNKNOWN_URL_SCHEME &&
-      frame_tree_node_->current_frame_host()->GetSiteInstance()->IsGuest() &&
-      SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled()) {
+      frame_tree_node_->current_frame_host()->GetSiteInstance()->IsGuest()) {
     return ErrorPageProcess::kCurrentProcess;
   }
 
diff --git a/content/browser/renderer_host/render_frame_host_impl_interface_binders.cc b/content/browser/renderer_host/render_frame_host_impl_interface_binders.cc
index 06f95c2..0a0224d 100644
--- a/content/browser/renderer_host/render_frame_host_impl_interface_binders.cc
+++ b/content/browser/renderer_host/render_frame_host_impl_interface_binders.cc
@@ -319,10 +319,10 @@
           },
           base::Unretained(this)));
 
-  associated_registry_->AddInterface<blink::mojom::ConversionHost>(
+  associated_registry_->AddInterface<blink::mojom::AttributionHost>(
       base::BindRepeating(
           [](RenderFrameHostImpl* impl,
-             mojo::PendingAssociatedReceiver<blink::mojom::ConversionHost>
+             mojo::PendingAssociatedReceiver<blink::mojom::AttributionHost>
                  receiver) {
             AttributionHost::BindReceiver(std::move(receiver), impl);
           },
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 0c39b117..54f38b8 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -2216,15 +2216,6 @@
 
   SiteInstanceImpl* current_instance = render_frame_host_->GetSiteInstance();
 
-  // Do not currently swap processes for navigations in webview tag guests,
-  // unless site isolation is enabled for them.
-  if (current_instance->IsGuest() &&
-      !SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled()) {
-    AppendReason(reason,
-                 "GetSiteInstanceForNavigation => current_instance (IsGuest)");
-    return current_instance;
-  }
-
   // Determine if we need a new BrowsingInstance for this entry.  If true, this
   // implies that it will get a new SiteInstance (and likely process), and that
   // other tabs in the current BrowsingInstance will be unable to script it.
@@ -2936,11 +2927,9 @@
 
   // If the current SiteInstance is for a guest, the new unrelated
   // SiteInstance must also be for a guest and must stay in the same
-  // StoragePartition.  Note that we should only attempt BrowsingInstance
-  // swaps in guests when site isolation for guests is enabled.
+  // StoragePartition.
   UrlInfo dest_url_info = descriptor.dest_url_info;
   if (current_instance->IsGuest()) {
-    DCHECK(SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled());
     dest_url_info.storage_partition_config =
         current_instance->GetSiteInfo().storage_partition_config();
   }
@@ -4096,9 +4085,7 @@
       // it would end up trying to focus the root view. Instead, we need to
       // focus the new main frame's RenderWidgetHost, which would set the new
       // widget as focused and also propagate page-level focus to the
-      // corresponding renderer process. Note that for <webview> guests, this
-      // case is only reached when cross-process navigations are possible,
-      // which requires features::kSiteIsolationForGuests.
+      // corresponding renderer process.
       if (frame_tree_node_->GetParentOrOuterDocumentOrEmbedder()) {
         render_frame_host_->GetRenderWidgetHost()->Focus();
       } else {
diff --git a/content/browser/renderer_host/render_frame_host_manager_unittest.cc b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
index 5dd16f76..0dd253e 100644
--- a/content/browser/renderer_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
@@ -1463,9 +1463,8 @@
             rfh2->GetRenderViewHost()->opener_frame_token());
 }
 
-// Test guest navigation behavior when navigating across sites.  With site
-// isolation for guests, we should swap guest SiteInstances, otherwise the
-// guest SiteInstance should be reused.
+// Test guest navigation behavior when navigating across sites.  Since guests
+// support site isolation, we should swap guest SiteInstances as usual.
 TEST_P(RenderFrameHostManagerTest, GuestNavigations) {
   // Create a custom StoragePartitionConfig for the guest SiteInstance. The
   // resulting SiteInstance should become associated with this
@@ -1503,29 +1502,22 @@
   EXPECT_EQ(first_instance->GetStoragePartitionConfig(), kGuestPartitionConfig);
   EXPECT_TRUE(first_instance->IsGuest());
 
-  // Without site isolation for guests, we should stay in the same initial
-  // RenderFrameHost and SiteInstance.  With site isolation for guests, we have
-  // to swap SiteInstances and RenderFrameHosts, since the initial SiteInstance
-  // (`instance`) has an empty site and process lock, whereas the navigation
-  // needs a SiteInstance with the site URL that corresponds to `kUrl1`.  Note
-  // that even in that case, there will be no speculative RenderFrameHost since
-  // the new RenderFrameHost will be committed right away due to the early
-  // commit optimization. This behavior may change if the early commit
-  // optimization is removed in https://crbug.com/1072817.
-  if (SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled()) {
-    EXPECT_NE(first_instance, initial_instance);
-    EXPECT_NE(host, initial_host);
-    // This test may run without strict site isolation, e.g. on Android.  In
-    // that case, the navigation will end up in a default SiteInstance.
-    if (AreAllSitesIsolatedForTesting()) {
-      EXPECT_EQ("http://google.com/",
-                first_instance->GetSiteInfo().site_url().spec());
-    } else {
-      EXPECT_TRUE(first_instance->IsDefaultSiteInstance());
-    }
+  // We have to swap SiteInstances and RenderFrameHosts, since the initial
+  // SiteInstance (`instance`) has an empty site and process lock, whereas the
+  // navigation needs a SiteInstance with the site URL that corresponds to
+  // `kUrl1`.  Note that there will be no speculative RenderFrameHost in that
+  // case, since the new RenderFrameHost will be committed right away due to
+  // the early commit optimization. This behavior may change if the early
+  // commit optimization is removed in https://crbug.com/1072817.
+  EXPECT_NE(first_instance, initial_instance);
+  EXPECT_NE(host, initial_host);
+  // This test may run without strict site isolation, e.g. on Android.  In
+  // that case, the navigation will end up in a default SiteInstance.
+  if (AreAllSitesIsolatedForTesting()) {
+    EXPECT_EQ("http://google.com/",
+              first_instance->GetSiteInfo().site_url().spec());
   } else {
-    EXPECT_EQ(first_instance, initial_instance);
-    EXPECT_EQ(host, initial_host);
+    EXPECT_TRUE(first_instance->IsDefaultSiteInstance());
   }
   EXPECT_FALSE(manager->speculative_frame_host());
   EXPECT_EQ(host, manager->current_frame_host());
@@ -1537,9 +1529,8 @@
   EXPECT_TRUE(host->GetSiteInstance()->HasSite());
 
   // 2) Second navigation. ------------------------
-  // Navigate to a different site. If site isolation for guests is enabled, and
-  // strict site isolation is also enabled, this will swap processes.
-  // Otherwise, the guest will stay in the same process.
+  // Navigate to a different site. If strict site isolation is enabled, this
+  // will swap processes. Otherwise, the guest will stay in the same process.
   const GURL kUrl2("http://www.chromium.org");
   const url::Origin kInitiatorOrigin =
       url::Origin::Create(GURL("https://initiator.example.com"));
@@ -1553,9 +1544,8 @@
   host = NavigateToEntry(manager, &entry2);
 
   // The first RenderFrameHost will be reused only when there's no site
-  // isolation for guests (or no site isolation between the two sites).
-  if (SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled() &&
-      AreAllSitesIsolatedForTesting()) {
+  // isolation between the two sites.
+  if (AreAllSitesIsolatedForTesting()) {
     EXPECT_NE(host, manager->current_frame_host());
     EXPECT_TRUE(manager->speculative_frame_host());
   } else {
@@ -1569,9 +1559,7 @@
   ASSERT_TRUE(host);
   EXPECT_TRUE(host->GetSiteInstance()->IsGuest());
 
-  // We should swap SiteInstances with site isolation for guests.
-  if (SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled() &&
-      AreAllSitesIsolatedForTesting()) {
+  if (AreAllSitesIsolatedForTesting()) {
     EXPECT_NE(host->GetSiteInstance(), first_instance);
     EXPECT_EQ("http://chromium.org/",
               host->GetSiteInstance()->GetSiteInfo().site_url().spec());
diff --git a/content/browser/renderer_host/render_widget_targeter.cc b/content/browser/renderer_host/render_widget_targeter.cc
index 27d627d..fb15f29 100644
--- a/content/browser/renderer_host/render_widget_targeter.cc
+++ b/content/browser/renderer_host/render_widget_targeter.cc
@@ -42,49 +42,10 @@
               blink::WebPointerProperties::Button::kMiddle);
 }
 
-constexpr const char kTracingCategory[] = "input,latency";
-
 constexpr base::TimeDelta kAsyncHitTestTimeout = base::Seconds(5);
 
 }  // namespace
 
-class TracingUmaTracker {
- public:
-  explicit TracingUmaTracker(const char* metric_name)
-      : id_(next_id_++),
-        start_time_(base::TimeTicks::Now()),
-        metric_name_(metric_name) {
-    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
-        kTracingCategory, metric_name_,
-        TRACE_ID_WITH_SCOPE("UmaTracker", TRACE_ID_LOCAL(id_)));
-  }
-
-  TracingUmaTracker(const TracingUmaTracker&) = delete;
-  TracingUmaTracker& operator=(const TracingUmaTracker&) = delete;
-
-  ~TracingUmaTracker() = default;
-  TracingUmaTracker(TracingUmaTracker&& tracker) = default;
-
-  void StopAndRecord() {
-    TRACE_EVENT_NESTABLE_ASYNC_END0(
-        kTracingCategory, metric_name_,
-        TRACE_ID_WITH_SCOPE("UmaTracker", TRACE_ID_LOCAL(id_)));
-    UmaHistogramTimes(metric_name_, base::TimeTicks::Now() - start_time_);
-  }
-
- private:
-  const int id_;
-  const base::TimeTicks start_time_;
-
-  // These variables must be string literals and live for the duration
-  // of the program since tracing stores pointers.
-  const char* metric_name_;
-
-  static int next_id_;
-};
-
-int TracingUmaTracker::next_id_ = 1;
-
 RenderWidgetTargetResult::RenderWidgetTargetResult() = default;
 
 RenderWidgetTargetResult::RenderWidgetTargetResult(
@@ -305,7 +266,6 @@
 
   request_in_flight_ = std::move(request);
 
-  TracingUmaTracker tracker("Event.AsyncTargeting.ResponseTime");
   async_hit_test_timeout_.Start(
       FROM_HERE, async_hit_test_timeout_delay_,
       base::BindOnce(
@@ -327,7 +287,7 @@
       target_location, trace_id_,
       base::BindOnce(&RenderWidgetTargeter::FoundFrameSinkId,
                      weak_ptr_factory_.GetWeakPtr(), target->GetWeakPtr(),
-                     ++last_request_id_, target_location, std::move(tracker)));
+                     ++last_request_id_, target_location));
 }
 
 void RenderWidgetTargeter::FlushEventQueue() {
@@ -355,13 +315,11 @@
     base::WeakPtr<RenderWidgetHostViewBase> target,
     uint32_t request_id,
     const gfx::PointF& target_location,
-    TracingUmaTracker tracker,
     const viz::FrameSinkId& frame_sink_id,
     const gfx::PointF& transformed_location) {
-  if (!target)
+  if (!target) {
     return;
-
-  tracker.StopAndRecord();
+  }
 
   uint32_t last_id = last_request_id_;
   bool in_flight = request_in_flight_.has_value();
@@ -381,8 +339,9 @@
       base::OnceClosure());
 
   auto* view = delegate_->FindViewFromFrameSinkId(frame_sink_id);
-  if (!view)
+  if (!view) {
     view = target.get();
+  }
 
   // If a client returned an embedded target, then it might be necessary to
   // continue asking the clients until a client claims an event for itself.
diff --git a/content/browser/renderer_host/render_widget_targeter.h b/content/browser/renderer_host/render_widget_targeter.h
index ab0b5c0a..83cee27 100644
--- a/content/browser/renderer_host/render_widget_targeter.h
+++ b/content/browser/renderer_host/render_widget_targeter.h
@@ -50,8 +50,6 @@
   bool latched_target = false;
 };
 
-class TracingUmaTracker;
-
 class RenderWidgetTargeter {
  public:
   using RenderWidgetHostAtPointCallback =
@@ -203,7 +201,6 @@
   void FoundFrameSinkId(base::WeakPtr<RenderWidgetHostViewBase> target,
                         uint32_t request_id,
                         const gfx::PointF& target_location,
-                        TracingUmaTracker tracker,
                         const viz::FrameSinkId& frame_sink_id,
                         const gfx::PointF& transformed_location);
 
diff --git a/content/browser/scheduler/browser_ui_thread_scheduler.h b/content/browser/scheduler/browser_ui_thread_scheduler.h
index c15b5c0..5ee09f00 100644
--- a/content/browser/scheduler/browser_ui_thread_scheduler.h
+++ b/content/browser/scheduler/browser_ui_thread_scheduler.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/task/sequence_manager/task_queue.h"
 #include "base/time/time.h"
 #include "content/browser/scheduler/browser_task_queues.h"
@@ -40,7 +41,9 @@
     void MoveFrom(UserInputActiveHandle* other);
     // Only this constructor actually creates a UserInputActiveHandle that will
     // inform scheduling decisions.
-    BrowserUIThreadScheduler* scheduler_ = nullptr;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #union
+    RAW_PTR_EXCLUSION BrowserUIThreadScheduler* scheduler_ = nullptr;
   };
 
   enum ScrollState { kGestureScrollActive, kFlingActive, kNone };
diff --git a/content/browser/serial/serial_unittest.cc b/content/browser/serial/serial_unittest.cc
index 3633599c..e864f14 100644
--- a/content/browser/serial/serial_unittest.cc
+++ b/content/browser/serial/serial_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/barrier_closure.h"
 #include "base/command_line.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/run_loop.h"
 #include "base/test/gmock_callback_support.h"
 #include "base/test/test_future.h"
@@ -92,7 +93,9 @@
   SerialTestContentBrowserClient test_client_;
   raw_ptr<ContentBrowserClient> original_client_ = nullptr;
   device::FakeSerialPortManager port_manager_;
-  SerialDelegate::Observer* observer_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION SerialDelegate::Observer* observer_ = nullptr;
 };
 
 }  // namespace
diff --git a/content/browser/site_info.cc b/content/browser/site_info.cc
index a33fe2a5..ea20846 100644
--- a/content/browser/site_info.cc
+++ b/content/browser/site_info.cc
@@ -8,7 +8,6 @@
 #include "base/containers/contains.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/ranges/algorithm.h"
-#include "base/strings/escape.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "content/browser/child_process_security_policy_impl.h"
@@ -75,106 +74,6 @@
   return GURL(scheme + url::kStandardSchemeSeparator + host);
 }
 
-// Strings used to encode blob url fallback mode in guest site URLs.
-constexpr char kNoFallback[] = "nofallback";
-constexpr char kInMemoryFallback[] = "inmemoryfallback";
-constexpr char kOnDiskFallback[] = "ondiskfallback";
-
-// SiteInstances for <webview> guests currently use a special site URL that
-// encodes that guest's StoragePartition configuration, including the partition
-// name and whether the storage for that partition should be persisted. This
-// helper translates a guest's StoragePartitionConfig into a site URL, and
-// GetGuestPartitionConfigForSite below performs the opposite translation.
-// The format for a guest site URL is:
-// chrome-guest://partition_domain/persist?partition_name
-// The `partition_domain` (i.e., the site URL's host) identifies the guest's
-// embedder.
-//
-// TODO(alexmos): Guest site URLs are deprecated and will be removed once
-// <webview> guests support site isolation.  See https://crbug.com/1267977.
-GURL GetSiteURLForGuestPartitionConfig(
-    const StoragePartitionConfig& storage_partition_config) {
-  DCHECK(!storage_partition_config.is_default());
-  std::string url_encoded_partition = base::EscapeQueryParamValue(
-      storage_partition_config.partition_name(), false);
-  const char* fallback = "";
-  switch (
-      storage_partition_config.fallback_to_partition_domain_for_blob_urls()) {
-    case StoragePartitionConfig::FallbackMode::kNone:
-      fallback = kNoFallback;
-      break;
-    case StoragePartitionConfig::FallbackMode::kFallbackPartitionOnDisk:
-      fallback = kOnDiskFallback;
-      break;
-    case StoragePartitionConfig::FallbackMode::kFallbackPartitionInMemory:
-      fallback = kInMemoryFallback;
-      break;
-  }
-  return GURL(
-      base::StringPrintf("%s://%s/%s?%s#%s", kGuestScheme,
-                         storage_partition_config.partition_domain().c_str(),
-                         storage_partition_config.in_memory() ? "" : "persist",
-                         url_encoded_partition.c_str(), fallback));
-}
-
-// Opposite of GetSiteURLForGuestPartitionConfig. Converts the provided site
-// URL of a <webview> guest into a StoragePartitionConfig.  The return value
-// indicates whether the translation succeeded.
-bool GetGuestPartitionConfigForSite(
-    BrowserContext* browser_context,
-    const GURL& site,
-    StoragePartitionConfig* storage_partition_config) {
-  if (!site.SchemeIs(kGuestScheme))
-    return false;
-
-  // The partition name is user supplied value, which we have encoded when the
-  // URL was created, so it needs to be decoded. Since it was created via
-  // EscapeQueryParamValue(), it should have no path separators or control codes
-  // when unescaped, but safest to check for that and fail if it does.
-  std::string partition_name;
-  if (!base::UnescapeBinaryURLComponentSafe(site.query_piece(),
-                                            true /* fail_on_path_separators */,
-                                            &partition_name)) {
-    return false;
-  }
-
-  // The host must contain an ID for the guest's embedder (e.g., packaged app's
-  // ID or WebUI host).
-  CHECK(site.has_host());
-
-  // Since persistence is optional, the path must either be empty or the
-  // literal string.
-  bool in_memory = (site.path() != "/persist");
-
-  *storage_partition_config = StoragePartitionConfig::Create(
-      browser_context, site.host(), partition_name, in_memory);
-
-  // A <webview> guest inside an embedder needs to be able to resolve Blob URLs
-  // that were created by the embedder (such as a Chrome app). The embedder has
-  // the same partition_domain but empty partition_name. Setting this flag on
-  // the partition config causes it to be used as fallback for the purpose of
-  // resolving blob URLs.
-  //
-  // Default to having the fallback partition on disk, as that matches most
-  // closely what we would have done before fallback behavior started being
-  // encoded in the site URL.
-  StoragePartitionConfig::FallbackMode fallback_mode =
-      StoragePartitionConfig::FallbackMode::kFallbackPartitionOnDisk;
-  if (site.ref() == kNoFallback) {
-    fallback_mode = StoragePartitionConfig::FallbackMode::kNone;
-  } else if (site.ref() == kInMemoryFallback) {
-    fallback_mode =
-        StoragePartitionConfig::FallbackMode::kFallbackPartitionInMemory;
-  } else if (site.ref() == kOnDiskFallback) {
-    fallback_mode =
-        StoragePartitionConfig::FallbackMode::kFallbackPartitionOnDisk;
-  }
-  storage_partition_config->set_fallback_to_partition_domain_for_blob_urls(
-      fallback_mode);
-
-  return true;
-}
-
 }  // namespace
 
 // static
@@ -218,26 +117,15 @@
 SiteInfo SiteInfo::CreateForGuest(
     BrowserContext* browser_context,
     const StoragePartitionConfig& partition_config) {
-  // Traditionally, site URLs for guests were expected to have a special value
-  // that encodes the StoragePartition information. With site isolation for
-  // guests, however, this is no longer the case, and guests may use regular
-  // site and lock URLs, and the StoragePartition information is maintained in
-  // a separate SiteInfo field.  See https://crbug.com/1267977 for more info.
-  //
-  // Thus, when site isolation for guests is not used, set the site and lock
-  // URLs to the legacy value.  Otherwise, leave them as empty for now; this
+  // Guests use regular site and lock URLs, and their StoragePartition
+  // information is maintained in a separate SiteInfo field.  Since this
   // function is called when a guest SiteInstance is first created (prior to
-  // any navigations), so there is no URL at this point to compute proper site
-  // and lock URLs.  Future navigations (if any) in the guest, will follow the
-  // normal process selection paths and use SiteInstances with real site and
-  // lock URLs.
-  GURL guest_site_url =
-      SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled()
-          ? GURL()
-          : GetSiteURLForGuestPartitionConfig(partition_config);
-
+  // any navigations), there is no URL at this point to compute proper site and
+  // lock URLs, so leave them empty for now.  Future navigations (if any) in
+  // the guest will follow the normal process selection paths and use
+  // SiteInstances with real site and lock URLs.
   return SiteInfo(
-      guest_site_url, guest_site_url, false /* requires_origin_keyed_process */,
+      GURL(), GURL(), false /* requires_origin_keyed_process */,
       false /* is_sandboxed */, UrlInfo::kInvalidUniqueSandboxId,
       partition_config, WebExposedIsolationInfo::CreateNonIsolated(),
       true /* is_guest */,
@@ -293,8 +181,7 @@
 
     if (!storage_partition_config.has_value()) {
       storage_partition_config =
-          GetStoragePartitionConfigForUrl(browser_context, site_url,
-                                          /*is_site_url=*/true);
+          GetStoragePartitionConfigForUrl(browser_context, site_url);
     }
   }
   DCHECK(storage_partition_config.has_value());
@@ -679,13 +566,6 @@
   if (!RequiresDedicatedProcess(isolation_context))
     return false;
 
-  // Legacy guest processes without site isolation support cannot be locked to
-  // a specific site, because those guests always use a single SiteInstance for
-  // all URLs they load. The SiteInfo for those URLs do not match the SiteInfo
-  // of the guest SiteInstance so we skip locking these guest processes.
-  if (is_guest_ && !SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled())
-    return false;
-
   // Most WebUI processes should be locked on all platforms.  The only exception
   // is NTP, handled via the separate callout to the embedder.
   const auto& webui_schemes = URLDataManagerBackend::GetWebUISchemes();
@@ -728,28 +608,13 @@
 // static
 StoragePartitionConfig SiteInfo::GetStoragePartitionConfigForUrl(
     BrowserContext* browser_context,
-    const GURL& url,
-    bool is_site_url) {
-  if (url.is_empty())
+    const GURL& site_or_regular_url) {
+  if (site_or_regular_url.is_empty()) {
     return StoragePartitionConfig::CreateDefault(browser_context);
-
-  if (url.SchemeIs(kGuestScheme)) {
-    StoragePartitionConfig storage_partition_config =
-        StoragePartitionConfig::CreateDefault(browser_context);
-    // Guest schemes should only appear in site URLs.
-    DCHECK(is_site_url);
-
-    // This should only ever see guest site URLs generated within SiteInfo, so
-    // it shouldn't ever fail.
-    bool success = GetGuestPartitionConfigForSite(browser_context, url,
-                                                  &storage_partition_config);
-    DCHECK(success);
-
-    return storage_partition_config;
   }
 
   return GetContentClient()->browser()->GetStoragePartitionConfigForSite(
-      browser_context, url);
+      browser_context, site_or_regular_url);
 }
 
 void SiteInfo::WriteIntoTrace(perfetto::TracedValue context) const {
diff --git a/content/browser/site_info.h b/content/browser/site_info.h
index 09f26f45..9710b38 100644
--- a/content/browser/site_info.h
+++ b/content/browser/site_info.h
@@ -113,10 +113,9 @@
   // decisions, Create() should be used instead.
   static GURL GetSiteForOrigin(const url::Origin& origin);
 
-  // Returns a StoragePartitionConfig for the specified URL.
-  // If |is_site_url| is set to true, then |url| MUST be a site URL that
-  // was generated by a SiteInfo. Otherwise the URL is interpreted as a
-  // user-provided URL or origin.
+  // Returns a StoragePartitionConfig for the specified URL. Note that the URL
+  // can be both a site URL that was generated by a SiteInfo or a regular
+  // user-provided URL.
   //
   // Note: New callers of this method should be discouraged. New code should
   // have access to a SiteInfo object and call GetStoragePartitionConfig() on
@@ -126,8 +125,7 @@
   // this method.
   static StoragePartitionConfig GetStoragePartitionConfigForUrl(
       BrowserContext* browser_context,
-      const GURL& url,
-      bool is_site_url);
+      const GURL& site_or_regular_url);
 
   // Initializes |storage_partition_config_| with a value appropriate for
   // |browser_context|.
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc
index d1b5f3c..16b0a2c5 100644
--- a/content/browser/site_instance_impl.cc
+++ b/content/browser/site_instance_impl.cc
@@ -138,15 +138,8 @@
   DCHECK(url_info.is_sandboxed ||
          url_info.unique_sandbox_id == UrlInfo::kInvalidUniqueSandboxId);
   CHECK(!is_guest || url_info.storage_partition_config.has_value());
-
-  if (is_guest && !SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled()) {
-    // Guests without site isolation support need to use a SiteInfo with a
-    // special site URL and process lock URL computed in CreateForGuest().
-    return CreateForGuest(browser_context,
-                          url_info.storage_partition_config.value());
-  }
-
   DCHECK(browser_context);
+
   // This will create a new SiteInstance and BrowsingInstance.
   scoped_refptr<BrowsingInstance> instance(
       new BrowsingInstance(browser_context,
@@ -170,28 +163,24 @@
     bool is_fenced) {
   DCHECK(!url_info.url.SchemeIs(kChromeErrorScheme));
   DCHECK(url_info.storage_partition_config.has_value());
-  scoped_refptr<SiteInstanceImpl> site_instance;
 
-  if (is_guest && !SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled()) {
-    site_instance = CreateForGuest(browser_context,
-                                   url_info.storage_partition_config.value());
-  } else {
-    // This will create a new SiteInstance and BrowsingInstance.
-    // TODO(https://crbug.com/1221127): Verify that having different common
-    // COOP origins does not hinder the ability of a ServiceWorker to share its
-    // page's process.
-    scoped_refptr<BrowsingInstance> instance(new BrowsingInstance(
-        browser_context,
-        url_info.web_exposed_isolation_info.value_or(
-            WebExposedIsolationInfo::CreateNonIsolated()),
-        is_guest, is_fenced, /*coop_related_group=*/nullptr,
-        url_info.common_coop_origin));
+  // This will create a new SiteInstance and BrowsingInstance.
+  // TODO(https://crbug.com/1221127): Verify that having different common COOP
+  // origins does not hinder the ability of a ServiceWorker to share its page's
+  // process.
+  scoped_refptr<BrowsingInstance> instance(
+      new BrowsingInstance(browser_context,
+                           url_info.web_exposed_isolation_info.value_or(
+                               WebExposedIsolationInfo::CreateNonIsolated()),
+                           is_guest, is_fenced, /*coop_related_group=*/nullptr,
+                           url_info.common_coop_origin));
 
-    // We do NOT want to allow the default site instance here because workers
-    // need to be kept separate from other sites.
-    site_instance = instance->GetSiteInstanceForURL(
-        url_info, /* allow_default_instance */ false);
-  }
+  // We do NOT want to allow the default site instance here because workers
+  // need to be kept separate from other sites.
+  scoped_refptr<SiteInstanceImpl> site_instance =
+      instance->GetSiteInstanceForURL(url_info,
+                                      /* allow_default_instance */ false);
+
   DCHECK(!site_instance->GetSiteInfo().is_error_page());
   DCHECK_EQ(site_instance->IsGuest(), is_guest);
   site_instance->is_for_service_worker_ = true;
@@ -267,7 +256,6 @@
     // code path and will need to also set is_fenced for the SiteInfo created
     // below.
     DCHECK(!should_isolate_fenced_frames);
-    DCHECK(SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled());
     site_instance->SetSite(SiteInfo::CreateForGuest(
         browser_context, embedder_site_instance->GetStoragePartitionConfig()));
   }
@@ -640,13 +628,6 @@
     const UrlInfo& url_info,
     bool is_related,
     bool disregard_web_exposed_isolation_info) {
-  if (IsGuest() && !SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled()) {
-    // Guests without site isolation support currently must stay in the same
-    // SiteInstance no matter what the information in |url_info| so we return
-    // the current SiteInfo.
-    return site_info_;
-  }
-
   if (is_related) {
     return browsing_instance_->GetSiteInfoForURL(
         url_info, /* allow_default_instance */ true);
@@ -694,12 +675,6 @@
 
 scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::GetRelatedSiteInstanceImpl(
     const UrlInfo& url_info) {
-  if (IsGuest() && !SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled()) {
-    // Without site isolation in guests, there should only be one guest
-    // SiteInstance per BrowsingInstance.
-    return this;
-  }
-
   return browsing_instance_->GetSiteInstanceForURL(
       url_info, /* allow_default_instance */ true);
 }
@@ -1320,11 +1295,6 @@
             site_info_.storage_partition_config());
 
   if (site_info_.ShouldLockProcessToSite(GetIsolationContext())) {
-    // Sanity check that this won't try to assign an origin lock to a
-    // non-site-isolated <webview> process, which can't be locked.
-    if (!SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled())
-      CHECK(!process->IsForGuestsOnly());
-
     ProcessLock lock_to_set = ProcessLock::FromSiteInfo(GetSiteInfo());
     if (!process_lock.is_locked_to_site()) {
       // TODO(nick): When all sites are isolated, this operation provides
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc
index c32e3827..2bca07f 100644
--- a/content/browser/site_instance_impl_unittest.cc
+++ b/content/browser/site_instance_impl_unittest.cc
@@ -1805,17 +1805,12 @@
   }
 
   // Verify that a SiteInstance created with CreateForGuest() is considered
-  // a <webview> guest.  Without site isolation for guests, its site URL
-  // should reflect the guest's StoragePartition configuration.
+  // a <webview> guest and has the correct StoragePartition.
   const StoragePartitionConfig kGuestConfig = StoragePartitionConfig::Create(
       context(), "appid", "partition_name", /*in_memory=*/false);
-  const GURL kGuestSiteUrl(std::string(kGuestScheme) +
-                           "://appid/persist?partition_name#nofallback");
   auto instance2 = SiteInstanceImpl::CreateForGuest(context(), kGuestConfig);
   EXPECT_TRUE(instance2->IsGuest());
   EXPECT_EQ(instance2->GetStoragePartitionConfig(), kGuestConfig);
-  if (!SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled())
-    EXPECT_EQ(kGuestSiteUrl, instance2->GetSiteURL());
 }
 
 // TODO(https://crbug.com/1377466): Test is flaky for android builders.
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc
index ab7e9a6..39461b474 100644
--- a/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -162,7 +162,8 @@
   // TODO(oysteine): Retry when time_until_allowed has elapsed.
   if (config_impl && delegate_ &&
       !delegate_->IsAllowedToBeginBackgroundScenario(
-          *config_impl.get(), requires_anonymized_data)) {
+          config_impl->scenario_name(), requires_anonymized_data,
+          config_impl->has_crash_scenario())) {
     return false;
   }
 
@@ -364,7 +365,7 @@
   return !delegate_ ||
          (active_scenario_ &&
           delegate_->IsAllowedToEndBackgroundScenario(
-              *active_scenario_->GetConfig(),
+              active_scenario_->GetConfig()->scenario_name(),
               active_scenario_->GetConfig()->requires_anonymized_data(),
               is_crash_scenario));
 }
diff --git a/content/browser/tracing/startup_tracing_browsertest.cc b/content/browser/tracing/startup_tracing_browsertest.cc
index eebb529..f28ac17 100644
--- a/content/browser/tracing/startup_tracing_browsertest.cc
+++ b/content/browser/tracing/startup_tracing_browsertest.cc
@@ -322,7 +322,8 @@
             OutputLocation::kDirectoryWithDefaultBasename,
             OutputLocation::kDirectoryWithBasenameUpdatedBeforeStop)));
 
-IN_PROC_BROWSER_TEST_P(StartupTracingTest, TestEnableTracing) {
+// TODO(1428814): Re-enable this test.
+IN_PROC_BROWSER_TEST_P(StartupTracingTest, DISABLED_TestEnableTracing) {
   EXPECT_TRUE(NavigateToURL(shell(), GetTestUrl("", "title1.html")));
 
   if (GetOutputLocation() ==
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 9c13a7db..b41d1cf 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4078,14 +4078,10 @@
   scoped_refptr<SiteInstance> site_instance;
   if (params.opener_suppressed) {
     if (is_guest) {
-      // For site-isolated guests, noopener windows can be created in a new
-      // BrowsingInstance as long as they preserve the guest's StoragePartition.
-      // For non-isolated guests, we preserve the legacy behavior of keeping the
-      // new window in the old SiteInstance and BrowsingInstance.
-      site_instance = SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled()
-                          ? SiteInstance::CreateForGuest(GetBrowserContext(),
-                                                         partition_config)
-                          : source_site_instance;
+      // For guests, noopener windows can be created in a new BrowsingInstance
+      // as long as they preserve the guest's StoragePartition.
+      site_instance =
+          SiteInstance::CreateForGuest(GetBrowserContext(), partition_config);
     } else {
       site_instance = SiteInstance::Create(GetBrowserContext());
     }
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 6980739..ef2b993 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -22,6 +22,7 @@
 #include "base/functional/function_ref.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/safe_ref.h"
 #include "base/observer_list.h"
 #include "base/process/kill.h"
@@ -1915,7 +1916,9 @@
   // The view of the RVHD. Usually this is our WebContentsView implementation,
   // but if an embedder uses a different WebContentsView, they'll need to
   // provide this.
-  RenderViewHostDelegateView* render_view_host_delegate_view_;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION RenderViewHostDelegateView* render_view_host_delegate_view_;
 
   // Tracks CreatedWindow objects that have not been shown yet. They are
   // identified by the process ID and routing ID passed to CreateNewWindow.
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 82aa910..1f60956 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/path_service.h"
 #include "base/rand_util.h"
 #include "base/ranges/algorithm.h"
@@ -4422,7 +4423,9 @@
 
   static const struct {
     device::CoseAlgorithmIdentifier algo;
-    const EVP_MD* digest;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #global-scope
+    RAW_PTR_EXCLUSION const EVP_MD* digest;
   } kTests[] = {
       {device::CoseAlgorithmIdentifier::kEs256, EVP_sha256()},
       {device::CoseAlgorithmIdentifier::kRs256, EVP_sha256()},
diff --git a/content/browser/webauth/client_data_json.cc b/content/browser/webauth/client_data_json.cc
index 37e2d48..199ff866 100644
--- a/content/browser/webauth/client_data_json.cc
+++ b/content/browser/webauth/client_data_json.cc
@@ -112,13 +112,6 @@
     ret.append(R"("rpId":)");
     ret.append(ToJSONString(params.payment_rp));
 
-    // TODO(crbug.com/1356224): Remove legacy 'rp' parameter.
-    if (!base::FeatureList::IsEnabled(
-            features::kSecurePaymentConfirmationRemoveRpField)) {
-      ret.append(R"(,"rp":)");
-      ret.append(ToJSONString(params.payment_rp));
-    }
-
     ret.append(R"(,"topOrigin":)");
     ret.append(ToJSONString(params.payment_top_origin));
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java b/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java
index 5b0fd33..3db444b 100644
--- a/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java
+++ b/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java
@@ -97,6 +97,12 @@
                 Uri.parse(topLevelOrigin.getSpec())));
     }
 
+    private void onDataDeletionCompleted(int requestId) {
+        if (mNativePtr != 0) {
+            AttributionOsLevelManagerJni.get().onDataDeletionCompleted(mNativePtr, requestId);
+        }
+    }
+
     /**
      * Deletes attribution data with native, see `deleteRegistrationsAsync()`:
      * https://developer.android.com/reference/androidx/privacysandbox/ads/adservices/java/measurement/MeasurementManagerFutures.
@@ -105,16 +111,12 @@
     private void deleteRegistrations(int requestId, long startMs, long endMs, GURL[] origins,
             String[] domains, int deletionMode, int matchBehavior) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
-            if (mNativePtr != 0) {
-                AttributionOsLevelManagerJni.get().onDataDeletionCompleted(mNativePtr, requestId);
-            }
+            onDataDeletionCompleted(requestId);
             return;
         }
         MeasurementManagerFutures mm = getManager();
         if (mm == null) {
-            if (mNativePtr != 0) {
-                AttributionOsLevelManagerJni.get().onDataDeletionCompleted(mNativePtr, requestId);
-            }
+            onDataDeletionCompleted(requestId);
             return;
         }
         ArrayList<Uri> originUris = new ArrayList<Uri>(origins.length);
@@ -127,15 +129,21 @@
             domainUris.add(Uri.parse(domain));
         }
 
-        // TODO(johnidel): Wait for the returned ListenableFuture to finish before
-        // indicating deletion is complete.
-        mm.deleteRegistrationsAsync(
+        ListenableFuture<?> future = mm.deleteRegistrationsAsync(
                 new DeletionRequest(deletionMode, matchBehavior, Instant.ofEpochMilli(startMs),
                         Instant.ofEpochMilli(endMs), originUris, domainUris));
 
-        if (mNativePtr != 0) {
-            AttributionOsLevelManagerJni.get().onDataDeletionCompleted(mNativePtr, requestId);
-        }
+        Futures.addCallback(future, new FutureCallback<Object>() {
+            @Override
+            public void onSuccess(Object result) {
+                onDataDeletionCompleted(requestId);
+            }
+            @Override
+            public void onFailure(Throwable thrown) {
+                Log.w(TAG, "Failed to delete measurement API data", thrown);
+                onDataDeletionCompleted(requestId);
+            }
+        }, ContextUtils.getApplicationContext().getMainExecutor());
     }
 
     /**
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/GestureDetectorResetTest.java b/content/public/android/javatests/src/org/chromium/content/browser/GestureDetectorResetTest.java
index b80c529..95483e9 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/GestureDetectorResetTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/GestureDetectorResetTest.java
@@ -16,6 +16,7 @@
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.CriteriaNotSatisfiedException;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -98,6 +99,7 @@
     @Test
     @LargeTest
     @Feature({"Browser"})
+    @DisabledTest(message = "https://crbug.com/1233309")
     public void testSeparateClicksAreRegisteredOnReload()
             throws InterruptedException, Exception, Throwable {
         // Load the test page.
diff --git a/content/public/app/content_main.h b/content/public/app/content_main.h
index 16e8c65..26fad7e 100644
--- a/content/public/app/content_main.h
+++ b/content/public/app/content_main.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include "base/functional/callback.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 
@@ -41,7 +42,9 @@
   ContentMainParams(ContentMainParams&&);
   ContentMainParams& operator=(ContentMainParams&&);
 
-  ContentMainDelegate* delegate;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION ContentMainDelegate* delegate;
 
 #if BUILDFLAG(IS_WIN)
   HINSTANCE instance = nullptr;
@@ -51,7 +54,9 @@
   sandbox::SandboxInterfaceInfo* sandbox_info = nullptr;
 #elif !BUILDFLAG(IS_ANDROID)
   int argc = 0;
-  const char** argv = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION const char** argv = nullptr;
 #endif
 
   // Used by BrowserTestBase. If set, BrowserMainLoop runs this task instead of
diff --git a/content/public/browser/browser_or_resource_context.h b/content/public/browser/browser_or_resource_context.h
index a767058e..b451074 100644
--- a/content/public/browser/browser_or_resource_context.h
+++ b/content/public/browser/browser_or_resource_context.h
@@ -9,6 +9,7 @@
 #include <type_traits>
 
 #include "base/check_op.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace content {
@@ -79,8 +80,12 @@
 
  private:
   union Union {
-    BrowserContext* browser_context_;
-    ResourceContext* resource_context_;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #union
+    RAW_PTR_EXCLUSION BrowserContext* browser_context_;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #union
+    RAW_PTR_EXCLUSION ResourceContext* resource_context_;
   } union_;
 
   enum Flavour {
diff --git a/content/public/browser/site_isolation_policy.cc b/content/public/browser/site_isolation_policy.cc
index f8a447c..b8bb564 100644
--- a/content/public/browser/site_isolation_policy.cc
+++ b/content/public/browser/site_isolation_policy.cc
@@ -254,11 +254,6 @@
 }
 
 // static
-bool SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled() {
-  return base::FeatureList::IsEnabled(features::kSiteIsolationForGuests);
-}
-
-// static
 std::string SiteIsolationPolicy::GetIsolatedOriginsFromCommandLine() {
   std::string cmdline_arg =
       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
diff --git a/content/public/browser/site_isolation_policy.h b/content/public/browser/site_isolation_policy.h
index 2c788a8..3aebf17 100644
--- a/content/public/browser/site_isolation_policy.h
+++ b/content/public/browser/site_isolation_policy.h
@@ -76,9 +76,6 @@
   // persisted across restarts.
   static bool ShouldPersistIsolatedCOOPSites();
 
-  // Returns true when site isolation is turned on for <webview> guests.
-  static bool IsSiteIsolationForGuestsEnabled();
-
   // Applies isolated origins from all available sources, including the
   // command-line switch, field trials, enterprise policy, and the embedder.
   // See also AreIsolatedOriginsEnabled. These origins apply globally to the
diff --git a/content/public/browser/tracing_delegate.cc b/content/public/browser/tracing_delegate.cc
index 5465e05..366a6ab2 100644
--- a/content/public/browser/tracing_delegate.cc
+++ b/content/public/browser/tracing_delegate.cc
@@ -10,13 +10,14 @@
 namespace content {
 
 bool TracingDelegate::IsAllowedToBeginBackgroundScenario(
-    const BackgroundTracingConfig& config,
-    bool requires_anonymized_data) {
+    const std::string& scenario_name,
+    bool requires_anonymized_data,
+    bool is_crash_scenario) {
   return false;
 }
 
 bool TracingDelegate::IsAllowedToEndBackgroundScenario(
-    const content::BackgroundTracingConfig& config,
+    const std::string& scenario_name,
     bool requires_anonymized_data,
     bool is_crash_scenario) {
   return false;
diff --git a/content/public/browser/tracing_delegate.h b/content/public/browser/tracing_delegate.h
index f59dff9..b7562201 100644
--- a/content/public/browser/tracing_delegate.h
+++ b/content/public/browser/tracing_delegate.h
@@ -11,7 +11,6 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
-class BackgroundTracingConfig;
 
 // This can be implemented by the embedder to provide functionality for the
 // about://tracing WebUI.
@@ -21,11 +20,12 @@
 
   // This can be used to veto a particular background tracing scenario.
   virtual bool IsAllowedToBeginBackgroundScenario(
-      const BackgroundTracingConfig& config,
-      bool requires_anonymized_data);
+      const std::string& scenario_name,
+      bool requires_anonymized_data,
+      bool is_crash_scenario);
 
   virtual bool IsAllowedToEndBackgroundScenario(
-      const content::BackgroundTracingConfig& config,
+      const std::string& scenario_name,
       bool requires_anonymized_data,
       bool is_crash_scenario);
 
diff --git a/content/public/browser/web_ui_message_handler.h b/content/public/browser/web_ui_message_handler.h
index 5cbfe46..3594039 100644
--- a/content/public/browser/web_ui_message_handler.h
+++ b/content/public/browser/web_ui_message_handler.h
@@ -9,6 +9,7 @@
 
 #include "base/check.h"
 #include "base/gtest_prod_util.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "content/common/content_export.h"
@@ -130,8 +131,9 @@
 
   // True if the page is for JavaScript calls from this handler.
   bool javascript_allowed_ = false;
-
-  WebUI* web_ui_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #constexpr-ctor-field-initializer
+  RAW_PTR_EXCLUSION WebUI* web_ui_ = nullptr;
 };
 
 }  // namespace content
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 59f3f477..65949dd 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -1092,13 +1092,6 @@
              "SecurePaymentConfirmationDebug",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Remove the 'rp' field from the output SPC
-// CollectedClientAdditionalPaymentData dictionary. See
-// https://crbug.com/1356224 .
-BASE_FEATURE(kSecurePaymentConfirmationRemoveRpField,
-             "SecurePaymentConfirmationRemoveRpField",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Make sendBeacon throw for a Blob with a non simple type.
 BASE_FEATURE(kSendBeaconThrowForBlobWithNonSimpleType,
              "SendBeaconThrowForBlobWithNonSimpleType",
@@ -1211,11 +1204,6 @@
         &kSiteIsolationForCrossOriginOpenerPolicy, "expiration_timeout",
         base::Days(7)};
 
-// This feature turns on site isolation support in <webview> guests.
-BASE_FEATURE(kSiteIsolationForGuests,
-             "SiteIsolationForGuests",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // When enabled, OOPIFs will not try to reuse compatible processes from
 // unrelated tabs.
 BASE_FEATURE(kDisableProcessReuse,
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index f22a8ad..1b0756b 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -203,7 +203,6 @@
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kRunVideoCaptureServiceInBrowserProcess);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kSecurePaymentConfirmation);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kSecurePaymentConfirmationDebug);
-CONTENT_EXPORT BASE_DECLARE_FEATURE(kSecurePaymentConfirmationRemoveRpField);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kSendBeaconThrowForBlobWithNonSimpleType);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kServiceWorkerPaymentApps);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kSharedArrayBuffer);
@@ -219,7 +218,6 @@
     kSiteIsolationForCrossOriginOpenerPolicyMaxSitesParam;
 CONTENT_EXPORT extern const base::FeatureParam<base::TimeDelta>
     kSiteIsolationForCrossOriginOpenerPolicyExpirationTimeoutParam;
-CONTENT_EXPORT BASE_DECLARE_FEATURE(kSiteIsolationForGuests);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kDisableProcessReuse);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kSkipEarlyCommitPendingForCrashedFrame);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kServiceWorkerBypassFetchHandler);
diff --git a/content/public/common/content_switch_dependent_feature_overrides.cc b/content/public/common/content_switch_dependent_feature_overrides.cc
index 7cf2b5b..9757e12 100644
--- a/content/public/common/content_switch_dependent_feature_overrides.cc
+++ b/content/public/common/content_switch_dependent_feature_overrides.cc
@@ -172,6 +172,9 @@
      std::cref(blink::features::kConversionMeasurement),
      base::FeatureList::OVERRIDE_ENABLE_FEATURE},
     {switches::kEnablePrivacySandboxAdsApis,
+     std::cref(blink::features::kAttributionReportingCrossAppWeb),
+     base::FeatureList::OVERRIDE_ENABLE_FEATURE},
+    {switches::kEnablePrivacySandboxAdsApis,
      std::cref(blink::features::kFencedFrames),
      base::FeatureList::OVERRIDE_ENABLE_FEATURE},
     {switches::kEnablePrivacySandboxAdsApis,
diff --git a/content/public/common/main_function_params.h b/content/public/common/main_function_params.h
index 72aa747..6a22f3f 100644
--- a/content/public/common/main_function_params.h
+++ b/content/public/common/main_function_params.h
@@ -9,6 +9,7 @@
 
 #include "base/command_line.h"
 #include "base/functional/callback.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 
@@ -42,7 +43,9 @@
   MainFunctionParams(MainFunctionParams&&);
   MainFunctionParams& operator=(MainFunctionParams&&);
 
-  const base::CommandLine* command_line;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION const base::CommandLine* command_line;
 
 #if BUILDFLAG(IS_WIN)
   sandbox::SandboxInterfaceInfo* sandbox_info = nullptr;
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index e710fba..f18ce124 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -538,7 +538,9 @@
   RenderFrameHost* render_frame_host() const { return render_frame_host_; }
 
  private:
-  RenderFrameHost* render_frame_host_;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION RenderFrameHost* render_frame_host_;
 };
 
 RenderFrameHost* ConvertToRenderFrameHost(RenderFrameHost* render_view_host);
diff --git a/content/shell/browser/shell_devtools_manager_delegate.cc b/content/shell/browser/shell_devtools_manager_delegate.cc
index ee719fa..5219f35 100644
--- a/content/shell/browser/shell_devtools_manager_delegate.cc
+++ b/content/shell/browser/shell_devtools_manager_delegate.cc
@@ -143,8 +143,18 @@
       DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
     }
   }
+  // By default listen to incoming DevTools connections on localhost.
+  std::string address_str = net::IPAddress::IPv4Localhost().ToString();
+  if (command_line.HasSwitch(switches::kRemoteDebuggingAddress)) {
+    net::IPAddress address;
+    address_str =
+        command_line.GetSwitchValueASCII(switches::kRemoteDebuggingAddress);
+    if (!address.AssignFromIPLiteral(address_str)) {
+      DLOG(WARNING) << "Invalid devtools server address: " << address_str;
+    }
+  }
   return std::unique_ptr<content::DevToolsSocketFactory>(
-      new TCPServerSocketFactory("127.0.0.1", port));
+      new TCPServerSocketFactory(address_str, port));
 #endif
 }
 
diff --git a/content/shell/common/shell_switches.cc b/content/shell/common/shell_switches.cc
index b565320..33081752 100644
--- a/content/shell/common/shell_switches.cc
+++ b/content/shell/common/shell_switches.cc
@@ -39,6 +39,12 @@
 // comma-separated list of origins.
 const char kIsolatedContextOrigins[] = "isolated-context-origins";
 
+// Use the given address instead of the default loopback for accepting remote
+// debugging connections. Note that the remote debugging protocol does not
+// perform any authentication, so exposing it too widely can be a security
+// risk.
+const char kRemoteDebuggingAddress[] = "remote-debugging-address";
+
 // Runs Content Shell in web test mode, injecting test-only behaviour for
 // blink web tests.
 const char kRunWebTests[] = "run-web-tests";
diff --git a/content/shell/common/shell_switches.h b/content/shell/common/shell_switches.h
index 6be9e9f..687bea3d 100644
--- a/content/shell/common/shell_switches.h
+++ b/content/shell/common/shell_switches.h
@@ -17,6 +17,7 @@
 extern const char kContentShellHideToolbar[];
 extern const char kContentShellDevToolsTabTarget[];
 extern const char kIsolatedContextOrigins[];
+extern const char kRemoteDebuggingAddress[];
 extern const char kRunWebTests[];
 
 // Helper that returns true if kRunWebTests is present in the command line,
diff --git a/content/test/content_unittests_bundle_data.filelist b/content/test/content_unittests_bundle_data.filelist
index f458bff..58e57d0 100644
--- a/content/test/content_unittests_bundle_data.filelist
+++ b/content/test/content_unittests_bundle_data.filelist
@@ -405,6 +405,8 @@
 data/fenced_frames/ad_with_fenced_frame_private_aggregation_reporting.html.mock-http-headers
 data/fenced_frames/ad_with_fenced_frame_reporting.html
 data/fenced_frames/ad_with_fenced_frame_reporting.html.mock-http-headers
+data/fenced_frames/attribution_reporting_disallowed.html
+data/fenced_frames/attribution_reporting_disallowed.html.mock-http-headers
 data/fenced_frames/basic.html
 data/fenced_frames/basic.html.mock-http-headers
 data/fenced_frames/basic_fenced_frame_src.html
diff --git a/content/test/data/accessibility/html/bounds-fixed-scrolling.html b/content/test/data/accessibility/html/bounds-fixed-scrolling.html
index bf8a10b..40197f0 100644
--- a/content/test/data/accessibility/html/bounds-fixed-scrolling.html
+++ b/content/test/data/accessibility/html/bounds-fixed-scrolling.html
@@ -1,6 +1,7 @@
 <!--
 @BLINK-ALLOW:location=(8, 70)
 @BLINK-WAIT-FOR:done
+@BLINK-WAIT-FOR:location=(8, 70)
 -->
 <!DOCTYPE html>
 <html>
diff --git a/content/test/data/accessibility/html/popover-hint-expected-blink.txt b/content/test/data/accessibility/html/popover-hint-expected-blink.txt
new file mode 100644
index 0000000..2f65e62
--- /dev/null
+++ b/content/test/data/accessibility/html/popover-hint-expected-blink.txt
@@ -0,0 +1,37 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer
+++++++genericContainer ignored invisible
+++++++++staticText ignored invisible name='<newline>  Test popover!<newline>'
+++++++button name=' Test popover! '
+++++++genericContainer ignored invisible
+++++++++genericContainer ignored invisible
+++++++++++staticText ignored invisible name='<newline>    Test popover with image!<newline>    '
+++++++++++image ignored invisible
+++++++button name=' Test popover with image! test 123'
+++++++genericContainer ignored invisible
+++++++++staticText ignored invisible name='<newline>  Test popover with rich content like a datatable.<newline>  '
+++++++++layoutTable ignored invisible
+++++++++++genericContainer ignored invisible
+++++++++++++layoutTableRow ignored invisible
+++++++++++++++layoutTableCell ignored invisible
+++++++++++++++++staticText ignored invisible name='1'
+++++++++++++++layoutTableCell ignored invisible
+++++++++++++++++staticText ignored invisible name='2'
+++++++++++++layoutTableRow ignored invisible
+++++++++++++++layoutTableCell ignored invisible
+++++++++++++++++staticText ignored invisible name='3'
+++++++++++++++layoutTableCell ignored invisible
+++++++++++++++++staticText ignored invisible name='4'
+++++++button description='Test popover with rich content like a datatable. 1 2 3 4' descriptionFrom=popoverAttribute
+++++++genericContainer ignored invisible
+++++++++staticText ignored invisible name='<newline>  Test popover with a textinput!<newline>  '
+++++++++genericContainer ignored invisible
+++++++++++genericContainer ignored invisible
+++++++++++++textField ignored invisible
+++++++++++++++genericContainer ignored invisible
+++++++++++++++++staticText ignored invisible name='test'
+++++++button description='Test popover with a textinput! test' descriptionFrom=popoverAttribute
+++++++genericContainer ignored invisible
+++++++++staticText ignored invisible name='<newline>  Test popover with title in button to test description.<newline>'
+++++++button description='Test popover with title in button to test description.' name='the title' descriptionFrom=popoverAttribute
diff --git a/content/test/data/accessibility/html/popover-hint.html b/content/test/data/accessibility/html/popover-hint.html
new file mode 100644
index 0000000..e042738
--- /dev/null
+++ b/content/test/data/accessibility/html/popover-hint.html
@@ -0,0 +1,55 @@
+<!--
+@MAC-ALLOW:AXExpanded
+@WIN-ALLOW:details-roles*
+@WIN-ALLOW:EXPANDED*
+@WIN-ALLOW:HASPOPUP*
+@WIN-ALLOW:haspopup*
+@BLINK-ALLOW:haspopup*
+@BLINK-ALLOW:expanded*
+@AURALINUX-ALLOW:details-roles*
+@AURALINUX-ALLOW:expanded*
+@AURALINUX-ALLOW:haspopup:*
+-->
+<div popover="hint" id="popover1">
+  Test popover!
+</div>
+<button popovertarget="popover1"></button>
+
+<div popover="hint" id="popover2">
+  <div>
+    Test popover with image!
+    <img title="test 123">
+  </div>
+</div>
+<button popovertarget="popover2"></button>
+
+<div popover="hint" id="popover3">
+  Test popover with rich content like a datatable.
+  <table>
+    <tr>
+      <td>1</td>
+      <td>2</td>
+    </tr>
+    <tr>
+      <td>3</td>
+      <td>4</td>
+    </tr>
+  </table>
+</div>
+<button popovertarget="popover3"></button>
+
+<div popover="hint" id="popover4">
+  Test popover with a textinput!
+  <div>
+    <span>
+      <input type="text" value="test">
+    </span>
+  </div>
+</div>
+<button popovertarget="popover4"></button>
+
+
+<div popover="hint" id="popover5">
+  Test popover with title in button to test description.
+</div>
+<button title="the title" popovertarget="popover5"></button>
diff --git a/content/test/data/fenced_frames/attribution_reporting_disallowed.html b/content/test/data/fenced_frames/attribution_reporting_disallowed.html
new file mode 100644
index 0000000..2526072
--- /dev/null
+++ b/content/test/data/fenced_frames/attribution_reporting_disallowed.html
@@ -0,0 +1,4 @@
+<html>
+<head></head>
+<body>This page has no title.</body>
+</html>
diff --git a/content/test/data/fenced_frames/attribution_reporting_disallowed.html.mock-http-headers b/content/test/data/fenced_frames/attribution_reporting_disallowed.html.mock-http-headers
new file mode 100644
index 0000000..e00ab3a
--- /dev/null
+++ b/content/test/data/fenced_frames/attribution_reporting_disallowed.html.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Supports-Loading-Mode: fenced-frame
+Permissions-Policy: attribution-reporting=()
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
index ba8bc67..7fa5196 100644
--- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -207,8 +207,6 @@
 
 crbug.com/1417340 [ android android-sm-a235m ] TraceTest_WebGLGreenTriangle_AA_Alpha [ RetryOnFailure ]
 
-# Flakily times out on kevin.
-crbug.com/1426207 [ chromeos chromeos-board-kevin no-passthrough ] TraceTest_Video_* [ Failure ]
 
 #######################################################################
 # Automated Entries After This Point - Do Not Manually Add Below Here #
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 6dc949c..9c716f3 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
@@ -744,6 +744,134 @@
 crbug.com/1223542 [ chromeos chromeos-board-amd64-generic ] deqp/functional/gles3/framebufferblit/rect_03.html [ Failure ]
 crbug.com/1223542 [ chromeos chromeos-board-amd64-generic ] deqp/functional/gles3/framebufferblit/rect_04.html [ Failure ]
 
+crbug.com/1211588 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/transformfeedback/* [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin ] WebglExtension_EXT_texture_compression_bptc [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin ] WebglExtension_EXT_texture_compression_rgtc [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin ] WebglExtension_EXT_texture_filter_anisotropic [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin ] WebglExtension_EXT_texture_norm16 [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin ] WebglExtension_OES_texture_float_linear [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin ] WebglExtension_OVR_multiview2 [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin ] WebglExtension_WEBGL_compressed_texture_pvrtc [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin ] WebglExtension_WEBGL_compressed_texture_s3tc [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin ] WebglExtension_WEBGL_compressed_texture_s3tc_srgb [ Failure ]
+crbug.com/1218162 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/uniformbuffers/instance_array_basic_type.html [ Failure ]
+crbug.com/1218162 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/uniformbuffers/random.html [ Failure ]
+crbug.com/1218162 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/uniformbuffers/single_basic_array.html [ Failure ]
+crbug.com/1218162 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/uniformbuffers/single_basic_type.html [ Failure ]
+crbug.com/1218169 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/fragmentoutput/array.float.html [ Failure ]
+crbug.com/1218169 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/fragmentoutput/basic.float.html [ Failure ]
+crbug.com/1218509 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/fbomultisample.2_samples.html [ RetryOnFailure ]
+crbug.com/1218509 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/fbomultisample.4_samples.html [ RetryOnFailure ]
+crbug.com/1218509 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/fbomultisample.8_samples.html [ Failure ]
+crbug.com/1218512 [ chromeos chromeos-board-kevin ] deqp/functional/gles3/shadertexturefunction/texturelodoffset.html [ Failure ]
+crbug.com/1218516 [ chromeos chromeos-board-kevin ] deqp/data/gles3/shaders/arrays.html [ Failure ]
+crbug.com/1218607 [ chromeos chromeos-board-kevin ] conformance2/reading/read-pixels-pack-parameters.html [ Failure ]
+crbug.com/1218612 [ chromeos chromeos-board-kevin ] conformance2/glsl3/array-as-return-value.html [ Failure ]
+crbug.com/1218612 [ chromeos chromeos-board-kevin ] conformance2/glsl3/matrix-row-major.html [ Failure ]
+crbug.com/1218612 [ chromeos chromeos-board-kevin ] conformance2/glsl3/tricky-loop-conditions.html [ Failure ]
+crbug.com/1218612 [ chromeos chromeos-board-kevin ] conformance2/glsl3/uninitialized-local-global-variables.html [ Failure ]
+crbug.com/1218615 [ chromeos chromeos-board-kevin ] conformance2/extensions/ext-color-buffer-float.html [ Failure ]
+crbug.com/1219024 [ chromeos chromeos-board-kevin ] conformance/glsl/bugs/constant-precision-qualifier.html [ Failure ]
+crbug.com/1219024 [ chromeos chromeos-board-kevin ] conformance/misc/shader-precision-format.html [ Failure ]
+crbug.com/1219024 [ chromeos chromeos-board-kevin ] conformance/rendering/blending.html [ Failure ]
+crbug.com/1219057 [ chromeos chromeos-board-kevin ] conformance2/buffers/uniform-buffers.html [ Failure ]
+
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_points.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/interpolation_centroid.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/interpolation_flat.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/interpolation_smooth.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/point_size.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/position.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_lines.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/random_separate_lines.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ Failure ]
+crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ Failure ]
+crbug.com/1285109 [ chromeos chromeos-board-kevin passthrough ] conformance/canvas/render-after-resize-test.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/context/context-hidden-alpha.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/ogles/GL/array/array_001_to_006.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/ogles/GL/functions/functions_033_to_040.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/ogles/GL/refract/refract_001_to_006.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/textures/misc/copy-tex-image-2d-formats.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/renderbuffers/renderbuffer-initialization.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/renderbuffers/stencil-renderbuffer-initialization.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/rendering/rasterizer-discard-and-implicit-clear.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-float.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/textures/video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2d_03.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/fbocolorbuffer/tex3d_00.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/framebufferblit/conversion_26.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/textureshadow/2d_array_nearest_always.html [ Failure ]
+crbug.com/1285111 [ chromeos chromeos-board-kevin passthrough ] conformance/textures/misc/copy-tex-image-and-sub-image-2d.html [ Failure ]
+crbug.com/1285112 [ chromeos chromeos-board-kevin passthrough ] conformance2/rendering/blitframebuffer-multisampled-readbuffer.html [ Failure ]
+crbug.com/1285114 [ chromeos chromeos-board-kevin passthrough ] conformance2/transform_feedback/transform_feedback.html [ Failure ]
+crbug.com/1286099 [ chromeos chromeos-board-kevin passthrough ] conformance2/rendering/blitframebuffer-r11f-g11f-b10f.html [ Failure ]
+crbug.com/1374291 [ chromeos chromeos-board-kevin passthrough ] conformance2/textures/video/tex-3d-rgba8-rgba-unsigned_byte.html [ Failure ]
+
+crbug.com/1213198 [ chromeos chromeos-board-kevin no-passthrough ] WebglExtension_WEBGL_draw_instanced_base_vertex_base_instance [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin no-passthrough ] WebglExtension_WEBGL_multi_draw_instanced_base_vertex_base_instance [ Failure ]
+crbug.com/1213198 [ chromeos chromeos-board-kevin no-passthrough ] conformance/extensions/ext-float-blend.html [ Failure ]
+crbug.com/1215695 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2d_00.html [ Failure ]
+crbug.com/1215695 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2darray_00.html [ Failure ]
+crbug.com/1215695 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2darray_01.html [ Failure ]
+crbug.com/1215695 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fbocolorbuffer/tex3d_00.html [ Failure ]
+crbug.com/1215695 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fbocolorbuffer/texcube_00.html [ Failure ]
+crbug.com/1215695 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fbocolorbuffer/texcube_01.html [ Failure ]
+crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/recreate_color_01.html [ Failure ]
+crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/recreate_color_04.html [ Failure ]
+crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/recreate_color_05.html [ Failure ]
+crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/recreate_color_06.html [ Failure ]
+crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/resize_00.html [ Failure ]
+crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/resize_01.html [ Failure ]
+crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/resize_02.html [ Failure ]
+crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/resize_03.html [ Failure ]
+crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/shared_depth_stencil.html [ Failure ]
+crbug.com/1218157 [ chromeos chromeos-board-kevin no-passthrough ] conformance/offscreencanvas/context-lost-restored.html [ Failure ]
+crbug.com/1218157 [ chromeos chromeos-board-kevin no-passthrough ] conformance/offscreencanvas/context-lost-restored-worker.html [ Failure ]
+crbug.com/1218607 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/reading/read-pixels-from-fbo-test.html [ Failure ]
+crbug.com/1219024 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/rendering/framebuffer-render-to-layer.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/canvas/webgl-to-2d-canvas.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/context/context-attribute-preserve-drawing-buffer.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/context/context-creation-and-destruction.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/ogles/GL/atan/atan_001_to_008.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/ogles/GL/functions/functions_073_to_080.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/ogles/GL/struct/struct_049_to_056.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/ogles/GL/swizzlers/swizzlers_009_to_016.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/video/tex-2d-alpha-alpha-unsigned_byte.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/webgl_canvas/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/rendering/clear-func-buffer-type-match.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/image_bitmap_from_video/tex-2d-r32f-red-float.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-half_float.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/image_bitmap_from_video/tex-2d-srgb8-rgb-unsigned_byte.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-r16f-red-half_float.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-rg32f-rg-float.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-rgb16f-rgb-half_float.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-rgb32f-rgb-float.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-rgba16f-rgba-half_float.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-3d-rgba32f-rgba-float.html [ Failure ]
+
+crbug.com/1328444 [ chromeos chromeos-board-kevin ] conformance/context/context-size-change.html [ Failure ]
+crbug.com/1328444 [ chromeos chromeos-board-kevin ] conformance/rendering/color-mask-preserved-during-implicit-clears.html [ Failure ]
+crbug.com/1328444 [ chromeos chromeos-board-kevin ] conformance/state/gl-enable-enum-test.html [ Failure ]
+crbug.com/1337803 [ chromeos chromeos-board-kevin ] conformance2/misc/expando-loss-2.html [ Failure ]
+crbug.com/1328444 [ chromeos chromeos-board-kevin ] conformance2/rendering/blitframebuffer-resolve-to-back-buffer.html [ Failure ]
+crbug.com/1328444 [ chromeos chromeos-board-kevin ] conformance2/textures/misc/tex-input-validation.html [ Failure ]
+crbug.com/1373277 [ chromeos chromeos-board-kevin ] conformance2/textures/video/tex-3d-srgb8-rgb-unsigned_byte.html [ Failure ]
 
 crbug.com/1232106 [ chromeos chromeos-board-amd64-generic no-passthrough ] conformance/extensions/webgl-compressed-texture-astc.html [ Failure ]
 crbug.com/1232118 [ angle-opengles chromeos chromeos-board-amd64-generic passthrough ] conformance/uniforms/uniform-samplers-test.html [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 9d6b907..8852e95 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -335,8 +335,6 @@
 crbug.com/1426916 [ chromeos chromeos-board-amd64-generic no-passthrough ] conformance/extensions/webgl-compressed-texture-astc.html [ Slow ]
 crbug.com/1426916 [ chromeos chromeos-board-amd64-generic no-passthrough ] conformance/reading/read-pixels-test.html [ Slow ]
 crbug.com/1426916 [ chromeos chromeos-board-amd64-generic no-passthrough ] conformance/textures/misc/tex-image-and-sub-image-2d-with-array-buffer-view.html [ Slow ]
-crbug.com/1427243 [ fuchsia fuchsia-board-astro ] conformance/glsl/bugs/complex-glsl-does-not-crash.html [ Slow ]
-crbug.com/1427243 [ fuchsia fuchsia-board-sherlock ] conformance/glsl/bugs/complex-glsl-does-not-crash.html [ Slow ]
 
 ###################
 # Failures/Flakes #
@@ -402,6 +400,10 @@
 # Anti-aliasing disabled on Fuchsia
 [ fuchsia ] conformance/context/context-attributes-alpha-depth-stencil-antialias.html [ Failure ]
 
+# Slow enough that Slow expectations are not currently sufficient.
+crbug.com/1427243 [ fuchsia fuchsia-board-astro ] conformance/glsl/bugs/complex-glsl-does-not-crash.html [ Failure ]
+crbug.com/1427243 [ fuchsia fuchsia-board-sherlock ] conformance/glsl/bugs/complex-glsl-does-not-crash.html [ Failure ]
+
 ####################
 # Win failures     #
 ####################
@@ -624,6 +626,29 @@
 crbug.com/1426793 [ android android-sm-a135m ] conformance/glsl/misc/shader-uniform-packing-restrictions.html [ Slow ]
 crbug.com/1426793 [ android android-sm-a135m ] conformance/textures/misc/tex-image-and-sub-image-2d-with-array-buffer-view.html [ Slow ]
 
+# Much slower (6x or worse) with the validating decoder than the passthrough
+# decoder. We list out all the tests so as to avoid a conflict with the wildcard
+# Slow expectation.
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-00.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-01.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-02.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-03.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-04.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-05.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-06.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-07.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-08.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-09.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-10.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-11.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-12.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-13.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-14.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-15.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-16.html [ Failure ]
+crbug.com/1426593 [ android android-sm-a135m no-passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-17.html [ Failure ]
+
+
 ############
 # ChromeOS #
 ############
@@ -633,7 +658,7 @@
 # TODO(crbug.com/1276153) uncomment after fix for updated part of test applies
 # crbug.com/957807 [ chromeos ] conformance/context/context-attributes-alpha-depth-stencil-antialias.html [ Failure ]
 
-crbug.com/957807 [ angle-opengles chromeos passthrough ] conformance/uniforms/uniform-samplers-test.html [ Failure ]
+crbug.com/957807 [ chromeos ] conformance/uniforms/uniform-samplers-test.html [ Failure ]
 
 # finder:disable-unused Reported by Intel but not currently testable in Chromium
 crbug.com/1237319 [ chromeos chromeos-board-eve passthrough intel ] conformance/textures/misc/texture-size-limit.html [ Failure ]
@@ -647,6 +672,28 @@
 crbug.com/angleproject/5038 [ chromeos no-passthrough ] conformance/extensions/ext-color-buffer-half-float.html [ Failure ]
 
 ## Arm-based issues. ##
+crbug.com/957807 [ chromeos chromeos-board-kevin ] conformance/rendering/clipping-wide-points.html [ Failure ]
+crbug.com/957807 [ chromeos chromeos-board-kevin ] deqp/data/gles2/shaders/conversions* [ Failure ]
+crbug.com/957807 [ chromeos chromeos-board-kevin ] deqp/data/gles2/shaders/swizzles* [ Failure ]
+
+# There is a crash, likely in this test, causing the root partition to become
+# read-only.
+crbug.com/1043953 [ chromeos chromeos-board-kevin ] conformance/textures/misc/texture-size-limit.html [ RetryOnFailure ]
+
+crbug.com/1080400 [ chromeos chromeos-board-kevin ] WebglExtension_EXT_color_buffer_half_float [ Failure ]
+crbug.com/1080356 [ chromeos chromeos-board-kevin ] WebglExtension_EXT_frag_depth [ Failure ]
+crbug.com/1080375 [ chromeos chromeos-board-kevin ] WebglExtension_OES_texture_float [ Failure ]
+crbug.com/1080402 [ chromeos chromeos-board-kevin ] WebglExtension_OES_texture_float_linear [ Failure ]
+crbug.com/1080403 [ chromeos chromeos-board-kevin ] WebglExtension_OES_texture_half_float [ Failure ]
+crbug.com/1080404 [ chromeos chromeos-board-kevin ] WebglExtension_OES_texture_half_float_linear [ Failure ]
+crbug.com/1080407 [ chromeos chromeos-board-kevin ] WebglExtension_WEBGL_color_buffer_float [ Failure ]
+crbug.com/1080379 [ chromeos chromeos-board-kevin ] conformance/glsl/bugs/constant-precision-qualifier.html [ Failure ]
+crbug.com/1080380 [ chromeos chromeos-board-kevin ] conformance/offscreencanvas/context-lost-restored-worker.html [ Failure ]
+crbug.com/1080380 [ chromeos chromeos-board-kevin ] conformance/offscreencanvas/context-lost-restored.html [ Failure ]
+crbug.com/1108368 [ chromeos chromeos-board-kevin ] conformance/misc/shader-precision-format.html [ Failure ]
+crbug.com/1357064 [ chromeos chromeos-board-kevin no-passthrough ] conformance/rendering/blending.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin no-passthrough ] conformance/ogles/GL/default/default_001_to_001.html [ Failure ]
+crbug.com/1374285 [ chromeos chromeos-board-kevin no-passthrough ] conformance/ogles/GL/mix/mix_001_to_006.html [ Failure ]
 
 ## VM Issues ##
 
diff --git a/content/test/portal/portal_activated_observer.h b/content/test/portal/portal_activated_observer.h
index 8f9a5cb..1f32d0a 100644
--- a/content/test/portal/portal_activated_observer.h
+++ b/content/test/portal/portal_activated_observer.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_TEST_PORTAL_PORTAL_ACTIVATED_OBSERVER_H_
 #define CONTENT_TEST_PORTAL_PORTAL_ACTIVATED_OBSERVER_H_
 
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/weak_ptr.h"
 #include "content/test/portal/portal_interceptor_for_testing.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -53,7 +54,9 @@
   const base::WeakPtr<PortalInterceptorForTesting> interceptor_;
   bool has_activated_ = false;
   absl::optional<blink::mojom::PortalActivateResult> result_;
-  base::RunLoop* run_loop_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of, #union
+  RAW_PTR_EXCLUSION base::RunLoop* run_loop_ = nullptr;
 };
 
 }  // namespace content
diff --git a/device/bluetooth/floss/bluetooth_local_gatt_characteristic_floss.cc b/device/bluetooth/floss/bluetooth_local_gatt_characteristic_floss.cc
index 820800b..ba38b171 100644
--- a/device/bluetooth/floss/bluetooth_local_gatt_characteristic_floss.cc
+++ b/device/bluetooth/floss/bluetooth_local_gatt_characteristic_floss.cc
@@ -12,6 +12,7 @@
 #include "device/bluetooth/floss/bluetooth_adapter_floss.h"
 #include "device/bluetooth/floss/bluetooth_gatt_service_floss.h"
 #include "device/bluetooth/floss/bluetooth_local_gatt_service_floss.h"
+#include "device/bluetooth/floss/floss_dbus_manager.h"
 
 namespace floss {
 
@@ -25,7 +26,8 @@
   auto* characteristic = new BluetoothLocalGattCharacteristicFloss(
       uuid, properties, permissions, service);
   auto weak_ptr = characteristic->weak_ptr_factory_.GetWeakPtr();
-  service->AddCharacteristic(base::WrapUnique(characteristic));
+  weak_ptr->index_ =
+      service->AddCharacteristic(base::WrapUnique(characteristic));
   return weak_ptr;
 }
 
@@ -34,37 +36,35 @@
     Properties properties,
     Permissions permissions,
     BluetoothLocalGattServiceFloss* service)
-    : service_(raw_ref<BluetoothLocalGattServiceFloss>::from_ptr(service)) {
-  characteristic_.uuid = uuid;
-  characteristic_.properties = properties;
-  characteristic_.permissions = permissions;
-  // TODO: Redesign after the GATT server registration wiring is finished.
-  // Temporarily use a random number to prefill the instance_id, as the
-  // application may want to access the object before GATT service registration
-  // when an instance_id is provided by the daemon through DBUS callback.
-  characteristic_.instance_id = static_cast<int32_t>(base::RandUint64());
-}
+    : uuid_(uuid),
+      properties_(properties),
+      permissions_(permissions),
+      service_(raw_ref<BluetoothLocalGattServiceFloss>::from_ptr(service)),
+      client_instance_id_(service_->NewInstanceId()) {}
 
 BluetoothLocalGattCharacteristicFloss::
-    ~BluetoothLocalGattCharacteristicFloss() = default;
+    ~BluetoothLocalGattCharacteristicFloss() {
+  service_->RemoveServerObserverForHandle(floss_instance_id_);
+}
 
 std::string BluetoothLocalGattCharacteristicFloss::GetIdentifier() const {
-  return base::StringPrintf("%s/%d", service_->GetIdentifier().c_str(),
-                            characteristic_.instance_id);
+  return base::StringPrintf("%s-%s/%04x",
+                            service_->GetAdapter()->GetAddress().c_str(),
+                            GetUUID().value().c_str(), client_instance_id_);
 }
 
 device::BluetoothUUID BluetoothLocalGattCharacteristicFloss::GetUUID() const {
-  return characteristic_.uuid;
+  return uuid_;
 }
 
 device::BluetoothGattCharacteristic::Properties
 BluetoothLocalGattCharacteristicFloss::GetProperties() const {
-  return characteristic_.properties;
+  return properties_;
 }
 
 device::BluetoothGattCharacteristic::Permissions
 BluetoothLocalGattCharacteristicFloss::GetPermissions() const {
-  return characteristic_.permissions;
+  return permissions_;
 }
 
 device::BluetoothLocalGattCharacteristic::NotificationStatus
@@ -72,10 +72,10 @@
     const device::BluetoothDevice* device,
     const std::vector<uint8_t>& new_value,
     bool indicate) {
-  if (indicate && !(characteristic_.properties & PROPERTY_INDICATE)) {
+  if (indicate && !(properties_ & PROPERTY_INDICATE)) {
     return INDICATE_PROPERTY_NOT_SET;
   }
-  if (!indicate && !(characteristic_.properties & PROPERTY_NOTIFY)) {
+  if (!indicate && !(properties_ & PROPERTY_NOTIFY)) {
     return NOTIFY_PROPERTY_NOT_SET;
   }
   return service_->GetAdapter()->SendValueChanged(this, new_value)
@@ -88,9 +88,50 @@
   return &*service_;
 }
 
-void BluetoothLocalGattCharacteristicFloss::AddDescriptor(
+GattCharacteristic
+BluetoothLocalGattCharacteristicFloss::ToGattCharacteristic() {
+  GattCharacteristic characteristic;
+  characteristic.uuid = uuid_;
+  characteristic.properties = properties_;
+  characteristic.permissions = permissions_;
+  for (auto& descriptor : descriptors_) {
+    characteristic.descriptors.push_back(descriptor->ToGattDescriptor());
+  }
+  return characteristic;
+}
+
+void BluetoothLocalGattCharacteristicFloss::ResolveInstanceId(
+    const GattService& service) {
+  DCHECK(service.characteristics[index_].uuid == GetUUID());
+  floss_instance_id_ = service.characteristics[index_].instance_id;
+  service_->AddServerObserverForHandle(floss_instance_id_, this);
+}
+
+void BluetoothLocalGattCharacteristicFloss::GattServerCharacteristicReadRequest(
+    std::string address,
+    int32_t request_id,
+    int32_t offset,
+    bool is_long,
+    int32_t handle) {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothLocalGattCharacteristicFloss::
+    GattServerCharacteristicWriteRequest(std::string address,
+                                         int32_t request_id,
+                                         int32_t offset,
+                                         int32_t length,
+                                         bool is_prepared_write,
+                                         bool needs_response,
+                                         int32_t handle,
+                                         std::vector<uint8_t> value) {
+  NOTIMPLEMENTED();
+}
+
+int32_t BluetoothLocalGattCharacteristicFloss::AddDescriptor(
     std::unique_ptr<BluetoothLocalGattDescriptorFloss> descriptor) {
   descriptors_.push_back(std::move(descriptor));
+  return descriptors_.size() - 1;
 }
 
 const std::vector<std::unique_ptr<BluetoothLocalGattDescriptorFloss>>&
diff --git a/device/bluetooth/floss/bluetooth_local_gatt_characteristic_floss.h b/device/bluetooth/floss/bluetooth_local_gatt_characteristic_floss.h
index 60c019c..008d4423 100644
--- a/device/bluetooth/floss/bluetooth_local_gatt_characteristic_floss.h
+++ b/device/bluetooth/floss/bluetooth_local_gatt_characteristic_floss.h
@@ -13,6 +13,7 @@
 #include "device/bluetooth/bluetooth_local_gatt_characteristic.h"
 #include "device/bluetooth/floss/bluetooth_local_gatt_descriptor_floss.h"
 #include "device/bluetooth/floss/bluetooth_local_gatt_service_floss.h"
+#include "device/bluetooth/floss/floss_gatt_manager_client.h"
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
 
 namespace floss {
@@ -23,7 +24,8 @@
 // BluetoothLocalGattCharacteristic for local GATT characteristics for
 // platforms that use Floss.
 class DEVICE_BLUETOOTH_EXPORT BluetoothLocalGattCharacteristicFloss
-    : public device::BluetoothLocalGattCharacteristic {
+    : public device::BluetoothLocalGattCharacteristic,
+      public FlossGattServerObserver {
  public:
   static base::WeakPtr<BluetoothLocalGattCharacteristicFloss> Create(
       const device::BluetoothUUID& uuid,
@@ -50,10 +52,29 @@
                                         bool indicate) override;
   device::BluetoothLocalGattService* GetService() const override;
 
+  // floss::FlossGattServerObserver overrides.
+  void GattServerCharacteristicReadRequest(std::string address,
+                                           int32_t request_id,
+                                           int32_t offset,
+                                           bool is_long,
+                                           int32_t handle) override;
+  void GattServerCharacteristicWriteRequest(
+      std::string address,
+      int32_t request_id,
+      int32_t offset,
+      int32_t length,
+      bool is_prepared_write,
+      bool needs_response,
+      int32_t handle,
+      std::vector<uint8_t> value) override;
+
+  void ResolveInstanceId(const GattService& service);
   const std::vector<std::unique_ptr<BluetoothLocalGattDescriptorFloss>>&
   GetDescriptors() const;
 
  private:
+  friend class BluetoothAdapterFloss;
+  friend class BluetoothLocalGattServiceFloss;
   friend class BluetoothLocalGattDescriptorFloss;
 
   BluetoothLocalGattCharacteristicFloss(
@@ -62,16 +83,33 @@
       Permissions permissions,
       BluetoothLocalGattServiceFloss* service);
 
-  // Adds a descriptor to this characteristic.
-  void AddDescriptor(
+  // Convert this characteristic to GattCharacteristic struct.
+  GattCharacteristic ToGattCharacteristic();
+
+  // Adds a descriptor to this characteristic. Returns the index of the
+  // descriptor.
+  int32_t AddDescriptor(
       std::unique_ptr<BluetoothLocalGattDescriptorFloss> descriptor);
 
-  // Characteristic represented by this class.
-  GattCharacteristic characteristic_;
+  // UUID of this characteristic.
+  device::BluetoothUUID uuid_;
+
+  // Properties of this characteristic.
+  Properties properties_;
+
+  // Permissions of this characteristic.
+  Permissions permissions_;
 
   // Service that contains this characteristic.
   raw_ref<BluetoothLocalGattServiceFloss> service_;
 
+  // Client and Floss-assigned instance ids.
+  int32_t client_instance_id_;
+  int32_t floss_instance_id_;
+
+  // Index of this characteristic within the containing service.
+  int32_t index_;
+
   // Descriptors contained by this characteristic.
   std::vector<std::unique_ptr<BluetoothLocalGattDescriptorFloss>> descriptors_;
 
diff --git a/device/bluetooth/floss/bluetooth_local_gatt_descriptor_floss.cc b/device/bluetooth/floss/bluetooth_local_gatt_descriptor_floss.cc
index f74e64d1a..1b257944 100644
--- a/device/bluetooth/floss/bluetooth_local_gatt_descriptor_floss.cc
+++ b/device/bluetooth/floss/bluetooth_local_gatt_descriptor_floss.cc
@@ -8,6 +8,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/rand_util.h"
 #include "base/strings/stringprintf.h"
+#include "device/bluetooth/floss/floss_dbus_manager.h"
 
 namespace floss {
 
@@ -20,7 +21,8 @@
   auto* descriptor =
       new BluetoothLocalGattDescriptorFloss(uuid, permissions, characteristic);
   auto weak_ptr = descriptor->weak_ptr_factory_.GetWeakPtr();
-  characteristic->AddDescriptor(base::WrapUnique(descriptor));
+  weak_ptr->index_ =
+      characteristic->AddDescriptor(base::WrapUnique(descriptor));
   return weak_ptr;
 }
 
@@ -28,34 +30,30 @@
     const device::BluetoothUUID& uuid,
     device::BluetoothGattCharacteristic::Permissions permissions,
     BluetoothLocalGattCharacteristicFloss* characteristic)
-    : characteristic_(raw_ref<BluetoothLocalGattCharacteristicFloss>::from_ptr(
-          characteristic)) {
-  DCHECK(characteristic);
+    : uuid_(uuid),
+      permissions_(permissions),
+      characteristic_(raw_ref<BluetoothLocalGattCharacteristicFloss>::from_ptr(
+          characteristic)),
+      client_instance_id_(characteristic_->service_->NewInstanceId()) {}
 
-  descriptor_.uuid = uuid;
-  descriptor_.permissions = permissions;
-  // TODO: Redesign after the GATT server registration wiring is finished.
-  // Temporarily use a random number to prefill the instance_id, as the
-  // application may want to access the object before GATT service registration
-  // when an instance_id is provided by the daemon through DBUS callback.
-  descriptor_.instance_id = static_cast<int32_t>(base::RandUint64());
+BluetoothLocalGattDescriptorFloss::~BluetoothLocalGattDescriptorFloss() {
+  characteristic_->service_->RemoveServerObserverForHandle(floss_instance_id_);
 }
 
-BluetoothLocalGattDescriptorFloss::~BluetoothLocalGattDescriptorFloss() =
-    default;
-
 std::string BluetoothLocalGattDescriptorFloss::GetIdentifier() const {
-  return base::StringPrintf("%s/%d", characteristic_->GetIdentifier().c_str(),
-                            descriptor_.instance_id);
+  return base::StringPrintf(
+      "%s-%s/%04x",
+      characteristic_->service_->GetAdapter()->GetAddress().c_str(),
+      GetUUID().value().c_str(), client_instance_id_);
 }
 
 device::BluetoothUUID BluetoothLocalGattDescriptorFloss::GetUUID() const {
-  return descriptor_.uuid;
+  return uuid_;
 }
 
 device::BluetoothGattCharacteristic::Permissions
 BluetoothLocalGattDescriptorFloss::GetPermissions() const {
-  return descriptor_.permissions;
+  return permissions_;
 }
 
 device::BluetoothLocalGattCharacteristic*
@@ -63,4 +61,41 @@
   return &*characteristic_;
 }
 
+GattDescriptor BluetoothLocalGattDescriptorFloss::ToGattDescriptor() {
+  GattDescriptor descriptor;
+  descriptor.uuid = uuid_;
+  descriptor.instance_id = floss_instance_id_;
+  descriptor.permissions = permissions_;
+  return descriptor;
+}
+
+void BluetoothLocalGattDescriptorFloss::ResolveInstanceId(
+    const GattCharacteristic& characteristic) {
+  DCHECK(characteristic.descriptors[index_].uuid == GetUUID());
+  floss_instance_id_ = characteristic.descriptors[index_].instance_id;
+  characteristic_->service_->AddServerObserverForHandle(floss_instance_id_,
+                                                        this);
+}
+
+void BluetoothLocalGattDescriptorFloss::GattServerDescriptorReadRequest(
+    std::string address,
+    int32_t request_id,
+    int32_t offset,
+    bool is_long,
+    int32_t handle) {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothLocalGattDescriptorFloss::GattServerDescriptorWriteRequest(
+    std::string address,
+    int32_t request_id,
+    int32_t offset,
+    int32_t length,
+    bool is_prepared_write,
+    bool needs_response,
+    int32_t handle,
+    std::vector<uint8_t> value) {
+  NOTIMPLEMENTED();
+}
+
 }  // namespace floss
diff --git a/device/bluetooth/floss/bluetooth_local_gatt_descriptor_floss.h b/device/bluetooth/floss/bluetooth_local_gatt_descriptor_floss.h
index 5483056d..3324ac6 100644
--- a/device/bluetooth/floss/bluetooth_local_gatt_descriptor_floss.h
+++ b/device/bluetooth/floss/bluetooth_local_gatt_descriptor_floss.h
@@ -13,6 +13,7 @@
 #include "device/bluetooth/bluetooth_local_gatt_descriptor.h"
 #include "device/bluetooth/floss/bluetooth_local_gatt_characteristic_floss.h"
 #include "device/bluetooth/floss/bluetooth_remote_gatt_descriptor_floss.h"
+#include "device/bluetooth/floss/floss_gatt_manager_client.h"
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
 
 namespace floss {
@@ -23,7 +24,8 @@
 // BluetoothRemoteGattDescriptor for remote and local GATT characteristic
 // descriptors for platforms that use Floss.
 class BluetoothLocalGattDescriptorFloss
-    : public device::BluetoothLocalGattDescriptor {
+    : public device::BluetoothLocalGattDescriptor,
+      public FlossGattServerObserver {
  public:
   static base::WeakPtr<BluetoothLocalGattDescriptorFloss> Create(
       const device::BluetoothUUID& uuid,
@@ -46,18 +48,50 @@
       const override;
   device::BluetoothLocalGattCharacteristic* GetCharacteristic() const override;
 
+  // floss::FlossGattServerObserver overrides.
+  void GattServerDescriptorReadRequest(std::string address,
+                                       int32_t request_id,
+                                       int32_t offset,
+                                       bool is_long,
+                                       int32_t handle) override;
+  void GattServerDescriptorWriteRequest(std::string address,
+                                        int32_t request_id,
+                                        int32_t offset,
+                                        int32_t length,
+                                        bool is_prepared_write,
+                                        bool needs_response,
+                                        int32_t handle,
+                                        std::vector<uint8_t> value) override;
+
+  void ResolveInstanceId(const GattCharacteristic& characteristic);
+
  private:
+  friend class BluetoothLocalGattCharacteristicFloss;
+
   BluetoothLocalGattDescriptorFloss(
       const device::BluetoothUUID& uuid,
       device::BluetoothGattCharacteristic::Permissions permissions,
       BluetoothLocalGattCharacteristicFloss* characteristic);
 
-  // Descriptor represented by this class.
-  GattDescriptor descriptor_;
+  // Convert this descriptor to GattDescriptor struct.
+  GattDescriptor ToGattDescriptor();
+
+  // UUID of this descriptor.
+  device::BluetoothUUID uuid_;
+
+  // Permissions of this descriptor.
+  device::BluetoothGattCharacteristic::Permissions permissions_;
 
   // Characteristic that contains this descriptor.
   raw_ref<BluetoothLocalGattCharacteristicFloss> characteristic_;
 
+  // Client and Floss-assigned instance id.
+  int32_t client_instance_id_;
+  int32_t floss_instance_id_;
+
+  // Index of this descriptor within the containing characteristic.
+  int32_t index_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<BluetoothLocalGattDescriptorFloss> weak_ptr_factory_{
diff --git a/device/bluetooth/floss/bluetooth_local_gatt_service_floss.cc b/device/bluetooth/floss/bluetooth_local_gatt_service_floss.cc
index 5f63c0b7..2cb59eb 100644
--- a/device/bluetooth/floss/bluetooth_local_gatt_service_floss.cc
+++ b/device/bluetooth/floss/bluetooth_local_gatt_service_floss.cc
@@ -105,10 +105,19 @@
   return service == characteristics_.end() ? nullptr : service->second.get();
 }
 
-void BluetoothLocalGattServiceFloss::AddCharacteristic(
+int32_t BluetoothLocalGattServiceFloss::AddCharacteristic(
     std::unique_ptr<BluetoothLocalGattCharacteristicFloss> characteristic) {
   DCHECK(!base::Contains(characteristics_, characteristic->GetIdentifier()));
   characteristics_[characteristic->GetIdentifier()] = std::move(characteristic);
+  return characteristics_.size() - 1;
+}
+
+// static
+uint32_t BluetoothLocalGattServiceFloss::instance_id_tracker_ = 1000;
+
+// static
+uint32_t BluetoothLocalGattServiceFloss::NewInstanceId() {
+  return instance_id_tracker_++;
 }
 
 }  // namespace floss
diff --git a/device/bluetooth/floss/bluetooth_local_gatt_service_floss.h b/device/bluetooth/floss/bluetooth_local_gatt_service_floss.h
index 13fb05d..c267811 100644
--- a/device/bluetooth/floss/bluetooth_local_gatt_service_floss.h
+++ b/device/bluetooth/floss/bluetooth_local_gatt_service_floss.h
@@ -59,6 +59,7 @@
 
  private:
   friend class BluetoothLocalGattCharacteristicFloss;
+  friend class BluetoothLocalGattDescriptorFloss;
 
   BluetoothLocalGattServiceFloss(BluetoothAdapterFloss* adapter,
                                  const device::BluetoothUUID& uuid,
@@ -70,9 +71,16 @@
                            const std::string& error_name,
                            const std::string& error_message);
 
-  void AddCharacteristic(
+  int32_t AddCharacteristic(
       std::unique_ptr<BluetoothLocalGattCharacteristicFloss> characteristic);
 
+  // Function to generate a new, unique instance id for each GATT attribute.
+  static uint32_t NewInstanceId();
+
+  // A tracker to guarantee unique instance ids for newly created GATT
+  // attributes.
+  static uint32_t instance_id_tracker_;
+
   // If this service is primary.
   const bool is_primary_;
 
diff --git a/device/vr/android/xr_java_coordinator.h b/device/vr/android/xr_java_coordinator.h
index 6587e8e..1cdea3f3 100644
--- a/device/vr/android/xr_java_coordinator.h
+++ b/device/vr/android/xr_java_coordinator.h
@@ -6,6 +6,7 @@
 #define DEVICE_VR_ANDROID_XR_JAVA_COORDINATOR_H_
 
 #include "base/android/scoped_java_ref.h"
+#include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "gpu/ipc/common/surface_handle.h"
 #include "ui/display/display.h"
@@ -63,6 +64,12 @@
       SurfaceReadyCallback ready_callback,
       SurfaceTouchCallback touch_callback,
       SurfaceDestroyedCallback destroyed_callback) = 0;
+  virtual void RequestVrSession(
+      int render_process_id,
+      int render_frame_id,
+      device::SurfaceReadyCallback ready_callback,
+      device::SurfaceTouchCallback touch_callback,
+      device::SurfaceDestroyedCallback destroyed_callback) = 0;
   virtual void EndSession() = 0;
 };
 
diff --git a/docs/speed/startup/android_startup.md b/docs/speed/startup/android_startup.md
new file mode 100644
index 0000000..854b674
--- /dev/null
+++ b/docs/speed/startup/android_startup.md
@@ -0,0 +1,66 @@
+# Android Start-up Performance
+
+## Stages of Start-up
+
+Every Android component (activities, broadcast receivers, etc) can be a
+start-up entry point for Chrome. The main start-up scenarios we optimize for
+are:
+
+ * Launching from the home screen
+ * Handling a View intent
+ * Showing a Chrome Custom Tab
+
+For a home screen launch, we consider start-up to be complete once the
+Activity is rendered. For the latter two, we care both about:
+
+* The first [Navigation Commit] in the app lifetime
+* The initial [First Contentful Paint]
+
+[Navigation Commit]: https://developer.chrome.com/docs/extensions/reference/webNavigation/#event-onCommitted
+[First Contentful Paint]: https://web.dev/fcp/
+
+## UMA
+
+Here are some UMA metrics that measure start-up (UMA's UI has descriptions):
+
+* `Startup.Android.Cold.TimeToFirstVisibleContent`
+* `Startup.Android.Cold.TimeToFirstNavigationCommit.Tabbed`
+* `Browser.PaintPreview.TabbedPlayer.TimeToFirstBitmap`
+* `Startup.Android.Cold.TimeToFirstContentfulPaint.Tabbed`
+
+This one can be useful for measuring dex optimization changes:
+
+* `Startup.LoadTime.ProcessCreateToApplicationStart`
+
+For Googlers, there's more background in [this doc].
+
+[this doc]: https://docs.google.com/document/d/1ahGc_uIRk76znPGg3KopOteRLmLLo4-sfXdq4Kt4Jwk/edit#heading=h.zgb0nx9k2mr0
+
+## ChromePerf
+
+Here are some [chromeperf metrics] that measure start-up in a lab
+environment:
+
+* `ChromiumPerf/android-pixel4-perf/startup.mobile / messageloop_start_time`
+* `ChromiumPerf/android-pixel4-perf/startup.mobile / navigation_commit_time`
+* `ChromiumPerf/android-pixel4-perf/startup.mobile / first_contentful_paint_time`
+
+[chromeperf metrics]: https://chromeperf.appspot.com/report?sid=06a1fe93dd4da84479b7ee8987ed6a7668c7cef3cdf2ba1d9e3234d31c773cf8
+
+## Pinpoint
+
+When using [Pinpoint] to test start-up changes, make sure to:
+
+* Use bundles rather than APKs.
+  * For 32-bit: `--browser=android-trichrome-bundle`
+  * For 64-bit: `--browser=android-trichrome-chrome-google-64-32-bundle`
+* Compile DEX: `--compile-apk=speed`
+
+Some start-up changes can improve start-up for high-end devices but degrade
+it for low-end ones (or vice versa). It is important to test both.
+
+* Use `android-go-*` devices to test low-end.
+* Use `android-pixel6-*` to test high-end. They set
+  `is_high_end_android=true`.
+
+[Pinpoint]: https://pinpoint-dot-chromeperf.appspot.com/
diff --git a/extensions/browser/api/app_runtime/app_runtime_api.cc b/extensions/browser/api/app_runtime/app_runtime_api.cc
index 951f750..8336ea9 100644
--- a/extensions/browser/api/app_runtime/app_runtime_api.cc
+++ b/extensions/browser/api/app_runtime/app_runtime_api.cc
@@ -12,6 +12,7 @@
 
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
+#include "base/types/cxx23_to_underlying.h"
 #include "extensions/browser/entry_info.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_prefs.h"
@@ -50,8 +51,7 @@
                                  app_runtime::LaunchSource source,
                                  base::Value::Dict launch_data,
                                  BrowserContext* context) {
-  UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchSource", source,
-                            app_runtime::LaunchSource::LAUNCH_SOURCE_LAST + 1);
+  UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchSource", source);
 
   launch_data.Set("isDemoSession",
                   ExtensionsBrowserClient::Get()->IsInDemoMode());
@@ -74,39 +74,38 @@
                                                   base::Time::Now());
 }
 
-#define ASSERT_ENUM_EQUAL(Name, Name2)                                 \
-  static_assert(static_cast<int>(extensions::AppLaunchSource::Name) == \
-                    static_cast<int>(app_runtime::LAUNCH_##Name2),     \
-                "The value of extensions::" #Name                      \
+#define ASSERT_ENUM_EQUAL(Name, Name2)                                     \
+  static_assert(base::to_underlying(extensions::AppLaunchSource::Name) ==  \
+                    base::to_underlying(app_runtime::LaunchSource::Name2), \
+                "The value of extensions::" #Name                          \
                 " and app_runtime::LAUNCH_" #Name2 " should be the same");
 
 app_runtime::LaunchSource GetLaunchSourceEnum(
     extensions::AppLaunchSource source) {
-  ASSERT_ENUM_EQUAL(kSourceNone, SOURCE_NONE);
-  ASSERT_ENUM_EQUAL(kSourceUntracked, SOURCE_UNTRACKED);
-  ASSERT_ENUM_EQUAL(kSourceAppLauncher, SOURCE_APP_LAUNCHER);
-  ASSERT_ENUM_EQUAL(kSourceNewTabPage, SOURCE_NEW_TAB_PAGE);
-  ASSERT_ENUM_EQUAL(kSourceReload, SOURCE_RELOAD);
-  ASSERT_ENUM_EQUAL(kSourceRestart, SOURCE_RESTART);
-  ASSERT_ENUM_EQUAL(kSourceLoadAndLaunch, SOURCE_LOAD_AND_LAUNCH);
-  ASSERT_ENUM_EQUAL(kSourceCommandLine, SOURCE_COMMAND_LINE);
-  ASSERT_ENUM_EQUAL(kSourceFileHandler, SOURCE_FILE_HANDLER);
-  ASSERT_ENUM_EQUAL(kSourceUrlHandler, SOURCE_URL_HANDLER);
-  ASSERT_ENUM_EQUAL(kSourceSystemTray, SOURCE_SYSTEM_TRAY);
-  ASSERT_ENUM_EQUAL(kSourceAboutPage, SOURCE_ABOUT_PAGE);
-  ASSERT_ENUM_EQUAL(kSourceKeyboard, SOURCE_KEYBOARD);
-  ASSERT_ENUM_EQUAL(kSourceExtensionsPage, SOURCE_EXTENSIONS_PAGE);
-  ASSERT_ENUM_EQUAL(kSourceManagementApi, SOURCE_MANAGEMENT_API);
-  ASSERT_ENUM_EQUAL(kSourceEphemeralAppDeprecated, SOURCE_EPHEMERAL_APP);
-  ASSERT_ENUM_EQUAL(kSourceBackground, SOURCE_BACKGROUND);
-  ASSERT_ENUM_EQUAL(kSourceKiosk, SOURCE_KIOSK);
-  ASSERT_ENUM_EQUAL(kSourceChromeInternal, SOURCE_CHROME_INTERNAL);
-  ASSERT_ENUM_EQUAL(kSourceTest, SOURCE_TEST);
-  ASSERT_ENUM_EQUAL(kSourceInstalledNotification,
-                    SOURCE_INSTALLED_NOTIFICATION);
-  ASSERT_ENUM_EQUAL(kSourceContextMenu, SOURCE_CONTEXT_MENU);
-  ASSERT_ENUM_EQUAL(kSourceArc, SOURCE_ARC);
-  ASSERT_ENUM_EQUAL(kSourceIntentUrl, SOURCE_INTENT_URL);
+  ASSERT_ENUM_EQUAL(kSourceNone, kNone);
+  ASSERT_ENUM_EQUAL(kSourceUntracked, kUntracked);
+  ASSERT_ENUM_EQUAL(kSourceAppLauncher, kAppLauncher);
+  ASSERT_ENUM_EQUAL(kSourceNewTabPage, kNewTabPage);
+  ASSERT_ENUM_EQUAL(kSourceReload, kReload);
+  ASSERT_ENUM_EQUAL(kSourceRestart, kRestart);
+  ASSERT_ENUM_EQUAL(kSourceLoadAndLaunch, kLoadAndLaunch);
+  ASSERT_ENUM_EQUAL(kSourceCommandLine, kCommandLine);
+  ASSERT_ENUM_EQUAL(kSourceFileHandler, kFileHandler);
+  ASSERT_ENUM_EQUAL(kSourceUrlHandler, kUrlHandler);
+  ASSERT_ENUM_EQUAL(kSourceSystemTray, kSystemTray);
+  ASSERT_ENUM_EQUAL(kSourceAboutPage, kAboutPage);
+  ASSERT_ENUM_EQUAL(kSourceKeyboard, kKeyboard);
+  ASSERT_ENUM_EQUAL(kSourceExtensionsPage, kExtensionsPage);
+  ASSERT_ENUM_EQUAL(kSourceManagementApi, kManagementApi);
+  ASSERT_ENUM_EQUAL(kSourceEphemeralAppDeprecated, kEphemeralApp);
+  ASSERT_ENUM_EQUAL(kSourceBackground, kBackground);
+  ASSERT_ENUM_EQUAL(kSourceKiosk, kKiosk);
+  ASSERT_ENUM_EQUAL(kSourceChromeInternal, kChromeInternal);
+  ASSERT_ENUM_EQUAL(kSourceTest, kTest);
+  ASSERT_ENUM_EQUAL(kSourceInstalledNotification, kInstalledNotification);
+  ASSERT_ENUM_EQUAL(kSourceContextMenu, kContextMenu);
+  ASSERT_ENUM_EQUAL(kSourceArc, kArc);
+  ASSERT_ENUM_EQUAL(kSourceIntentUrl, kIntentUrl);
 
   // We don't allow extensions to launch an app specifying RunOnOSLogin,
   // ProtocolHandler or Reparenting as the source. In this case we map
@@ -120,9 +119,10 @@
   // The +3 accounts for kSourceRunOnOsLogin, kSourceProtocolHandler and
   // kSourceReparenting not having a corresponding entry in
   // app_runtime::LaunchSource.
-  static_assert(static_cast<int>(extensions::AppLaunchSource::kMaxValue) ==
-                    app_runtime::LaunchSource::LAUNCH_SOURCE_LAST + 3,
-                "");
+  static_assert(
+      base::to_underlying(extensions::AppLaunchSource::kMaxValue) ==
+          base::to_underlying(app_runtime::LaunchSource::kMaxValue) + 3,
+      "");
 
   return static_cast<app_runtime::LaunchSource>(source);
 }
@@ -220,7 +220,7 @@
     const GURL& referrer_url) {
   app_runtime::LaunchData launch_data;
   app_runtime::LaunchSource source_enum =
-      app_runtime::LAUNCH_SOURCE_URL_HANDLER;
+      app_runtime::LaunchSource::kUrlHandler;
   launch_data.id = handler_id;
   launch_data.url = url.spec();
   launch_data.referrer_url = referrer_url.spec();
diff --git a/extensions/browser/api/app_window/app_window_api.cc b/extensions/browser/api/app_window/app_window_api.cc
index f1f2b77..d064168 100644
--- a/extensions/browser/api/app_window/app_window_api.cc
+++ b/extensions/browser/api/app_window/app_window_api.cc
@@ -372,9 +372,10 @@
     }
   }
 
-  api::app_runtime::ActionType action_type = api::app_runtime::ACTION_TYPE_NONE;
+  api::app_runtime::ActionType action_type =
+      api::app_runtime::ActionType::kNone;
   if (options &&
-      options->lock_screen_action != api::app_runtime::ACTION_TYPE_NONE) {
+      options->lock_screen_action != api::app_runtime::ActionType::kNone) {
     if (source_context_type() != Feature::LOCK_SCREEN_EXTENSION_CONTEXT) {
       return RespondNow(Error(
           app_window_constants::kLockScreenActionRequiresLockScreenContext));
@@ -393,7 +394,7 @@
   create_params.creator_process_id = source_process_id();
 
   AppWindow* app_window = nullptr;
-  if (action_type == api::app_runtime::ACTION_TYPE_NONE) {
+  if (action_type == api::app_runtime::ActionType::kNone) {
     app_window =
         AppWindowClient::Get()->CreateAppWindow(browser_context(), extension());
   } else {
diff --git a/extensions/browser/api/extensions_api_client.cc b/extensions/browser/api/extensions_api_client.cc
index 8f8bb445..1661e95 100644
--- a/extensions/browser/api/extensions_api_client.cc
+++ b/extensions/browser/api/extensions_api_client.cc
@@ -136,7 +136,8 @@
 }
 
 std::unique_ptr<SupervisedUserExtensionsDelegate>
-ExtensionsAPIClient::CreateSupervisedUserExtensionsDelegate() const {
+ExtensionsAPIClient::CreateSupervisedUserExtensionsDelegate(
+    content::BrowserContext* context) const {
   return nullptr;
 }
 
diff --git a/extensions/browser/api/extensions_api_client.h b/extensions/browser/api/extensions_api_client.h
index 2bc04d06..d9bb693 100644
--- a/extensions/browser/api/extensions_api_client.h
+++ b/extensions/browser/api/extensions_api_client.h
@@ -185,7 +185,8 @@
   // Creates a delegate for calling into the SupervisedUserService from the
   // Management API.
   virtual std::unique_ptr<SupervisedUserExtensionsDelegate>
-  CreateSupervisedUserExtensionsDelegate() const;
+  CreateSupervisedUserExtensionsDelegate(
+      content::BrowserContext* browser_context) const;
 
   // Creates and returns the DisplayInfoProvider used by the
   // chrome.system.display extension API.
diff --git a/extensions/browser/api/management/management_api.cc b/extensions/browser/api/management/management_api.cc
index 581fc63e..26e5b80f 100644
--- a/extensions/browser/api/management/management_api.cc
+++ b/extensions/browser/api/management/management_api.cc
@@ -445,21 +445,21 @@
           ->Get(browser_context())
           ->GetSupervisedUserExtensionsDelegate();
   if (supervised_user_extensions_delegate &&
-      supervised_user_extensions_delegate->IsChild(browser_context()) &&
+      supervised_user_extensions_delegate->IsChild() &&
       // Don't prompt the user if the extension has unsupported requirements.
       // TODO(crbug/1071978): If OnRequirementsChecked() passes, the extension
       // will enable, bypassing parent approval.
       !HasUnsupportedRequirements(extension_id_) &&
       // Only ask for parent approval if the extension still requires approval.
       !supervised_user_extensions_delegate->IsExtensionAllowedByParent(
-          *target_extension, browser_context())) {
+          *target_extension)) {
     // Either ask for parent permission or notify the child that their parent
     // has disabled this action.
     auto extension_approval_callback = base::BindOnce(
         &ManagementSetEnabledFunction::OnExtensionApprovalDone, this);
     AddRef();  // Matched in OnExtensionApprovalDone().
     supervised_user_extensions_delegate->RequestToEnableExtensionOrShowError(
-        *target_extension, browser_context(), GetSenderWebContents(),
+        *target_extension, GetSenderWebContents(),
         std::move(extension_approval_callback));
     return RespondLater();
   }
@@ -1110,8 +1110,8 @@
     : browser_context_(context),
       delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()),
       supervised_user_extensions_delegate_(
-          ExtensionsAPIClient::Get()
-              ->CreateSupervisedUserExtensionsDelegate()) {
+          ExtensionsAPIClient::Get()->CreateSupervisedUserExtensionsDelegate(
+              browser_context_)) {
   EventRouter* event_router = EventRouter::Get(browser_context_);
   event_router->RegisterObserver(this, management::OnInstalled::kEventName);
   event_router->RegisterObserver(this, management::OnUninstalled::kEventName);
diff --git a/extensions/browser/api/messaging/message_port.h b/extensions/browser/api/messaging/message_port.h
index 70d33bc..e7fcd62 100644
--- a/extensions/browser/api/messaging/message_port.h
+++ b/extensions/browser/api/messaging/message_port.h
@@ -96,7 +96,9 @@
   // later.
   virtual void NotifyResponsePending();
 
-  bool should_have_strong_keepalive() { return should_have_strong_keepalive_; }
+  bool should_have_strong_keepalive() const {
+    return should_have_strong_keepalive_;
+  }
   void set_should_have_strong_keepalive(bool should_have_strong_keepalive) {
     should_have_strong_keepalive_ = should_have_strong_keepalive;
   }
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc
index 2a79494..3bd0346d 100644
--- a/extensions/browser/extension_function.cc
+++ b/extensions/browser/extension_function.cc
@@ -763,7 +763,6 @@
 
 ExtensionFunction::ResponseValue ExtensionFunction::CreateBadMessageResponse() {
   SetBadMessage();
-  NOTREACHED() << name() << ": bad message";
   return ResponseValue(false, PassKey());
 }
 
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 ffa0620..283a4604 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -935,13 +935,10 @@
 void WebViewGuest::FrameNameChanged(RenderFrameHost* render_frame_host,
                                     const std::string& name) {
   // WebViewGuest does not support back/forward cache or prerendering so
-  // |render_frame_host| should be either active or pending deletion. Note that
-  // the pending deletion state becomes possible with site isolation for
-  // <webview> (crbug.com/1267977).
+  // |render_frame_host| should be either active or pending deletion.
   DCHECK(render_frame_host->IsActive() ||
-         (content::SiteIsolationPolicy::IsSiteIsolationForGuestsEnabled() &&
-          render_frame_host->IsInLifecycleState(
-              RenderFrameHost::LifecycleState::kPendingDeletion)));
+         render_frame_host->IsInLifecycleState(
+             RenderFrameHost::LifecycleState::kPendingDeletion));
   if (render_frame_host->GetParentOrOuterDocument())
     return;
 
diff --git a/extensions/browser/supervised_user_extensions_delegate.h b/extensions/browser/supervised_user_extensions_delegate.h
index 4395eae..ec9e51a 100644
--- a/extensions/browser/supervised_user_extensions_delegate.h
+++ b/extensions/browser/supervised_user_extensions_delegate.h
@@ -9,7 +9,6 @@
 #include "extensions/common/extension.h"
 
 namespace content {
-class BrowserContext;
 class WebContents;
 }  // namespace content
 
@@ -34,13 +33,12 @@
 
   virtual ~SupervisedUserExtensionsDelegate() = default;
 
-  // Returns true if |context| represents a supervised child account.
-  virtual bool IsChild(content::BrowserContext* context) const = 0;
+  // Returns true if the primary account is a supervised child.
+  virtual bool IsChild() const = 0;
 
   // Returns true if the parent has already approved the |extension|.
   virtual bool IsExtensionAllowedByParent(
-      const extensions::Extension& extension,
-      content::BrowserContext* context) const = 0;
+      const extensions::Extension& extension) const = 0;
 
   // If the current user is a child, the child user has a custodian/parent, and
   // the parent has enabled the "Permissions for sites, apps and extensions"
@@ -51,7 +49,6 @@
   // fetched via a network request.
   virtual void RequestToAddExtensionOrShowError(
       const extensions::Extension& extension,
-      content::BrowserContext* browser_context,
       content::WebContents* web_contents,
       const gfx::ImageSkia& icon,
       ExtensionApprovalDoneCallback extension_approval_callback) = 0;
@@ -60,7 +57,6 @@
   // installed extensions. The icon is fetched from local resources.
   virtual void RequestToEnableExtensionOrShowError(
       const extensions::Extension& extension,
-      content::BrowserContext* browser_context,
       content::WebContents* web_contents,
       ExtensionApprovalDoneCallback extension_approval_callback) = 0;
 };
diff --git a/extensions/common/api/app_runtime.idl b/extensions/common/api/app_runtime.idl
index 33ad7b9..53b786d 100644
--- a/extensions/common/api/app_runtime.idl
+++ b/extensions/common/api/app_runtime.idl
@@ -5,6 +5,7 @@
 // Use the <code>chrome.app.runtime</code> API to manage the app lifecycle.
 // The app runtime manages app installation, controls the event page, and can
 // shut down the app at anytime.
+[modernised_enums]
 namespace app.runtime {
 
   [inline_doc] dictionary LaunchItem {
diff --git a/extensions/common/api/automation.idl b/extensions/common/api/automation.idl
index 0e1ff04..d2506b3 100644
--- a/extensions/common/api/automation.idl
+++ b/extensions/common/api/automation.idl
@@ -470,6 +470,7 @@
     caption,
     contents,
     placeholder,
+    popoverAttribute,
     relatedElement,
     title,
     value
diff --git a/extensions/common/manifest_handlers/action_handlers_handler.cc b/extensions/common/manifest_handlers/action_handlers_handler.cc
index 85f6222..63357de 100644
--- a/extensions/common/manifest_handlers/action_handlers_handler.cc
+++ b/extensions/common/manifest_handlers/action_handlers_handler.cc
@@ -75,7 +75,7 @@
     }
 
     app_runtime::ActionType action_type = app_runtime::ParseActionType(value);
-    if (action_type == app_runtime::ACTION_TYPE_NONE) {
+    if (action_type == app_runtime::ActionType::kNone) {
       *error = ErrorUtils::FormatErrorMessageUTF16(
           errors::kInvalidActionHandlersActionType, value);
       return false;
diff --git a/extensions/common/manifest_handlers/action_handlers_handler_unittest.cc b/extensions/common/manifest_handlers/action_handlers_handler_unittest.cc
index 230575fe..1ab680c6 100644
--- a/extensions/common/manifest_handlers/action_handlers_handler_unittest.cc
+++ b/extensions/common/manifest_handlers/action_handlers_handler_unittest.cc
@@ -78,61 +78,61 @@
   EXPECT_TRUE(GetActionHandlers(none.get()).empty());
 
   EXPECT_FALSE(ActionHandlersInfo::HasActionHandler(
-      none.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      none.get(), app_runtime::ActionType::kNewNote));
   EXPECT_FALSE(ActionHandlersInfo::HasLockScreenActionHandler(
-      none.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      none.get(), app_runtime::ActionType::kNewNote));
 
   scoped_refptr<Extension> new_note =
       LoadAndExpectSuccess(CreateManifest("[\"new_note\"]"));
   EXPECT_EQ(
-      std::set<app_runtime::ActionType>{app_runtime::ACTION_TYPE_NEW_NOTE},
+      std::set<app_runtime::ActionType>{app_runtime::ActionType::kNewNote},
       GetActionHandlers(new_note.get()));
   EXPECT_TRUE(GetLockScreenActionHandlers(new_note.get()).empty());
   EXPECT_TRUE(ActionHandlersInfo::HasActionHandler(
-      new_note.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      new_note.get(), app_runtime::ActionType::kNewNote));
   EXPECT_FALSE(ActionHandlersInfo::HasLockScreenActionHandler(
-      new_note.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      new_note.get(), app_runtime::ActionType::kNewNote));
 }
 
 TEST_F(ActionHandlersManifestTest, ParseDictionaryActionValues) {
   scoped_refptr<Extension> no_enabled_on_lock_screen_key =
       LoadAndExpectSuccess(CreateManifest(R"([{"action": "new_note"}])"));
   EXPECT_EQ(
-      std::set<app_runtime::ActionType>{app_runtime::ACTION_TYPE_NEW_NOTE},
+      std::set<app_runtime::ActionType>{app_runtime::ActionType::kNewNote},
       GetActionHandlers(no_enabled_on_lock_screen_key.get()));
   EXPECT_TRUE(
       GetLockScreenActionHandlers(no_enabled_on_lock_screen_key.get()).empty());
   EXPECT_TRUE(ActionHandlersInfo::HasActionHandler(
-      no_enabled_on_lock_screen_key.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      no_enabled_on_lock_screen_key.get(), app_runtime::ActionType::kNewNote));
   EXPECT_FALSE(ActionHandlersInfo::HasLockScreenActionHandler(
-      no_enabled_on_lock_screen_key.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      no_enabled_on_lock_screen_key.get(), app_runtime::ActionType::kNewNote));
 
   scoped_refptr<Extension> enabled_on_lock_screen_false =
       LoadAndExpectSuccess(CreateManifest(
           R"([{"action": "new_note", "enabled_on_lock_screen": false}])"));
   EXPECT_EQ(
-      std::set<app_runtime::ActionType>{app_runtime::ACTION_TYPE_NEW_NOTE},
+      std::set<app_runtime::ActionType>{app_runtime::ActionType::kNewNote},
       GetActionHandlers(enabled_on_lock_screen_false.get()));
   EXPECT_TRUE(
       GetLockScreenActionHandlers(enabled_on_lock_screen_false.get()).empty());
   EXPECT_TRUE(ActionHandlersInfo::HasActionHandler(
-      enabled_on_lock_screen_false.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      enabled_on_lock_screen_false.get(), app_runtime::ActionType::kNewNote));
   EXPECT_FALSE(ActionHandlersInfo::HasLockScreenActionHandler(
-      enabled_on_lock_screen_false.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      enabled_on_lock_screen_false.get(), app_runtime::ActionType::kNewNote));
 
   scoped_refptr<Extension> enabled_on_lock_screen_true =
       LoadAndExpectSuccess(CreateManifest(
           R"([{"action": "new_note", "enabled_on_lock_screen": true}])"));
   EXPECT_EQ(
-      std::set<app_runtime::ActionType>{app_runtime::ACTION_TYPE_NEW_NOTE},
+      std::set<app_runtime::ActionType>{app_runtime::ActionType::kNewNote},
       GetActionHandlers(enabled_on_lock_screen_true.get()));
   EXPECT_EQ(
-      std::set<app_runtime::ActionType>{app_runtime::ACTION_TYPE_NEW_NOTE},
+      std::set<app_runtime::ActionType>{app_runtime::ActionType::kNewNote},
       GetLockScreenActionHandlers(enabled_on_lock_screen_true.get()));
   EXPECT_TRUE(ActionHandlersInfo::HasActionHandler(
-      enabled_on_lock_screen_true.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      enabled_on_lock_screen_true.get(), app_runtime::ActionType::kNewNote));
   EXPECT_TRUE(ActionHandlersInfo::HasLockScreenActionHandler(
-      enabled_on_lock_screen_true.get(), app_runtime::ACTION_TYPE_NEW_NOTE));
+      enabled_on_lock_screen_true.get(), app_runtime::ActionType::kNewNote));
 }
 
 TEST_F(ActionHandlersManifestTest, DuplicateHandlers) {
diff --git a/fuchsia_web/common/test/BUILD.gn b/fuchsia_web/common/test/BUILD.gn
index b39cc9c..b6aa601 100644
--- a/fuchsia_web/common/test/BUILD.gn
+++ b/fuchsia_web/common/test/BUILD.gn
@@ -13,8 +13,12 @@
     "fake_feedback_service.cc",
     "fake_feedback_service.h",
     "fit_adapter.h",
+    "frame_for_test.cc",
+    "frame_for_test.h",
     "frame_test_util.cc",
     "frame_test_util.h",
+    "test_debug_listener.cc",
+    "test_debug_listener.h",
     "test_devtools_list_fetcher.cc",
     "test_devtools_list_fetcher.h",
     "test_navigation_listener.cc",
diff --git a/fuchsia_web/webengine/test/frame_for_test.cc b/fuchsia_web/common/test/frame_for_test.cc
similarity index 97%
rename from fuchsia_web/webengine/test/frame_for_test.cc
rename to fuchsia_web/common/test/frame_for_test.cc
index b245c06..60bf0214 100644
--- a/fuchsia_web/webengine/test/frame_for_test.cc
+++ b/fuchsia_web/common/test/frame_for_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "fuchsia_web/webengine/test/frame_for_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 
 #include "base/fuchsia/fuchsia_logging.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
diff --git a/fuchsia_web/webengine/test/frame_for_test.h b/fuchsia_web/common/test/frame_for_test.h
similarity index 94%
rename from fuchsia_web/webengine/test/frame_for_test.h
rename to fuchsia_web/common/test/frame_for_test.h
index 1b9c003..1d0e1e3 100644
--- a/fuchsia_web/webengine/test/frame_for_test.h
+++ b/fuchsia_web/common/test/frame_for_test.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef FUCHSIA_WEB_WEBENGINE_TEST_FRAME_FOR_TEST_H_
-#define FUCHSIA_WEB_WEBENGINE_TEST_FRAME_FOR_TEST_H_
+#ifndef FUCHSIA_WEB_COMMON_TEST_FRAME_FOR_TEST_H_
+#define FUCHSIA_WEB_COMMON_TEST_FRAME_FOR_TEST_H_
 
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
@@ -69,4 +69,4 @@
       navigation_listener_binding_;
 };
 
-#endif  // FUCHSIA_WEB_WEBENGINE_TEST_FRAME_FOR_TEST_H_
+#endif  // FUCHSIA_WEB_COMMON_TEST_FRAME_FOR_TEST_H_
diff --git a/fuchsia_web/webengine/test_debug_listener.cc b/fuchsia_web/common/test/test_debug_listener.cc
similarity index 97%
rename from fuchsia_web/webengine/test_debug_listener.cc
rename to fuchsia_web/common/test/test_debug_listener.cc
index f089be1..f421e04 100644
--- a/fuchsia_web/webengine/test_debug_listener.cc
+++ b/fuchsia_web/common/test/test_debug_listener.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "fuchsia_web/webengine/test_debug_listener.h"
+#include "fuchsia_web/common/test/test_debug_listener.h"
 
 #include "base/auto_reset.h"
 #include "base/run_loop.h"
diff --git a/fuchsia_web/webengine/test_debug_listener.h b/fuchsia_web/common/test/test_debug_listener.h
similarity index 92%
rename from fuchsia_web/webengine/test_debug_listener.h
rename to fuchsia_web/common/test/test_debug_listener.h
index 0b84590..14f03956 100644
--- a/fuchsia_web/webengine/test_debug_listener.h
+++ b/fuchsia_web/common/test/test_debug_listener.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef FUCHSIA_WEB_WEBENGINE_TEST_DEBUG_LISTENER_H_
-#define FUCHSIA_WEB_WEBENGINE_TEST_DEBUG_LISTENER_H_
+#ifndef FUCHSIA_WEB_COMMON_TEST_TEST_DEBUG_LISTENER_H_
+#define FUCHSIA_WEB_COMMON_TEST_TEST_DEBUG_LISTENER_H_
 
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
@@ -67,4 +67,4 @@
   base::RepeatingClosure on_debug_ports_changed_;
 };
 
-#endif  // FUCHSIA_WEB_WEBENGINE_TEST_DEBUG_LISTENER_H_
+#endif  // FUCHSIA_WEB_COMMON_TEST_TEST_DEBUG_LISTENER_H_
diff --git a/fuchsia_web/runners/cast/DEPS b/fuchsia_web/runners/cast/DEPS
index 281073e2..cd87013 100644
--- a/fuchsia_web/runners/cast/DEPS
+++ b/fuchsia_web/runners/cast/DEPS
@@ -13,7 +13,6 @@
 specific_include_rules = {
   ".*_browsertest\.cc": [
     # WebEngine test helpers.
-    "+fuchsia_web/webengine/test/frame_for_test.h",
     "+fuchsia_web/webengine/test/web_engine_browser_test.h",
   ],
   "cast_runner_integration_test\.cc": [
diff --git a/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc b/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc
index f9e21fdc..1d3453bf 100644
--- a/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc
+++ b/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc
@@ -15,12 +15,12 @@
 #include "components/cast/message_port/fuchsia/message_port_fuchsia.h"
 #include "content/public/test/browser_test.h"
 #include "fuchsia_web/common/test/fit_adapter.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/runners/cast/api_bindings_client.h"
 #include "fuchsia_web/runners/cast/fake_api_bindings.h"
 #include "fuchsia_web/runners/cast/named_message_port_connector_fuchsia.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/fuchsia_web/runners/cast/named_message_port_connector_fuchsia_browsertest.cc b/fuchsia_web/runners/cast/named_message_port_connector_fuchsia_browsertest.cc
index 49afba82..a0505f0 100644
--- a/fuchsia_web/runners/cast/named_message_port_connector_fuchsia_browsertest.cc
+++ b/fuchsia_web/runners/cast/named_message_port_connector_fuchsia_browsertest.cc
@@ -12,10 +12,10 @@
 #include "components/cast/message_port/test_message_port_receiver.h"
 #include "content/public/test/browser_test.h"
 #include "fuchsia_web/common/test/fit_adapter.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/runners/cast/named_message_port_connector_fuchsia.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/fuchsia_web/webengine/BUILD.gn b/fuchsia_web/webengine/BUILD.gn
index f794ce2..a65fdf8 100644
--- a/fuchsia_web/webengine/BUILD.gn
+++ b/fuchsia_web/webengine/BUILD.gn
@@ -237,7 +237,8 @@
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.logger:fuchsia.logger_cpp",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.logger:fuchsia.logger_cpp_hlcpp_conversion",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.math:fuchsia.math_hlcpp",
-    "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.media.sessions2:fuchsia.media.sessions2_hlcpp",
+    "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.media.sessions2:fuchsia.media.sessions2_cpp",
+    "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.media.sessions2:fuchsia.media.sessions2_cpp_hlcpp_conversion",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem:fuchsia.mem_hlcpp",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.settings:fuchsia.settings_hlcpp",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.gfx:fuchsia.ui.gfx_hlcpp",
@@ -528,8 +529,6 @@
   ]
   testonly = true
   sources = [
-    "test/frame_for_test.cc",
-    "test/frame_for_test.h",
     "test/scenic_test_helper.cc",
     "test/scenic_test_helper.h",
     "test/scoped_connection_checker.h",
@@ -672,6 +671,7 @@
     "//services/network/public/mojom",
     "//testing/gmock",
     "//testing/gtest",
+    "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.media.sessions2:fuchsia.media.sessions2_cpp",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.web:fuchsia.web_hlcpp",
     "//third_party/fuchsia-sdk/sdk/pkg/fdio",
     "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
@@ -690,8 +690,6 @@
 
 test("web_engine_integration_tests") {
   sources = [
-    "test_debug_listener.cc",
-    "test_debug_listener.h",
     "web_engine_debug_integration_test.cc",
     "web_engine_integration_logging_test.cc",
     "web_engine_integration_test.cc",
diff --git a/fuchsia_web/webengine/browser/accessibility_browsertest.cc b/fuchsia_web/webengine/browser/accessibility_browsertest.cc
index 5c8e49a..d9f8148a 100644
--- a/fuchsia_web/webengine/browser/accessibility_browsertest.cc
+++ b/fuchsia_web/webengine/browser/accessibility_browsertest.cc
@@ -13,12 +13,12 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/bind.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/browser/fake_semantics_manager.h"
 #include "fuchsia_web/webengine/browser/frame_impl.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
diff --git a/fuchsia_web/webengine/browser/autoplay_browsertest.cc b/fuchsia_web/webengine/browser/autoplay_browsertest.cc
index 3aaf1ce..652d366 100644
--- a/fuchsia_web/webengine/browser/autoplay_browsertest.cc
+++ b/fuchsia_web/webengine/browser/autoplay_browsertest.cc
@@ -6,11 +6,11 @@
 
 #include "base/files/file_path.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/browser/frame_impl.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom.h"
diff --git a/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc b/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
index 679fb7c..6c41f36 100644
--- a/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
+++ b/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
@@ -13,11 +13,11 @@
 #include "components/cast_streaming/test/cast_streaming_test_sender.h"
 #include "content/public/test/browser_test.h"
 #include "fuchsia_web/common/test/fit_adapter.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/browser/frame_impl.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "media/base/media_util.h"
diff --git a/fuchsia_web/webengine/browser/client_hints_browsertest.cc b/fuchsia_web/webengine/browser/client_hints_browsertest.cc
index 133f4df7..ec407086 100644
--- a/fuchsia_web/webengine/browser/client_hints_browsertest.cc
+++ b/fuchsia_web/webengine/browser/client_hints_browsertest.cc
@@ -16,12 +16,12 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/browser/frame_impl.h"
 #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
diff --git a/fuchsia_web/webengine/browser/content_directory_browsertest.cc b/fuchsia_web/webengine/browser/content_directory_browsertest.cc
index b5bd0c8d..6c3908f5 100644
--- a/fuchsia_web/webengine/browser/content_directory_browsertest.cc
+++ b/fuchsia_web/webengine/browser/content_directory_browsertest.cc
@@ -19,11 +19,11 @@
 #include "base/threading/thread_restrictions.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/content_test_suite_base.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/content_directory_loader_factory.h"
 #include "fuchsia_web/webengine/switches.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/url_util.h"
 
diff --git a/fuchsia_web/webengine/browser/context_impl_browsertest.cc b/fuchsia_web/webengine/browser/context_impl_browsertest.cc
index 26e93b0..722810d 100644
--- a/fuchsia_web/webengine/browser/context_impl_browsertest.cc
+++ b/fuchsia_web/webengine/browser/context_impl_browsertest.cc
@@ -5,10 +5,10 @@
 #include "base/command_line.h"
 #include "base/no_destructor.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/switches.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/url_constants.h"
diff --git a/fuchsia_web/webengine/browser/explicit_sites_filter_browsertest.cc b/fuchsia_web/webengine/browser/explicit_sites_filter_browsertest.cc
index 3dd6f7a..3ec128b 100644
--- a/fuchsia_web/webengine/browser/explicit_sites_filter_browsertest.cc
+++ b/fuchsia_web/webengine/browser/explicit_sites_filter_browsertest.cc
@@ -12,13 +12,13 @@
 #include "components/safe_search_api/stub_url_checker.h"
 #include "components/safe_search_api/url_checker.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/browser/frame_impl.h"
 #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
 #include "fuchsia_web/webengine/browser/web_engine_browser_main_parts.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
diff --git a/fuchsia_web/webengine/browser/favicon_browsertest.cc b/fuchsia_web/webengine/browser/favicon_browsertest.cc
index 3c93c829..8ddaaa2 100644
--- a/fuchsia_web/webengine/browser/favicon_browsertest.cc
+++ b/fuchsia_web/webengine/browser/favicon_browsertest.cc
@@ -4,9 +4,9 @@
 
 #include "base/fuchsia/mem_buffer_util.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia_web/webengine/browser/frame_impl.cc b/fuchsia_web/webengine/browser/frame_impl.cc
index 8734846..094b1318 100644
--- a/fuchsia_web/webengine/browser/frame_impl.cc
+++ b/fuchsia_web/webengine/browser/frame_impl.cc
@@ -6,6 +6,7 @@
 
 #include <fidl/fuchsia.logger/cpp/fidl.h>
 #include <fidl/fuchsia.logger/cpp/hlcpp_conversion.h>
+#include <fidl/fuchsia.media.sessions2/cpp/hlcpp_conversion.h>
 #include <fuchsia/ui/gfx/cpp/fidl.h>
 #include <lib/fpromise/result.h>
 #include <lib/sys/cpp/component_context.h>
@@ -883,7 +884,8 @@
               perfetto::Flow::FromPointer(this));
 
   media_player_ = std::make_unique<MediaPlayerImpl>(
-      content::MediaSession::Get(web_contents_.get()), std::move(player),
+      content::MediaSession::Get(web_contents_.get()),
+      fidl::HLCPPToNatural(player),
       base::BindOnce(&FrameImpl::OnMediaPlayerDisconnect,
                      base::Unretained(this)));
 }
diff --git a/fuchsia_web/webengine/browser/frame_impl_browsertest.cc b/fuchsia_web/webengine/browser/frame_impl_browsertest.cc
index e3cbd81e..8ef15e5 100644
--- a/fuchsia_web/webengine/browser/frame_impl_browsertest.cc
+++ b/fuchsia_web/webengine/browser/frame_impl_browsertest.cc
@@ -17,13 +17,13 @@
 #include "content/public/test/test_utils.h"
 #include "fuchsia_web/common/string_util.h"
 #include "fuchsia_web/common/test/fit_adapter.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/browser/fake_semantics_manager.h"
 #include "fuchsia_web/webengine/browser/frame_impl.h"
 #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "net/test/embedded_test_server/request_handler_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia_web/webengine/browser/headless_browsertest.cc b/fuchsia_web/webengine/browser/headless_browsertest.cc
index ee18c5f..829b56a 100644
--- a/fuchsia_web/webengine/browser/headless_browsertest.cc
+++ b/fuchsia_web/webengine/browser/headless_browsertest.cc
@@ -5,10 +5,10 @@
 #include "base/auto_reset.h"
 #include "base/test/scoped_command_line.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/switches.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia_web/webengine/browser/input_browsertest.cc b/fuchsia_web/webengine/browser/input_browsertest.cc
index da670123..07da741 100644
--- a/fuchsia_web/webengine/browser/input_browsertest.cc
+++ b/fuchsia_web/webengine/browser/input_browsertest.cc
@@ -13,11 +13,11 @@
 #include "base/test/scoped_feature_list.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/features.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/scenic_test_helper.h"
 #include "fuchsia_web/webengine/test/scoped_connection_checker.h"
 #include "fuchsia_web/webengine/test/test_data.h"
diff --git a/fuchsia_web/webengine/browser/javascript_browsertest.cc b/fuchsia_web/webengine/browser/javascript_browsertest.cc
index cfde9052..63c30c9 100644
--- a/fuchsia_web/webengine/browser/javascript_browsertest.cc
+++ b/fuchsia_web/webengine/browser/javascript_browsertest.cc
@@ -4,10 +4,10 @@
 
 #include "base/fuchsia/mem_buffer_util.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 
 namespace {
 
diff --git a/fuchsia_web/webengine/browser/media_browsertest.cc b/fuchsia_web/webengine/browser/media_browsertest.cc
index a6074dfa..8bac4a8 100644
--- a/fuchsia_web/webengine/browser/media_browsertest.cc
+++ b/fuchsia_web/webengine/browser/media_browsertest.cc
@@ -11,10 +11,10 @@
 #include "base/fuchsia/test_component_context_for_process.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/features.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/fuchsia_web/webengine/browser/media_player_impl.cc b/fuchsia_web/webengine/browser/media_player_impl.cc
index 1060424..bb5cd0d 100644
--- a/fuchsia_web/webengine/browser/media_player_impl.cc
+++ b/fuchsia_web/webengine/browser/media_player_impl.cc
@@ -4,7 +4,7 @@
 
 #include "fuchsia_web/webengine/browser/media_player_impl.h"
 
-#include <fuchsia/media/cpp/fidl.h>
+#include <lib/async/default.h>
 
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/logging.h"
@@ -16,29 +16,28 @@
 
 namespace {
 
-fuchsia::media::sessions2::PlayerCapabilityFlags ActionToCapabilityFlag(
+fuchsia_media_sessions2::PlayerCapabilityFlags ActionToCapabilityFlag(
     media_session::mojom::MediaSessionAction action) {
   using MediaSessionAction = media_session::mojom::MediaSessionAction;
-  using PlayerCapabilityFlags =
-      fuchsia::media::sessions2::PlayerCapabilityFlags;
+  using PlayerCapabilityFlags = fuchsia_media_sessions2::PlayerCapabilityFlags;
   switch (action) {
     case MediaSessionAction::kEnterPictureInPicture:
     case MediaSessionAction::kExitPictureInPicture:
       return {};  // PlayerControl does not support picture-in-picture.
     case MediaSessionAction::kPlay:
-      return PlayerCapabilityFlags::PLAY;
+      return PlayerCapabilityFlags::kPlay;
     case MediaSessionAction::kPause:
-      return PlayerCapabilityFlags::PAUSE;
+      return PlayerCapabilityFlags::kPause;
     case MediaSessionAction::kPreviousTrack:
-      return PlayerCapabilityFlags::CHANGE_TO_PREV_ITEM;
+      return PlayerCapabilityFlags::kChangeToPrevItem;
     case MediaSessionAction::kNextTrack:
-      return PlayerCapabilityFlags::CHANGE_TO_NEXT_ITEM;
+      return PlayerCapabilityFlags::kChangeToNextItem;
     case MediaSessionAction::kSeekBackward:
-      return PlayerCapabilityFlags::SKIP_REVERSE;
+      return PlayerCapabilityFlags::kSkipReverse;
     case MediaSessionAction::kSeekForward:
-      return PlayerCapabilityFlags::SKIP_FORWARD;
+      return PlayerCapabilityFlags::kSkipForward;
     case MediaSessionAction::kSeekTo:
-      return PlayerCapabilityFlags::SEEK;
+      return PlayerCapabilityFlags::kSeek;
     case MediaSessionAction::kScrubTo:
       return {};  // PlayerControl does not support scrub-to.
     case MediaSessionAction::kSkipAd:
@@ -67,22 +66,22 @@
 
 void AddMetadata(base::StringPiece label,
                  base::StringPiece16 value,
-                 fuchsia::media::Metadata* metadata) {
-  fuchsia::media::Property property = {.label{label},
-                                       .value{base::UTF16ToUTF8(value)}};
-  metadata->properties.emplace_back(std::move(property));
+                 fuchsia_media::Metadata* metadata) {
+  fuchsia_media::Property property{
+      {.label{label}, .value{base::UTF16ToUTF8(value)}}};
+  metadata->properties().emplace_back(std::move(property));
 }
 
-fuchsia::media::sessions2::PlayerState SessionStateToPlayerState(
+fuchsia_media_sessions2::PlayerState SessionStateToPlayerState(
     media_session::mojom::MediaSessionInfo::SessionState state) {
   switch (state) {
     case media_session::mojom::MediaSessionInfo::SessionState::kActive:
     case media_session::mojom::MediaSessionInfo::SessionState::kDucking:
-      return fuchsia::media::sessions2::PlayerState::PLAYING;
+      return fuchsia_media_sessions2::PlayerState::kPlaying;
     case media_session::mojom::MediaSessionInfo::SessionState::kInactive:
-      return fuchsia::media::sessions2::PlayerState::IDLE;
+      return fuchsia_media_sessions2::PlayerState::kIdle;
     case media_session::mojom::MediaSessionInfo::SessionState::kSuspended:
-      return fuchsia::media::sessions2::PlayerState::PAUSED;
+      return fuchsia_media_sessions2::PlayerState::kPaused;
   };
 }
 
@@ -90,34 +89,30 @@
 
 MediaPlayerImpl::MediaPlayerImpl(
     content::MediaSession* media_session,
-    fidl::InterfaceRequest<fuchsia::media::sessions2::Player> request,
+    fidl::ServerEnd<fuchsia_media_sessions2::Player> server_end,
     base::OnceClosure on_disconnect)
     : media_session_(media_session),
       on_disconnect_(std::move(on_disconnect)),
-      binding_(this, std::move(request)),
+      binding_(async_get_default_dispatcher(),
+               std::move(server_end),
+               this,
+               fit::bind_member(this, &MediaPlayerImpl::OnBindingClosure)),
       observer_receiver_(this) {
-  binding_.set_error_handler([this](zx_status_t status) mutable {
-    ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
-        << "Player disconnected.";
-    std::move(on_disconnect_).Run();
-  });
-
   // Set default values for some fields in |pending_info_delta_|, which some
   // clients may otherwise use incorrect defaults for.
-  pending_info_delta_.set_local(true);
+  pending_info_delta_.local(true);
 }
 
 MediaPlayerImpl::~MediaPlayerImpl() = default;
 
 void MediaPlayerImpl::WatchInfoChange(
-    WatchInfoChangeCallback info_change_callback) {
+    MediaPlayerImpl::WatchInfoChangeCompleter::Sync& completer) {
   if (pending_info_change_callback_) {
-    DLOG(ERROR) << "Unexpected WatchInfoChange().";
     ReportErrorAndDisconnect(ZX_ERR_BAD_STATE);
     return;
   }
 
-  pending_info_change_callback_ = std::move(info_change_callback);
+  pending_info_change_callback_ = completer.ToAsync();
 
   if (!observer_receiver_.is_bound()) {
     // |media_session| will notify us via our MediaSessionObserver interface
@@ -129,93 +124,112 @@
   MaybeSendPlayerInfoDelta();
 }
 
-void MediaPlayerImpl::Play() {
+void MediaPlayerImpl::Play(
+    MediaPlayerImpl::PlayCompleter::Sync& ignored_completer) {
   media_session_->Resume(content::MediaSession::SuspendType::kUI);
 }
 
-void MediaPlayerImpl::Pause() {
+void MediaPlayerImpl::Pause(
+    MediaPlayerImpl::PauseCompleter::Sync& ignored_completer) {
   media_session_->Suspend(content::MediaSession::SuspendType::kUI);
 }
 
-void MediaPlayerImpl::Stop() {
+void MediaPlayerImpl::Stop(
+    MediaPlayerImpl::StopCompleter::Sync& ignored_completer) {
   media_session_->Suspend(content::MediaSession::SuspendType::kUI);
 }
 
-void MediaPlayerImpl::Seek(zx_duration_t position) {
-  media_session_->SeekTo(base::TimeDelta::FromZxDuration(position));
+void MediaPlayerImpl::Seek(
+    MediaPlayerImpl::SeekRequest& request,
+    MediaPlayerImpl::SeekCompleter::Sync& ignored_completer) {
+  media_session_->SeekTo(base::TimeDelta::FromZxDuration(request.position()));
 }
 
-void MediaPlayerImpl::SkipForward() {
+void MediaPlayerImpl::SkipForward(
+    MediaPlayerImpl::SkipForwardCompleter::Sync& ignored_completer) {
   media_session_->Seek(
       base::Seconds(media_session::mojom::kDefaultSeekTimeSeconds));
 }
 
-void MediaPlayerImpl::SkipReverse() {
+void MediaPlayerImpl::SkipReverse(
+    MediaPlayerImpl::SkipReverseCompleter::Sync& ignored_completer) {
   media_session_->Seek(
       -base::Seconds(media_session::mojom::kDefaultSeekTimeSeconds));
 }
 
-void MediaPlayerImpl::NextItem() {
+void MediaPlayerImpl::NextItem(
+    MediaPlayerImpl::NextItemCompleter::Sync& ignored_completer) {
   media_session_->NextTrack();
 }
 
-void MediaPlayerImpl::PrevItem() {
+void MediaPlayerImpl::PrevItem(
+    MediaPlayerImpl::PrevItemCompleter::Sync& ignored_completer) {
   media_session_->PreviousTrack();
 }
 
-void MediaPlayerImpl::SetPlaybackRate(float playback_rate) {
+void MediaPlayerImpl::SetPlaybackRate(
+    MediaPlayerImpl::SetPlaybackRateRequest& request,
+    MediaPlayerImpl::SetPlaybackRateCompleter::Sync& ignored_completer) {
   // content::MediaSession does not support changes to playback rate.
+  NOTIMPLEMENTED_LOG_ONCE();
 }
 
 void MediaPlayerImpl::SetRepeatMode(
-    fuchsia::media::sessions2::RepeatMode repeat_mode) {
+    MediaPlayerImpl::SetRepeatModeRequest& request,
+    MediaPlayerImpl::SetRepeatModeCompleter::Sync& ignored_completer) {
   // content::MediaSession does not provide control over repeat playback.
+  NOTIMPLEMENTED_LOG_ONCE();
 }
 
-void MediaPlayerImpl::SetShuffleMode(bool shuffle_on) {
+void MediaPlayerImpl::SetShuffleMode(
+    MediaPlayerImpl::SetShuffleModeRequest& request,
+    MediaPlayerImpl::SetShuffleModeCompleter::Sync& ignored_completer) {
   // content::MediaSession does not provide control over item playback order.
+  NOTIMPLEMENTED_LOG_ONCE();
 }
 
 void MediaPlayerImpl::BindVolumeControl(
-    fidl::InterfaceRequest<fuchsia::media::audio::VolumeControl>
-        volume_control_request) {
+    MediaPlayerImpl::BindVolumeControlRequest& request,
+    MediaPlayerImpl::BindVolumeControlCompleter::Sync& ignored_completer) {
   // content::MediaSession does not provide control over audio gain.
-  volume_control_request.Close(ZX_ERR_NOT_SUPPORTED);
+  request.volume_control_request().Close(ZX_ERR_NOT_SUPPORTED);
 }
 
 void MediaPlayerImpl::MediaSessionInfoChanged(
     media_session::mojom::MediaSessionInfoPtr info) {
-  fuchsia::media::sessions2::PlayerStatus status;
-  status.set_player_state(SessionStateToPlayerState(info->state));
-  pending_info_delta_.set_player_status(std::move(status));
+  fuchsia_media_sessions2::PlayerStatus status{{
+      .player_state = SessionStateToPlayerState(info->state),
+  }};
+  pending_info_delta_.player_status(std::move(status));
   MaybeSendPlayerInfoDelta();
 }
 
 void MediaPlayerImpl::MediaSessionMetadataChanged(
     const absl::optional<media_session::MediaMetadata>& metadata_mojo) {
-  fuchsia::media::Metadata metadata;
+  fuchsia_media::Metadata metadata;
   if (metadata_mojo) {
-    AddMetadata(fuchsia::media::METADATA_LABEL_TITLE, metadata_mojo->title,
+    AddMetadata(fuchsia_media::kMetadataLabelTitle, metadata_mojo->title,
                 &metadata);
-    AddMetadata(fuchsia::media::METADATA_LABEL_ARTIST, metadata_mojo->artist,
+    AddMetadata(fuchsia_media::kMetadataLabelArtist, metadata_mojo->artist,
                 &metadata);
-    AddMetadata(fuchsia::media::METADATA_LABEL_ALBUM, metadata_mojo->album,
+    AddMetadata(fuchsia_media::kMetadataLabelAlbum, metadata_mojo->album,
                 &metadata);
-    AddMetadata(fuchsia::media::METADATA_SOURCE_TITLE,
+    AddMetadata(fuchsia_media::kMetadataSourceTitle,
                 metadata_mojo->source_title, &metadata);
   }
-  pending_info_delta_.set_metadata(std::move(metadata));
+  pending_info_delta_.metadata(std::move(metadata));
   MaybeSendPlayerInfoDelta();
 }
 
 void MediaPlayerImpl::MediaSessionActionsChanged(
     const std::vector<media_session::mojom::MediaSessionAction>& actions) {
   // TODO(https://crbug.com/879317): Implement PROVIDE_BITMAPS.
-  fuchsia::media::sessions2::PlayerCapabilityFlags capability_flags{};
+  fuchsia_media_sessions2::PlayerCapabilityFlags capability_flags{};
   for (auto action : actions)
     capability_flags |= ActionToCapabilityFlag(action);
-  pending_info_delta_.mutable_player_capabilities()->set_flags(
-      std::move(capability_flags));
+  pending_info_delta_.player_capabilities(
+      fuchsia_media_sessions2::PlayerCapabilities{
+          {.flags = std::move(capability_flags)}});
   MaybeSendPlayerInfoDelta();
 }
 
@@ -239,11 +253,18 @@
     return;
   // std::exchange(foo, {}) returns the contents of |foo|, while ensuring that
   // |foo| is reset to the initial/empty state.
-  std::exchange(pending_info_change_callback_,
-                {})(std::exchange(pending_info_delta_, {}));
+  std::exchange(pending_info_change_callback_, absl::nullopt)
+      ->Reply(std::exchange(pending_info_delta_, {}));
+}
+
+void MediaPlayerImpl::OnBindingClosure(fidl::UnbindInfo info) {
+  ZX_LOG_IF(ERROR, info.status() != ZX_ERR_PEER_CLOSED, info.status())
+      << "Player disconnected.";
+  if (on_disconnect_) {
+    std::move(on_disconnect_).Run();
+  }
 }
 
 void MediaPlayerImpl::ReportErrorAndDisconnect(zx_status_t status) {
   binding_.Close(status);
-  std::move(on_disconnect_).Run();
 }
diff --git a/fuchsia_web/webengine/browser/media_player_impl.h b/fuchsia_web/webengine/browser/media_player_impl.h
index a93681e2..f128ee7e 100644
--- a/fuchsia_web/webengine/browser/media_player_impl.h
+++ b/fuchsia_web/webengine/browser/media_player_impl.h
@@ -5,9 +5,7 @@
 #ifndef FUCHSIA_WEB_WEBENGINE_BROWSER_MEDIA_PLAYER_IMPL_H_
 #define FUCHSIA_WEB_WEBENGINE_BROWSER_MEDIA_PLAYER_IMPL_H_
 
-#include <fuchsia/media/sessions2/cpp/fidl.h>
-#include <lib/fidl/cpp/binding.h>
-#include <lib/fidl/cpp/interface_request.h>
+#include <fidl/fuchsia.media.sessions2/cpp/fidl.h>
 #include <string>
 
 #include "base/functional/callback.h"
@@ -21,40 +19,44 @@
 }
 
 class WEB_ENGINE_EXPORT MediaPlayerImpl final
-    : public fuchsia::media::sessions2::Player,
+    : public fidl::Server<fuchsia_media_sessions2::Player>,
       public media_session::mojom::MediaSessionObserver {
  public:
   // |media_session| must out-live |this|.
   // |on_disconnect| will be invoked when |request| disconnects, and should
   // clean up |this|, and any references to it.
-  MediaPlayerImpl(
-      content::MediaSession* media_session,
-      fidl::InterfaceRequest<fuchsia::media::sessions2::Player> request,
-      base::OnceClosure on_disconnect);
+  MediaPlayerImpl(content::MediaSession* media_session,
+                  fidl::ServerEnd<fuchsia_media_sessions2::Player> server_end,
+                  base::OnceClosure on_disconnect);
   ~MediaPlayerImpl() override;
 
   MediaPlayerImpl(const MediaPlayerImpl&) = delete;
   MediaPlayerImpl& operator=(const MediaPlayerImpl&) = delete;
 
-  // fuchsia::media::sessions2::Player implementation.
-  void WatchInfoChange(WatchInfoChangeCallback info_change_callback) override;
+  // fuchsia_media_sessions2::Player implementation.
+  void WatchInfoChange(WatchInfoChangeCompleter::Sync& completer) override;
 
-  // fuchsia::media::sessions2::PlayerControl implementation.
-  void Play() override;
-  void Pause() override;
-  void Stop() override;
-  void Seek(zx_duration_t position) override;
-  void SkipForward() override;
-  void SkipReverse() override;
-  void NextItem() override;
-  void PrevItem() override;
-  void SetPlaybackRate(float playback_rate) override;
-  void SetRepeatMode(
-      fuchsia::media::sessions2::RepeatMode repeat_mode) override;
-  void SetShuffleMode(bool shuffle_on) override;
+  // fuchsia_media_sessions2::PlayerControl implementation.
+  void Play(PlayCompleter::Sync& ignored_completer) override;
+  void Pause(PauseCompleter::Sync& ignored_completer) override;
+  void Stop(StopCompleter::Sync& ignored_completer) override;
+  void Seek(SeekRequest& request,
+            SeekCompleter::Sync& ignored_completer) override;
+  void SkipForward(SkipForwardCompleter::Sync& ignored_completer) override;
+  void SkipReverse(SkipReverseCompleter::Sync& ignored_completer) override;
+  void NextItem(NextItemCompleter::Sync& ignored_completer) override;
+  void PrevItem(PrevItemCompleter::Sync& ignored_completer) override;
+  void SetPlaybackRate(
+      SetPlaybackRateRequest& request,
+      SetPlaybackRateCompleter::Sync& ignored_completer) override;
+  void SetRepeatMode(SetRepeatModeRequest& request,
+                     SetRepeatModeCompleter::Sync& ignored_completer) override;
+  void SetShuffleMode(
+      SetShuffleModeRequest& request,
+      SetShuffleModeCompleter::Sync& ignored_completer) override;
   void BindVolumeControl(
-      fidl::InterfaceRequest<fuchsia::media::audio::VolumeControl>
-          volume_control_request) override;
+      BindVolumeControlRequest& request,
+      BindVolumeControlCompleter::Sync& ignored_completer) override;
 
  private:
   // media_session::mojom::MediaSessionObserver implementation.
@@ -76,6 +78,8 @@
   // |pending_info_change_callback_|, if it is set.
   void MaybeSendPlayerInfoDelta();
 
+  void OnBindingClosure(fidl::UnbindInfo info);
+
   // Reports the specified |status| to the client and calls |on_disconnect_|.
   void ReportErrorAndDisconnect(zx_status_t status);
 
@@ -85,14 +89,14 @@
   base::OnceClosure on_disconnect_;
 
   // Binding through which control requests are received from the client.
-  fidl::Binding<fuchsia::media::sessions2::Player> binding_;
+  fidl::ServerBinding<fuchsia_media_sessions2::Player> binding_;
 
   // Binding through which notifications are received from the MediaSession.
   mojo::Receiver<media_session::mojom::MediaSessionObserver> observer_receiver_;
 
   // Pending PlayerInfo deltas and info-change callback.
-  WatchInfoChangeCallback pending_info_change_callback_;
-  fuchsia::media::sessions2::PlayerInfoDelta pending_info_delta_;
+  absl::optional<WatchInfoChangeCompleter::Async> pending_info_change_callback_;
+  fuchsia_media_sessions2::PlayerInfoDelta pending_info_delta_;
 };
 
 #endif  // FUCHSIA_WEB_WEBENGINE_BROWSER_MEDIA_PLAYER_IMPL_H_
diff --git a/fuchsia_web/webengine/browser/media_player_impl_unittest.cc b/fuchsia_web/webengine/browser/media_player_impl_unittest.cc
index 3f183cf9..58d9f7b 100644
--- a/fuchsia_web/webengine/browser/media_player_impl_unittest.cc
+++ b/fuchsia_web/webengine/browser/media_player_impl_unittest.cc
@@ -4,6 +4,12 @@
 
 #include "fuchsia_web/webengine/browser/media_player_impl.h"
 
+#include <fidl/fuchsia.media.sessions2/cpp/fidl.h>
+#include <lib/async/default.h>
+
+#include "base/fuchsia/fidl_event_handler.h"
+#include "base/fuchsia/fuchsia_logging.h"
+#include "base/functional/bind.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
@@ -45,8 +51,8 @@
   mojo::Remote<media_session::mojom::MediaSessionObserver> observer_;
 };
 
-bool HasFlag(const fuchsia::media::sessions2::PlayerCapabilityFlags bits,
-             const fuchsia::media::sessions2::PlayerCapabilityFlags flag) {
+bool HasFlag(const fuchsia_media_sessions2::PlayerCapabilityFlags bits,
+             const fuchsia_media_sessions2::PlayerCapabilityFlags flag) {
   return (bits & flag) == flag;
 }
 
@@ -55,20 +61,45 @@
 class MediaPlayerImplTest : public testing::Test {
  public:
   MediaPlayerImplTest()
-      : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
+      : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
+        player_error_handler_(
+            base::BindRepeating(&MediaPlayerImplTest::OnPlayerFidlError,
+                                base::Unretained(this))) {
+    auto player_endpoints =
+        fidl::CreateEndpoints<fuchsia_media_sessions2::Player>();
+    ZX_CHECK(player_endpoints.is_ok(), player_endpoints.status_value());
+    player_.Bind(std::move(player_endpoints->client),
+                 async_get_default_dispatcher(), &player_error_handler_);
+    player_server_end_ = std::move(player_endpoints->server);
+  }
 
   MediaPlayerImplTest(const MediaPlayerImplTest&) = delete;
   MediaPlayerImplTest& operator=(const MediaPlayerImplTest&) = delete;
 
   ~MediaPlayerImplTest() override = default;
 
-  void OnPlayerDisconnected() {}
+  void SetPlayerFidlErrorCallback(
+      base::RepeatingCallback<void(fidl::UnbindInfo)>
+          player_fidl_error_callback) {
+    player_fidl_error_callback_ = std::move(player_fidl_error_callback);
+  }
 
  protected:
+  void OnPlayerFidlError(fidl::UnbindInfo error) {
+    if (player_fidl_error_callback_) {
+      player_fidl_error_callback_.Run(std::move(error));
+    }
+  }
+
   base::test::SingleThreadTaskEnvironment task_environment_;
 
   testing::StrictMock<FakeMediaSession> fake_session_;
-  fuchsia::media::sessions2::PlayerPtr player_;
+  fidl::Client<fuchsia_media_sessions2::Player> player_;
+  base::FidlErrorEventHandler<fuchsia_media_sessions2::Player>
+      player_error_handler_;
+  base::RepeatingCallback<void(fidl::UnbindInfo)> player_fidl_error_callback_;
+
+  fidl::ServerEnd<fuchsia_media_sessions2::Player> player_server_end_;
 
   std::unique_ptr<MediaPlayerImpl> player_impl_;
 };
@@ -77,8 +108,8 @@
 TEST_F(MediaPlayerImplTest, OnDisconnectCalledOnDisconnect) {
   base::RunLoop run_loop;
   player_impl_ = std::make_unique<MediaPlayerImpl>(
-      &fake_session_, player_.NewRequest(), run_loop.QuitClosure());
-  player_.Unbind();
+      &fake_session_, std::move(player_server_end_), run_loop.QuitClosure());
+  player_ = {};
   run_loop.Run();
 }
 
@@ -89,21 +120,25 @@
   base::RunLoop player_error_loop;
 
   player_impl_ = std::make_unique<MediaPlayerImpl>(
-      &fake_session_, player_.NewRequest(), on_disconnected_loop.QuitClosure());
-  player_.set_error_handler([&player_error_loop](zx_status_t status) {
-    EXPECT_EQ(status, ZX_ERR_BAD_STATE);
-    player_error_loop.Quit();
-  });
+      &fake_session_, std::move(player_server_end_),
+      on_disconnected_loop.QuitClosure());
+  SetPlayerFidlErrorCallback(
+      base::BindLambdaForTesting([&player_error_loop](fidl::UnbindInfo error) {
+        EXPECT_EQ(error.status(), ZX_ERR_BAD_STATE);
+        player_error_loop.Quit();
+      }));
 
   // Call WatchInfoChange() three times in succession. The first call may
   // immediately invoke the callback, with initial state, but since there will
   // be no state-change between that and the second, it will hold the callback,
   // and the third call will therefore be a protocol violation.
-  player_->WatchInfoChange([](fuchsia::media::sessions2::PlayerInfoDelta) {});
-  player_->WatchInfoChange(
-      [](fuchsia::media::sessions2::PlayerInfoDelta) { ADD_FAILURE(); });
-  player_->WatchInfoChange(
-      [](fuchsia::media::sessions2::PlayerInfoDelta) { ADD_FAILURE(); });
+  player_->WatchInfoChange().Then([](auto& result) {
+    ASSERT_TRUE(result.is_ok()) << result.error_value().status_string();
+  });
+  player_->WatchInfoChange().Then(
+      [](auto& result) { ASSERT_TRUE(result.is_error()); });
+  player_->WatchInfoChange().Then(
+      [](auto& result) { ASSERT_TRUE(result.is_error()); });
 
   // Wait for both on-disconnected and player error handler to be invoked.
   on_disconnected_loop.Run();
@@ -112,10 +147,10 @@
 
 // Verify that the first WatchInfoChange() registers the observer.
 TEST_F(MediaPlayerImplTest, WatchInfoChangeRegistersObserver) {
-  player_impl_ =
-      std::make_unique<MediaPlayerImpl>(&fake_session_, player_.NewRequest(),
-                                        MakeExpectedNotRunClosure(FROM_HERE));
-  player_->WatchInfoChange([](fuchsia::media::sessions2::PlayerInfoDelta) {});
+  player_impl_ = std::make_unique<MediaPlayerImpl>(
+      &fake_session_, std::move(player_server_end_),
+      MakeExpectedNotRunClosure(FROM_HERE));
+  player_->WatchInfoChange().Then([](auto result) {});
 
   ASSERT_FALSE(fake_session_.observer());
 
@@ -128,33 +163,42 @@
 // Verify that the initial session state is returned via WatchInfoChange(),
 // potentially via several calls to it.
 TEST_F(MediaPlayerImplTest, WatchInfoChangeReturnsInitialState) {
-  player_impl_ =
-      std::make_unique<MediaPlayerImpl>(&fake_session_, player_.NewRequest(),
-                                        MakeExpectedNotRunClosure(FROM_HERE));
+  player_impl_ = std::make_unique<MediaPlayerImpl>(
+      &fake_session_, std::move(player_server_end_),
+      MakeExpectedNotRunClosure(FROM_HERE));
 
   base::RunLoop return_info_loop;
-  fuchsia::media::sessions2::PlayerInfoDelta initial_info;
-  std::function<void(fuchsia::media::sessions2::PlayerInfoDelta)> watch_info =
-      [this, &initial_info, &watch_info,
-       &return_info_loop](fuchsia::media::sessions2::PlayerInfoDelta delta) {
-        if (delta.has_player_status())
-          initial_info.set_player_status(
-              std::move(*delta.mutable_player_status()));
-        if (delta.has_metadata())
-          initial_info.set_metadata(delta.metadata());
-        if (delta.has_player_capabilities())
-          initial_info.set_player_capabilities(
-              std::move(*delta.mutable_player_capabilities()));
+  fuchsia_media_sessions2::PlayerInfoDelta initial_info;
+  std::function<void(
+      fidl::Result<fuchsia_media_sessions2::Player::WatchInfoChange>&)>
+      on_info_change =
+          [this, &initial_info, &on_info_change, &return_info_loop](
+              fidl::Result<fuchsia_media_sessions2::Player::WatchInfoChange>&
+                  result) {
+            ASSERT_TRUE(result.is_ok()) << result.error_value().status_string();
+            auto delta = result->player_info_delta();
+            if (delta.player_status().has_value()) {
+              initial_info.player_status(
+                  std::move(delta.player_status().value()));
+            }
+            if (delta.metadata().has_value()) {
+              initial_info.metadata(std::move(delta.metadata().value()));
+            }
+            if (delta.player_capabilities().has_value()) {
+              initial_info.player_capabilities(
+                  std::move(delta.player_capabilities().value()));
+            }
 
-        // Only quit the loop once all of the expected fields are present.
-        if (initial_info.has_player_status() && initial_info.has_metadata() &&
-            initial_info.has_player_capabilities()) {
-          return_info_loop.Quit();
-        } else {
-          player_->WatchInfoChange(watch_info);
-        }
-      };
-  player_->WatchInfoChange(watch_info);
+            // Only quit the loop once all of the expected fields are present.
+            if (initial_info.player_status().has_value() &&
+                initial_info.metadata().has_value() &&
+                initial_info.player_capabilities().has_value()) {
+              return_info_loop.Quit();
+            } else {
+              player_->WatchInfoChange().Then(on_info_change);
+            }
+          };
+  player_->WatchInfoChange().Then(on_info_change);
 
   // Pump the message loop to process the WatchInfoChange() call.
   base::RunLoop().RunUntilIdle();
@@ -195,61 +239,65 @@
   return_info_loop.Run();
 
   // Verify that all of the expected fields are present, and correct.
-  ASSERT_TRUE(initial_info.has_player_status());
-  ASSERT_TRUE(initial_info.player_status().has_player_state());
-  EXPECT_EQ(initial_info.player_status().player_state(),
-            fuchsia::media::sessions2::PlayerState::PAUSED);
-  ASSERT_TRUE(initial_info.has_metadata());
+  ASSERT_TRUE(initial_info.player_status().has_value());
+  EXPECT_EQ(initial_info.player_status()->player_state(),
+            fuchsia_media_sessions2::PlayerState::kPaused);
+  ASSERT_TRUE(initial_info.metadata().has_value());
   std::map<std::string, std::string> received_metadata;
-  for (auto& property : initial_info.metadata().properties)
-    received_metadata[property.label] = property.value;
-  EXPECT_EQ(received_metadata[fuchsia::media::METADATA_LABEL_TITLE],
+  for (auto& property : initial_info.metadata()->properties()) {
+    received_metadata[property.label()] = property.value();
+  }
+  EXPECT_EQ(received_metadata[fuchsia_media::kMetadataLabelTitle],
             kExpectedTitle);
-  EXPECT_EQ(received_metadata[fuchsia::media::METADATA_LABEL_ARTIST],
+  EXPECT_EQ(received_metadata[fuchsia_media::kMetadataLabelArtist],
             kExpectedArtist);
-  EXPECT_EQ(received_metadata[fuchsia::media::METADATA_LABEL_ALBUM],
+  EXPECT_EQ(received_metadata[fuchsia_media::kMetadataLabelAlbum],
             kExpectedAlbum);
-  EXPECT_EQ(received_metadata[fuchsia::media::METADATA_SOURCE_TITLE],
+  EXPECT_EQ(received_metadata[fuchsia_media::kMetadataSourceTitle],
             kExpectedSourceTitle);
-  ASSERT_TRUE(initial_info.has_player_capabilities());
-  ASSERT_TRUE(initial_info.player_capabilities().has_flags());
-  const fuchsia::media::sessions2::PlayerCapabilityFlags received_flags =
-      initial_info.player_capabilities().flags();
+  ASSERT_TRUE(initial_info.player_capabilities().has_value());
+  ASSERT_TRUE(initial_info.player_capabilities()->flags().has_value());
+  const fuchsia_media_sessions2::PlayerCapabilityFlags received_flags =
+      initial_info.player_capabilities()->flags().value();
   EXPECT_TRUE(HasFlag(received_flags,
-                      fuchsia::media::sessions2::PlayerCapabilityFlags::PLAY));
+                      fuchsia_media_sessions2::PlayerCapabilityFlags::kPlay));
   EXPECT_TRUE(HasFlag(
       received_flags,
-      fuchsia::media::sessions2::PlayerCapabilityFlags::CHANGE_TO_NEXT_ITEM));
+      fuchsia_media_sessions2::PlayerCapabilityFlags::kChangeToNextItem));
   EXPECT_FALSE(HasFlag(received_flags,
-                       fuchsia::media::sessions2::PlayerCapabilityFlags::SEEK));
-  EXPECT_FALSE(HasFlag(
-      received_flags, fuchsia::media::sessions2::PlayerCapabilityFlags::PAUSE));
+                       fuchsia_media_sessions2::PlayerCapabilityFlags::kSeek));
+  EXPECT_FALSE(HasFlag(received_flags,
+                       fuchsia_media_sessions2::PlayerCapabilityFlags::kPause));
 }
 
 // Verify that WatchInfoChange() waits for the next change to the session state
 // before returning.
 TEST_F(MediaPlayerImplTest, WatchInfoChangeWaitsForNextChange) {
-  player_impl_ =
-      std::make_unique<MediaPlayerImpl>(&fake_session_, player_.NewRequest(),
-                                        MakeExpectedNotRunClosure(FROM_HERE));
+  player_impl_ = std::make_unique<MediaPlayerImpl>(
+      &fake_session_, std::move(player_server_end_),
+      MakeExpectedNotRunClosure(FROM_HERE));
 
   // Start watching, which will connect the observer, and send some initial
   // state so that WatchInfoChange() will return.
   base::RunLoop player_state_loop;
-  std::function<void(fuchsia::media::sessions2::PlayerInfoDelta)>
-      watch_for_player_state =
-          [this, &watch_for_player_state, &player_state_loop](
-              fuchsia::media::sessions2::PlayerInfoDelta delta) {
-            if (!delta.has_player_status() ||
-                !delta.player_status().has_player_state()) {
-              player_->WatchInfoChange(watch_for_player_state);
+  std::function<void(
+      fidl::Result<fuchsia_media_sessions2::Player::WatchInfoChange>&)>
+      on_info_change =
+          [this, &on_info_change, &player_state_loop](
+              fidl::Result<fuchsia_media_sessions2::Player::WatchInfoChange>&
+                  result) {
+            ASSERT_TRUE(result.is_ok()) << result.error_value().status_string();
+            auto delta = result->player_info_delta();
+            if (!delta.player_status().has_value() ||
+                !delta.player_status()->player_state().has_value()) {
+              player_->WatchInfoChange().Then(on_info_change);
               return;
             }
-            EXPECT_EQ(delta.player_status().player_state(),
-                      fuchsia::media::sessions2::PlayerState::PAUSED);
+            EXPECT_EQ(delta.player_status()->player_state().value(),
+                      fuchsia_media_sessions2::PlayerState::kPaused);
             player_state_loop.Quit();
           };
-  player_->WatchInfoChange(watch_for_player_state);
+  player_->WatchInfoChange().Then(on_info_change);
 
   // Pump the message loop to process the first WatchInfoChange() call.
   base::RunLoop().RunUntilIdle();
@@ -266,14 +314,18 @@
   // Calling WatchInfoChange() now should succeed, but not immediately return
   // any new data.
   base::RunLoop change_loop;
-  absl::optional<fuchsia::media::sessions2::PlayerState> state_after_change;
+  absl::optional<fuchsia_media_sessions2::PlayerState> state_after_change;
 
-  player_->WatchInfoChange(
-      [&change_loop,
-       &state_after_change](fuchsia::media::sessions2::PlayerInfoDelta delta) {
-        ASSERT_TRUE(delta.has_player_status());
-        ASSERT_TRUE(delta.player_status().has_player_state());
-        state_after_change.emplace(delta.player_status().player_state());
+  player_->WatchInfoChange().Then(
+      [&change_loop, &state_after_change](
+          fidl::Result<fuchsia_media_sessions2::Player::WatchInfoChange>&
+              result) {
+        ASSERT_TRUE(result.is_ok()) << result.error_value().status_string();
+        auto delta = result->player_info_delta();
+        ASSERT_TRUE(delta.player_status().has_value());
+        ASSERT_TRUE(delta.player_status()->player_state().has_value());
+        state_after_change.emplace(
+            delta.player_status()->player_state().value());
         change_loop.Quit();
       });
 
@@ -288,7 +340,7 @@
   change_loop.Run();
   ASSERT_TRUE(state_after_change.has_value());
   EXPECT_EQ(*state_after_change,
-            fuchsia::media::sessions2::PlayerState::PLAYING);
+            fuchsia_media_sessions2::PlayerState::kPlaying);
 }
 
 // Verify that each of the fire-and-forget playback controls are routed to the
@@ -308,18 +360,18 @@
   EXPECT_CALL(fake_session_, NextTrack());
   EXPECT_CALL(fake_session_, PreviousTrack());
 
-  player_impl_ =
-      std::make_unique<MediaPlayerImpl>(&fake_session_, player_.NewRequest(),
-                                        MakeExpectedNotRunClosure(FROM_HERE));
+  player_impl_ = std::make_unique<MediaPlayerImpl>(
+      &fake_session_, std::move(player_server_end_),
+      MakeExpectedNotRunClosure(FROM_HERE));
 
-  player_->Play();
-  player_->Pause();
-  player_->Stop();
-  player_->Seek(0);
-  player_->SkipForward();
-  player_->SkipReverse();
-  player_->NextItem();
-  player_->PrevItem();
+  EXPECT_TRUE(player_->Play().is_ok());
+  EXPECT_TRUE(player_->Pause().is_ok());
+  EXPECT_TRUE(player_->Stop().is_ok());
+  EXPECT_TRUE(player_->Seek(0).is_ok());
+  EXPECT_TRUE(player_->SkipForward().is_ok());
+  EXPECT_TRUE(player_->SkipReverse().is_ok());
+  EXPECT_TRUE(player_->NextItem().is_ok());
+  EXPECT_TRUE(player_->PrevItem().is_ok());
 
   // Pump the message loop to process each of the calls.
   base::RunLoop().RunUntilIdle();
diff --git a/fuchsia_web/webengine/browser/navigation_policy_browsertest.cc b/fuchsia_web/webengine/browser/navigation_policy_browsertest.cc
index bd5ca72..38c4b9a 100644
--- a/fuchsia_web/webengine/browser/navigation_policy_browsertest.cc
+++ b/fuchsia_web/webengine/browser/navigation_policy_browsertest.cc
@@ -6,13 +6,13 @@
 
 #include "base/task/single_thread_task_runner.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/browser/fake_navigation_policy_provider.h"
 #include "fuchsia_web/webengine/browser/frame_impl.h"
 #include "fuchsia_web/webengine/browser/navigation_policy_handler.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
diff --git a/fuchsia_web/webengine/browser/permissions_browsertest.cc b/fuchsia_web/webengine/browser/permissions_browsertest.cc
index 99f74f0..560ca2b 100644
--- a/fuchsia_web/webengine/browser/permissions_browsertest.cc
+++ b/fuchsia_web/webengine/browser/permissions_browsertest.cc
@@ -7,10 +7,10 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
diff --git a/fuchsia_web/webengine/browser/popup_browsertest.cc b/fuchsia_web/webengine/browser/popup_browsertest.cc
index 0652ba5..bf9584e 100644
--- a/fuchsia_web/webengine/browser/popup_browsertest.cc
+++ b/fuchsia_web/webengine/browser/popup_browsertest.cc
@@ -3,10 +3,10 @@
 // found in the LICENSE file.
 
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 
 namespace {
 
diff --git a/fuchsia_web/webengine/browser/post_message_browsertest.cc b/fuchsia_web/webengine/browser/post_message_browsertest.cc
index b94e0d7..3b59ed7c 100644
--- a/fuchsia_web/webengine/browser/post_message_browsertest.cc
+++ b/fuchsia_web/webengine/browser/post_message_browsertest.cc
@@ -6,10 +6,10 @@
 #include "base/test/test_future.h"
 #include "content/public/test/browser_test.h"
 #include "fuchsia_web/common/test/fit_adapter.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 
 namespace {
 
diff --git a/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc b/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc
index 370a052b..e4ce6855 100644
--- a/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc
+++ b/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc
@@ -5,12 +5,12 @@
 #include "base/task/sequenced_task_runner.h"
 #include "content/public/test/browser_test.h"
 #include "fuchsia_web/common/string_util.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/common/test/url_request_rewrite_test_util.h"
 #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
 #include "fuchsia_web/webengine/switches.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace {
diff --git a/fuchsia_web/webengine/browser/theme_manager_browsertest.cc b/fuchsia_web/webengine/browser/theme_manager_browsertest.cc
index 6a8b634..ff2b676 100644
--- a/fuchsia_web/webengine/browser/theme_manager_browsertest.cc
+++ b/fuchsia_web/webengine/browser/theme_manager_browsertest.cc
@@ -11,11 +11,11 @@
 #include "base/strings/stringprintf.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/browser/frame_impl.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/test_data.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia_web/webengine/browser/url_request_invalidation_browsertest.cc b/fuchsia_web/webengine/browser/url_request_invalidation_browsertest.cc
index a681152..6f01381 100644
--- a/fuchsia_web/webengine/browser/url_request_invalidation_browsertest.cc
+++ b/fuchsia_web/webengine/browser/url_request_invalidation_browsertest.cc
@@ -5,10 +5,10 @@
 #include <fuchsia/web/cpp/fidl.h>
 
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/common/test/url_request_rewrite_test_util.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc b/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc
index 7b239cf..01dc792 100644
--- a/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc
+++ b/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc
@@ -15,13 +15,13 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/public/test/browser_test.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/browser/context_impl.h"
 #include "fuchsia_web/webengine/browser/frame_impl.h"
 #include "fuchsia_web/webengine/browser/mock_virtual_keyboard.h"
 #include "fuchsia_web/webengine/features.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webengine/test/scenic_test_helper.h"
 #include "fuchsia_web/webengine/test/scoped_connection_checker.h"
 #include "fuchsia_web/webengine/test/test_data.h"
diff --git a/fuchsia_web/webengine/browser/web_engine_devtools_controller.cc b/fuchsia_web/webengine/browser/web_engine_devtools_controller.cc
index 706753c..09f3757 100644
--- a/fuchsia_web/webengine/browser/web_engine_devtools_controller.cc
+++ b/fuchsia_web/webengine/browser/web_engine_devtools_controller.cc
@@ -216,8 +216,10 @@
     return !user_debugging;
   }
   void OnFrameLoaded(content::WebContents* contents) override {
-    frame_loaded_ = true;
-    MaybeSendRemoteDebuggingCallbacks();
+    if (!frame_loaded_) {
+      frame_loaded_ = true;
+      MaybeSendRemoteDebuggingCallbacks();
+    }
   }
   void OnFrameDestroyed(content::WebContents* contents) override {}
   content::DevToolsAgentHost::List RemoteDebuggingTargets() override {
diff --git a/fuchsia_web/webengine/web_engine_debug_integration_test.cc b/fuchsia_web/webengine/web_engine_debug_integration_test.cc
index fcdc6c0..7b35230 100644
--- a/fuchsia_web/webengine/web_engine_debug_integration_test.cc
+++ b/fuchsia_web/webengine/web_engine_debug_integration_test.cc
@@ -11,10 +11,10 @@
 #include "base/test/test_future.h"
 #include "fuchsia_web/common/test/fit_adapter.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
+#include "fuchsia_web/common/test/test_debug_listener.h"
 #include "fuchsia_web/common/test/test_devtools_list_fetcher.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
 #include "fuchsia_web/webengine/test/context_provider_for_test.h"
-#include "fuchsia_web/webengine/test_debug_listener.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/fuchsia_web/webinstance_host/web_instance_host_integration_test.cc b/fuchsia_web/webinstance_host/web_instance_host_integration_test.cc
index ad413d0..93b08c4e 100644
--- a/fuchsia_web/webinstance_host/web_instance_host_integration_test.cc
+++ b/fuchsia_web/webinstance_host/web_instance_host_integration_test.cc
@@ -15,10 +15,10 @@
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
 #include "fuchsia_web/common/test/fit_adapter.h"
+#include "fuchsia_web/common/test/frame_for_test.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
 #include "fuchsia_web/common/test/test_devtools_list_fetcher.h"
 #include "fuchsia_web/common/test/test_navigation_listener.h"
-#include "fuchsia_web/webengine/test/frame_for_test.h"
 #include "fuchsia_web/webinstance_host/web_instance_host_v1.h"
 #include "net/test/embedded_test_server/default_handlers.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
diff --git "a/infra/config/generated/builders/ci/Lacros FYI Release \050octopus\051/properties.json" "b/infra/config/generated/builders/ci/Lacros FYI Release \050octopus\051/properties.json"
index a5cc6548..5e98c54 100644
--- "a/infra/config/generated/builders/ci/Lacros FYI Release \050octopus\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Lacros FYI Release \050octopus\051/properties.json"
@@ -21,6 +21,7 @@
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_cros_boards": [
+                  "amd64-generic",
                   "octopus"
                 ],
                 "target_platform": "chromeos"
diff --git a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
index e159e6d..cb2e4c7 100644
--- a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
@@ -374,6 +374,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.CHROMEOS,
             target_cros_boards = [
+                "amd64-generic",
                 "octopus",
             ],
         ),
diff --git a/infra/config/subprojects/chromium/ci/chromium.linux.star b/infra/config/subprojects/chromium/ci/chromium.linux.star
index ac8bf6d..f5b4f1c 100644
--- a/infra/config/subprojects/chromium/ci/chromium.linux.star
+++ b/infra/config/subprojects/chromium/ci/chromium.linux.star
@@ -106,7 +106,6 @@
         ),
         build_gs_bucket = "chromium-linux-archive",
     ),
-    os = os.LINUX_BIONIC,
     # TODO(crbug.com/1173333): Make it tree-closing.
     tree_closing = False,
     console_view_entry = consoles.console_view_entry(
@@ -463,6 +462,7 @@
         ),
         build_gs_bucket = "chromium-linux-archive",
     ),
+    # Focal is needed for better C++20 support. See crbug.com/1284275.
     os = os.LINUX_FOCAL,
     console_view_entry = consoles.console_view_entry(
         category = "release",
diff --git a/infra/config/subprojects/chromium/ci/chromium.memory.star b/infra/config/subprojects/chromium/ci/chromium.memory.star
index 307c4ed..2952113 100644
--- a/infra/config/subprojects/chromium/ci/chromium.memory.star
+++ b/infra/config/subprojects/chromium/ci/chromium.memory.star
@@ -62,7 +62,6 @@
         ),
         build_gs_bucket = "chromium-memory-archive",
     ),
-    os = os.LINUX_BIONIC,
     ssd = True,
     console_view_entry = consoles.console_view_entry(
         category = "linux|asan lsan",
@@ -91,7 +90,6 @@
         ),
         build_gs_bucket = "chromium-memory-archive",
     ),
-    os = os.LINUX_BIONIC,
     console_view_entry = consoles.console_view_entry(
         category = "linux|asan lsan",
         short_name = "tst",
@@ -258,6 +256,8 @@
         build_gs_bucket = "chromium-memory-archive",
     ),
     cores = 16,
+    # At this time, MSan is only compatibly with Focal. See
+    # //docs/linux/instrumented_libraries.md.
     os = os.LINUX_FOCAL,
     ssd = True,
     console_view_entry = consoles.console_view_entry(
@@ -288,6 +288,8 @@
         ),
         build_gs_bucket = "chromium-memory-archive",
     ),
+    # At this time, MSan is only compatibly with Focal. See
+    # //docs/linux/instrumented_libraries.md.
     os = os.LINUX_FOCAL,
     console_view_entry = consoles.console_view_entry(
         category = "cros|msan",
@@ -315,6 +317,8 @@
         ),
         build_gs_bucket = "chromium-memory-archive",
     ),
+    # At this time, MSan is only compatibly with Focal. See
+    # //docs/linux/instrumented_libraries.md.
     os = os.LINUX_FOCAL,
     ssd = True,
     console_view_entry = consoles.console_view_entry(
@@ -343,6 +347,8 @@
         ),
         build_gs_bucket = "chromium-memory-archive",
     ),
+    # At this time, MSan is only compatibly with Focal. See
+    # //docs/linux/instrumented_libraries.md.
     os = os.LINUX_FOCAL,
     console_view_entry = consoles.console_view_entry(
         category = "linux|msan",
@@ -532,6 +538,8 @@
         ),
         build_gs_bucket = "chromium-memory-archive",
     ),
+    # At this time, MSan is only compatibly with Focal. See
+    # //docs/linux/instrumented_libraries.md.
     os = os.LINUX_FOCAL,
     console_view_entry = consoles.console_view_entry(
         category = "linux|webkit",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
index 2d477ee9..79195104 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -80,7 +80,6 @@
     mirrors = [
         "ci/Cast Linux ARM64",
     ],
-    os = os.LINUX_BIONIC,
     main_list_view = "try",
     reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ,
     tryjob = try_.job(
@@ -129,6 +128,7 @@
     mirrors = [
         "ci/linux-gcc-rel",
     ],
+    # Focal is needed for better C++20 support. See crbug.com/1284275.
     os = os.LINUX_FOCAL,
 )
 
@@ -301,6 +301,8 @@
     mirrors = [
         "ci/WebKit Linux MSAN",
     ],
+    # At this time, MSan is only compatibly with Focal. See
+    # //docs/linux/instrumented_libraries.md.
     os = os.LINUX_FOCAL,
     reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ,
 )
@@ -442,6 +444,8 @@
         "ci/Linux ChromiumOS MSan Tests",
     ],
     cores = 16,
+    # At this time, MSan is only compatibly with Focal. See
+    # //docs/linux/instrumented_libraries.md.
     os = os.LINUX_FOCAL,
     ssd = True,
     reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ,
@@ -526,6 +530,8 @@
         "ci/Linux MSan Builder",
         "ci/Linux MSan Tests",
     ],
+    # At this time, MSan is only compatibly with Focal. See
+    # //docs/linux/instrumented_libraries.md.
     os = os.LINUX_FOCAL,
     execution_timeout = 6 * time.hour,
     reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ,
diff --git a/ios/build/bots/scripts/mac_util.py b/ios/build/bots/scripts/mac_util.py
new file mode 100644
index 0000000..c0f967dd
--- /dev/null
+++ b/ios/build/bots/scripts/mac_util.py
@@ -0,0 +1,59 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import distutils.version
+import logging
+import subprocess
+
+LOGGER = logging.getLogger(__name__)
+
+
+def version():
+  """Invokes sw_vers -productVersion
+
+  Raises:
+    subprocess.CalledProcessError on exit codes non zero
+
+  Returns:
+    e.g. 13.2.1
+  """
+  cmd = [
+      'sw_vers',
+      '-productVersion',
+  ]
+
+  # output sample:
+  # 13.2.1
+  output = subprocess.check_output(
+      cmd, stderr=subprocess.STDOUT).decode('utf-8')
+  return output
+
+
+def is_macos_13_or_higher():
+  """Returns true if the current MacOS version is 13 or higher"""
+  return distutils.version.LooseVersion(
+      '13.0') <= distutils.version.LooseVersion(version())
+
+
+def run_codesign_check(dir_path):
+  """Runs codesign check on a directory
+
+    Returns:
+        success (boolean), error (subprocess.CalledProcessError)
+    """
+  try:
+    cmd = [
+        'codesign',
+        '--verify',
+        '--verbose=9',
+        '--deep',
+        '--strict=all',
+        dir_path,
+    ]
+    subprocess.check_call(
+        cmd, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
+  except subprocess.CalledProcessError as e:
+    return False, e
+
+  return True, None
diff --git a/ios/build/bots/scripts/mac_util_test.py b/ios/build/bots/scripts/mac_util_test.py
new file mode 100755
index 0000000..c8ab833
--- /dev/null
+++ b/ios/build/bots/scripts/mac_util_test.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env vpython3
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Unittests for mac_util_test.py."""
+
+import subprocess
+import unittest
+from unittest.mock import patch, MagicMock
+import distutils.version
+
+import mac_util
+import test_runner_test
+
+
+class TestIsMacOS13OrHigher(test_runner_test.TestCase):
+
+  @patch('mac_util.version')
+  def test_is_macos_13_or_higher_with_version_12(self, mock_version):
+    mock_version.return_value = '12.0.0'
+    self.assertFalse(mac_util.is_macos_13_or_higher())
+
+  @patch('mac_util.version')
+  def test_is_macos_13_or_higher_with_version_13(self, mock_version):
+    mock_version.return_value = '13.0.0'
+    self.assertTrue(mac_util.is_macos_13_or_higher())
+
+  @patch('mac_util.version')
+  def test_is_macos_13_or_higher_with_version_14(self, mock_version):
+    mock_version.return_value = '14.0.0'
+    self.assertTrue(mac_util.is_macos_13_or_higher())
+
+
+class TestRunCodesignCheck(test_runner_test.TestCase):
+
+  @patch('subprocess.check_call')
+  def test_run_codesign_check_succeeds(self, mock_check_call):
+    mock_check_call.return_value = MagicMock()
+    success, message = mac_util.run_codesign_check("testdir/Xcode.app")
+    self.assertEqual(success, True)
+    self.assertEqual(message, None)
+
+  @patch('subprocess.check_call')
+  def test_run_codesign_check_fails(self, mock_check_call):
+    error = subprocess.CalledProcessError(1, "codesign check return error")
+    mock_check_call.side_effect = error
+    success, return_error = mac_util.run_codesign_check("testdir/Xcode.app")
+    self.assertEqual(success, False)
+    self.assertEqual(return_error, error)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/ios/build/bots/scripts/xcode_util.py b/ios/build/bots/scripts/xcode_util.py
index c4c93b2..8b19050 100644
--- a/ios/build/bots/scripts/xcode_util.py
+++ b/ios/build/bots/scripts/xcode_util.py
@@ -9,6 +9,7 @@
 import shutil
 import subprocess
 
+import mac_util
 import test_runner_errors
 
 LOGGER = logging.getLogger(__name__)
@@ -62,6 +63,7 @@
   runtimes_in_xcode = glob.glob(
       os.path.join(xcode_app_path, XcodeIOSSimulatorRuntimeRelPath,
                    '*.simruntime'))
+
   is_legacy = len(runtimes_in_xcode) >= 2
   if not is_legacy:
     for runtime in runtimes_in_xcode:
@@ -258,6 +260,8 @@
 
   If using legacy mac_toolchain, install the whole legacy Xcode package. (Will
   raise if the Xcode package isn't legacy.)
+  UPDATE: all MacOS13+ bots will also install the whole legacy Xcode package due
+  to the new codesign restrictions in crbug/1406204
 
   If using new mac_toolchain, first install the Xcode package:
   * If installed Xcode is legacy one (with runtimes bundled), return.
@@ -286,9 +290,29 @@
   """
   using_new_mac_toolchain = _using_new_mac_toolchain(mac_toolchain)
 
+  # (crbug/1406204): for MacOS13+, codesign check is automatically run prior
+  # to Xcode.app runFirstLaunch. To avoid codesign check failure on corrupted
+  # Xcode cache later, we will trigger a codesign check ourself first
+  # to ensure the cached Xcode is good.
+  # Otherwise, we will remove the corrupted Xcode.app and re-install Xcode.
+  if mac_util.is_macos_13_or_higher():
+    LOGGER.debug("checking Xcode's code signature")
+    codesign_success, codesign_error = mac_util.run_codesign_check(
+        xcode_app_path)
+    if not codesign_success:
+      LOGGER.debug(
+          "Xcode signature is invalid %s, going to re-create Xcode.app" %
+          codesign_error)
+      shutil.rmtree(xcode_app_path)
+      os.mkdir(xcode_app_path)
+
   _install_xcode(mac_toolchain, xcode_build_version, xcode_app_path,
                  using_new_mac_toolchain)
-  is_legacy_xcode_package = _is_legacy_xcode_package(xcode_app_path)
+
+  # (crbug/1406204): for MacOS13+, we are using Xcode fat upload/download again,
+  # so runtime should not be installed separately.
+  is_legacy_xcode_package = mac_util.is_macos_13_or_higher(
+  ) or _is_legacy_xcode_package(xcode_app_path)
 
   if not using_new_mac_toolchain and not is_legacy_xcode_package:
     # Legacy mac_toolchain can't handle the situation when no runtime is in
diff --git a/ios/build/bots/scripts/xcode_util_test.py b/ios/build/bots/scripts/xcode_util_test.py
index 1616c27..82610180 100755
--- a/ios/build/bots/scripts/xcode_util_test.py
+++ b/ios/build/bots/scripts/xcode_util_test.py
@@ -65,9 +65,12 @@
   @mock.patch('xcode_util.move_runtime', autospec=True)
   @mock.patch('xcode_util._install_runtime', autospec=True)
   @mock.patch('xcode_util._install_xcode', autospec=True)
-  def test_legacy_mactoolchain_new_xcode(self, mock_install_xcode,
+  @mock.patch('mac_util.is_macos_13_or_higher', autospec=True)
+  def test_legacy_mactoolchain_new_xcode(self, mock_macos_13_or_higher,
+                                         mock_install_xcode,
                                          mock_install_runtime,
                                          mock_move_runtime):
+    mock_macos_13_or_higher.return_value = False
     self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: False)
     self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: False)
 
@@ -87,9 +90,12 @@
   @mock.patch('xcode_util.move_runtime', autospec=True)
   @mock.patch('xcode_util._install_runtime', autospec=True)
   @mock.patch('xcode_util._install_xcode', autospec=True)
-  def test_legacy_mactoolchain_legacy_xcode(self, mock_install_xcode,
+  @mock.patch('mac_util.is_macos_13_or_higher', autospec=True)
+  def test_legacy_mactoolchain_legacy_xcode(self, mock_macos_13_or_higher,
+                                            mock_install_xcode,
                                             mock_install_runtime,
                                             mock_move_runtime):
+    mock_macos_13_or_higher.return_value = False
     self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: False)
     self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: True)
 
@@ -108,9 +114,12 @@
   @mock.patch('xcode_util.move_runtime', autospec=True)
   @mock.patch('xcode_util._install_runtime', autospec=True)
   @mock.patch('xcode_util._install_xcode', autospec=True)
-  def test_new_mactoolchain_legacy_xcode(self, mock_install_xcode,
+  @mock.patch('mac_util.is_macos_13_or_higher', autospec=True)
+  def test_new_mactoolchain_legacy_xcode(self, mock_macos_13_or_higher,
+                                         mock_install_xcode,
                                          mock_install_runtime,
                                          mock_move_runtime):
+    mock_macos_13_or_higher.return_value = False
     self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: True)
     self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: True)
 
@@ -129,8 +138,11 @@
   @mock.patch('xcode_util.move_runtime', autospec=True)
   @mock.patch('xcode_util._install_runtime')
   @mock.patch('xcode_util._install_xcode')
-  def test_new_mactoolchain_new_xcode(self, mock_install_xcode,
-                                      mock_install_runtime, mock_move_runtime):
+  @mock.patch('mac_util.is_macos_13_or_higher', autospec=True)
+  def test_new_mactoolchain_new_xcode(self, mock_macos_13_or_higher,
+                                      mock_install_xcode, mock_install_runtime,
+                                      mock_move_runtime):
+    mock_macos_13_or_higher.return_value = False
     self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: True)
     self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: False)
 
@@ -153,9 +165,12 @@
   @mock.patch('xcode_util.move_runtime', autospec=True)
   @mock.patch('xcode_util._install_runtime')
   @mock.patch('xcode_util._install_xcode')
-  def test_new_mactoolchain_new_xcode_no_runtime(self, mock_install_xcode,
+  @mock.patch('mac_util.is_macos_13_or_higher', autospec=True)
+  def test_new_mactoolchain_new_xcode_no_runtime(self, mock_macos_13_or_higher,
+                                                 mock_install_xcode,
                                                  mock_install_runtime,
                                                  mock_move_runtime):
+    mock_macos_13_or_higher.return_value = False
     self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: True)
     self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: False)
 
@@ -172,6 +187,63 @@
     self.assertFalse(mock_install_runtime.called)
     self.assertFalse(mock_move_runtime.called)
 
+  @mock.patch('xcode_util.move_runtime', autospec=True)
+  @mock.patch('xcode_util._install_runtime')
+  @mock.patch('xcode_util._install_xcode')
+  @mock.patch('mac_util.is_macos_13_or_higher', autospec=True)
+  @mock.patch('mac_util.run_codesign_check', autospec=True)
+  @mock.patch('shutil.rmtree', autospec=True)
+  @mock.patch('os.mkdir', autospec=True)
+  def test_new_mactoolchain_new_xcode_macos13_codesign_failed(
+      self, mock_mkdir, mock_rmtree, mock_codesign_check,
+      mock_macos_13_or_higher, mock_install_xcode, mock_install_runtime,
+      mock_move_runtime):
+    mock_macos_13_or_higher.return_value = True
+    mock_codesign_check.return_value = (False, None)
+    self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: True)
+    self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: False)
+
+    is_legacy_xcode = xcode_util.install(
+        self.mac_toolchain,
+        self.xcode_build_version,
+        self.xcode_app_path,
+        runtime_cache_folder=None,
+        ios_version=None)
+
+    mock_rmtree.assert_called_with(self.xcode_app_path)
+    mock_mkdir.assert_called_with(self.xcode_app_path)
+    self.assertTrue(is_legacy_xcode, 'install should return True')
+    mock_install_xcode.assert_called_with('mac_toolchain', 'TestXcodeVersion',
+                                          'test/path/Xcode.app', True)
+    self.assertFalse(mock_install_runtime.called)
+    self.assertFalse(mock_move_runtime.called)
+
+  @mock.patch('xcode_util.move_runtime', autospec=True)
+  @mock.patch('xcode_util._install_runtime')
+  @mock.patch('xcode_util._install_xcode')
+  @mock.patch('mac_util.is_macos_13_or_higher', autospec=True)
+  @mock.patch('mac_util.run_codesign_check', autospec=True)
+  def test_new_mactoolchain_new_xcode_macos13_codesign_success(
+      self, mock_codesign_check, mock_macos_13_or_higher, mock_install_xcode,
+      mock_install_runtime, mock_move_runtime):
+    mock_macos_13_or_higher.return_value = True
+    mock_codesign_check.return_value = (True, None)
+    self.mock(xcode_util, '_using_new_mac_toolchain', lambda cmd: True)
+    self.mock(xcode_util, '_is_legacy_xcode_package', lambda path: False)
+
+    is_legacy_xcode = xcode_util.install(
+        self.mac_toolchain,
+        self.xcode_build_version,
+        self.xcode_app_path,
+        runtime_cache_folder=None,
+        ios_version=None)
+
+    self.assertTrue(is_legacy_xcode, 'install should return True')
+    mock_install_xcode.assert_called_with('mac_toolchain', 'TestXcodeVersion',
+                                          'test/path/Xcode.app', True)
+    self.assertFalse(mock_install_runtime.called)
+    self.assertFalse(mock_move_runtime.called)
+
 
 class HelperFunctionTests(XcodeUtilTest):
   """Test class for xcode_util misc util functions."""
@@ -240,7 +312,10 @@
 
   @mock.patch('shutil.rmtree', autospec=True)
   @mock.patch('glob.glob', autospec=True)
-  def test_is_legacy_xcode_package_no_runtime(self, mock_glob, mock_rmtree):
+  @mock.patch('mac_util.is_macos_13_or_higher', autospec=True)
+  def test_is_legacy_xcode_package_no_runtime(self, mock_macos_13_or_higher,
+                                              mock_glob, mock_rmtree):
+    mock_macos_13_or_higher.return_value = False
     test_xcode_path = 'test/path/Xcode.app/'
     xcode_runtime_paths = []
     mock_glob.return_value = xcode_runtime_paths
@@ -252,7 +327,10 @@
 
   @mock.patch('shutil.rmtree', autospec=True)
   @mock.patch('glob.glob', autospec=True)
-  def test_is_legacy_xcode_package_single_runtime(self, mock_glob, mock_rmtree):
+  @mock.patch('mac_util.is_macos_13_or_higher', autospec=True)
+  def test_is_legacy_xcode_package_single_runtime(self, mock_macos_13_or_higher,
+                                                  mock_glob, mock_rmtree):
+    mock_macos_13_or_higher.return_value = False
     test_xcode_path = 'test/path/Xcode.app/'
     runtime_names = ['iOS.simruntime']
     xcode_runtime_paths = [
@@ -268,7 +346,6 @@
         os.path.join(test_xcode_path, self.xcode_runtime_dir_rel_path,
                      'iOS.simruntime'))
 
-
 class MoveRuntimeTests(XcodeUtilTest):
   """Test class for xcode_util.move_runtime function."""
 
diff --git a/ios/chrome/app/feed_app_agent.mm b/ios/chrome/app/feed_app_agent.mm
index c091280c..13bec10 100644
--- a/ios/chrome/app/feed_app_agent.mm
+++ b/ios/chrome/app/feed_app_agent.mm
@@ -50,12 +50,12 @@
              InitStageBrowserObjectsForBackgroundHandlers) {
     // Save the value of the feature flag now since 'base::FeatureList' was
     // not available in `InitStageBrowserBasic`.
-    // IsFeedBackgroundRefreshEnabled() simply reads the saved value saved by
-    // SaveFeedBackgroundRefreshEnabledForNextColdStart(). Do not wrap this in
-    // IsFeedBackgroundRefreshEnabled() -- in this case, a new value would
-    // never be saved again once we save NO, since the NO codepath would not
-    // execute saving a new value.
-    SaveFeedBackgroundRefreshEnabledForNextColdStart();
+    // IsFeedBackgroundRefreshCapabilityEnabled() simply reads the saved value
+    // saved by SaveFeedBackgroundRefreshCapabilityEnabledForNextColdStart(). Do
+    // not wrap this in IsFeedBackgroundRefreshCapabilityEnabled() -- in this
+    // case, a new value would never be saved again once we save NO, since the
+    // NO codepath would not execute saving a new value.
+    SaveFeedBackgroundRefreshCapabilityEnabledForNextColdStart();
   } else if (appState.initStage == InitStageNormalUI &&
              IsWebChannelsEnabled() && IsDiscoverFeedServiceCreatedEarly()) {
     // Starting the DiscoverFeedService is required before users are able to
@@ -79,10 +79,8 @@
 #pragma mark - SceneObservingAppAgent
 
 - (void)appDidEnterBackground {
-  if (IsFeedBackgroundRefreshEnabled()) {
-    [self scheduleBackgroundRefresh];
-  }
-  if (IsFeedAppCloseBackgroundRefreshEnabled()) {
+  if (IsFeedBackgroundRefreshEnabled() ||
+      IsFeedAppCloseBackgroundRefreshEnabled()) {
     [self scheduleBackgroundRefresh];
   } else if (IsFeedAppCloseForegroundRefreshEnabled()) {
     [self feedService]->RefreshFeed(FeedRefreshTrigger::kForegroundAppClose);
@@ -91,7 +89,7 @@
 
 - (void)appDidEnterForeground {
   _wasForegroundedAtLeastOnce = YES;
-  if (IsFeedBackgroundRefreshEnabled()) {
+  if (IsFeedBackgroundRefreshCapabilityEnabled()) {
     // This is not strictly necessary, but it makes it more explicit. The OS
     // limits to 1 refresh task at any time, and a new request will replace a
     // previous request. Tasks are only executed in the background.
@@ -115,7 +113,7 @@
 // documentation, this must complete before the end of
 // `applicationDidFinishLaunching`.
 - (void)maybeRegisterBackgroundRefreshTask {
-  if (!IsFeedBackgroundRefreshEnabled()) {
+  if (!IsFeedBackgroundRefreshCapabilityEnabled()) {
     return;
   }
   __weak FeedAppAgent* weakSelf = self;
@@ -137,9 +135,9 @@
 // including other files. The OS only allows one fetch task at a time.
 // Eventually, background fetches should be managed by a central manager.
 - (void)scheduleBackgroundRefresh {
-  // Do not DCHECK IsFeedBackgroundRefreshEnabled() because this is also called
-  // from the background task handler, and the value could have changed during a
-  // cold start.
+  // Do not DCHECK whether background refreshes were enabled at startup because
+  // this is also called from the background task handler, and the value could
+  // have changed during a cold start.
   if (!IsFeedBackgroundRefreshEnabled() &&
       !IsFeedAppCloseBackgroundRefreshEnabled()) {
     return;
@@ -175,9 +173,10 @@
 
 // This method is called when the app is in the background.
 - (void)handleBackgroundRefreshTask:(BGTask*)task {
-  // Do not DCHECK IsFeedBackgroundRefreshEnabled() because the value could have
-  // changed during a cold start.
-  if (!IsFeedBackgroundRefreshEnabled()) {
+  // Do not DCHECK whether background refreshes were enabled at startup because
+  // the value could have changed during a cold start.
+  if (!IsFeedBackgroundRefreshEnabled() &&
+      !IsFeedAppCloseBackgroundRefreshEnabled()) {
     return;
   }
   if (_wasForegroundedAtLeastOnce) {
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 933fdf5b..ce6a06f2 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -696,6 +696,9 @@
       <message name="IDS_IOS_CONTENT_CONTEXT_CLOSETAB" desc="The iOS context menu item for closing a tab. [iOS only]" meaning="Close the current tab [Title Case].">
         Close Tab
       </message>
+      <message name="IDS_IOS_CONTENT_CONTEXT_CLOSEPINNEDTAB" desc="The iOS context menu item for closing a pinned tab. [iOS only]" meaning="Close the current pinned tab [Title Case].">
+        Close Pinned Tab
+      </message>
       <message name="IDS_IOS_CONTENT_CONTEXT_COPY" desc="The iOS menu item for copying a link's URL into the pasteboard. Shorter than the desktop version [iOS only]">
         Copy Link URL
       </message>
@@ -2868,6 +2871,9 @@
       <message name="IDS_IOS_COMPROMISED_PASSWORD_ISSUES_PHISHED_DESCRIPTION" desc="Text explaining the user one of their credentials was phished. Displayed on the password manager screen showing credentials that have been leaked or phished. [iOS only]">
         Entered on deceptive site
       </message>
+      <message name="IDS_IOS_COMPROMISED_PASSWORD_ISSUES_PHISHED_AND_LEAKED_DESCRIPTION" desc="Text explaining the user one of their credentials was phished and leaked. Displayed on the password manager screen showing credentials that have been leaked or phished. [iOS only]">
+        Entered on a deceptive site and found in a data breach
+      </message>
       <message name="IDS_IOS_CHANGE_COMPROMISED_PASSWORD" desc="Button which is shown on Password Details Screen when password is compromised. [iOS only]" meaning="Telling user to change password on a website since it is compromised.">
         Change Password on Website
       </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COMPROMISED_PASSWORD_ISSUES_PHISHED_AND_LEAKED_DESCRIPTION.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COMPROMISED_PASSWORD_ISSUES_PHISHED_AND_LEAKED_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..2596d321
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COMPROMISED_PASSWORD_ISSUES_PHISHED_AND_LEAKED_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+b73ff6a5dd14c5892b36734930d097fad8a80c31
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_CLOSEPINNEDTAB.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_CLOSEPINNEDTAB.png.sha1
new file mode 100644
index 0000000..c0c7664
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_CLOSEPINNEDTAB.png.sha1
@@ -0,0 +1 @@
+adf8a9541028c6b6f293d72a9ebdf84b64135355
\ No newline at end of file
diff --git a/ios/chrome/browser/autofill/autofill_controller_js_unittest.mm b/ios/chrome/browser/autofill/autofill_controller_js_unittest.mm
index 79880f2..69d9785 100644
--- a/ios/chrome/browser/autofill/autofill_controller_js_unittest.mm
+++ b/ios/chrome/browser/autofill/autofill_controller_js_unittest.mm
@@ -8,11 +8,13 @@
 #import "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #import "components/autofill/core/common/autofill_constants.h"
+#import "components/autofill/ios/browser/autofill_java_script_feature.h"
 #import "components/autofill/ios/form_util/form_util_java_script_feature.h"
 #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/web/chrome_web_client.h"
 #import "ios/web/public/js_messaging/web_frame.h"
 #import "ios/web/public/js_messaging/web_frames_manager.h"
+#import "ios/web/public/test/js_test_util.h"
 #import "ios/web/public/test/scoped_testing_web_client.h"
 #import "ios/web/public/test/web_state_test_util.h"
 #import "ios/web/public/test/web_task_environment.h"
@@ -903,6 +905,12 @@
                                            NSArray* get_element_java_scripts,
                                            NSArray* expected_results);
 
+  id ExecuteJavaScript(NSString* java_script);
+
+  std::unique_ptr<base::Value> CallJavaScriptFunction(
+      const std::string& function,
+      const std::vector<base::Value>& parameters);
+
   web::ScopedTestingWebClient web_client_;
   web::WebTaskEnvironment task_environment_;
   std::unique_ptr<TestChromeBrowserState> browser_state_;
@@ -964,8 +972,7 @@
         [NSString stringWithFormat:java_script, get_element_java_script];
     BOOL expected = [get_element_java_scripts_expecting_true
         containsObject:get_element_java_script];
-    EXPECT_NSEQ(@(expected),
-                web::test::ExecuteJavaScript(js_to_execute, web_state()))
+    EXPECT_NSEQ(@(expected), ExecuteJavaScript(js_to_execute))
         << [NSString stringWithFormat:@"%@ on %@ should return %d", java_script,
                                       get_element_java_script, expected];
   }
@@ -978,11 +985,24 @@
   for (NSUInteger i = 0; i < get_element_java_scripts.count; ++i) {
     NSString* js_to_execute =
         [NSString stringWithFormat:java_script, get_element_java_scripts[i]];
-    EXPECT_NSEQ(expected_results[i],
-                web::test::ExecuteJavaScript(js_to_execute, web_state()));
+    EXPECT_NSEQ(expected_results[i], ExecuteJavaScript(js_to_execute));
   }
 }
 
+id AutofillControllerJsTest::ExecuteJavaScript(NSString* java_script) {
+  return web::test::ExecuteJavaScriptForFeature(
+      web_state(), java_script,
+      autofill::AutofillJavaScriptFeature::GetInstance());
+}
+
+std::unique_ptr<base::Value> AutofillControllerJsTest::CallJavaScriptFunction(
+    const std::string& function,
+    const std::vector<base::Value>& parameters) {
+  return web::test::CallJavaScriptFunctionForFeature(
+      web_state(), function, parameters,
+      autofill::AutofillJavaScriptFeature::GetInstance());
+}
+
 TEST_F(AutofillControllerJsTest, HasTagName) {
   const ElementByName elements_expecting_true[] = {
       {"hl", 0, -1},
@@ -1014,8 +1034,8 @@
   params.push_back(base::Value("foo"));
   params.push_back(base::Value("bar"));
   params.push_back(base::Value(false));
-  auto result = web::test::CallJavaScriptFunction(
-      web_state(), "fill.combineAndCollapseWhitespace", params);
+  auto result =
+      CallJavaScriptFunction("fill.combineAndCollapseWhitespace", params);
   ASSERT_TRUE(result->is_string());
   EXPECT_EQ("foobar", result->GetString());
 
@@ -1024,8 +1044,7 @@
   params.push_back(base::Value("foo"));
   params.push_back(base::Value("bar"));
   params.push_back(base::Value(true));
-  result = web::test::CallJavaScriptFunction(
-      web_state(), "fill.combineAndCollapseWhitespace", params);
+  result = CallJavaScriptFunction("fill.combineAndCollapseWhitespace", params);
   ASSERT_TRUE(result->is_string());
   EXPECT_EQ("foo bar", result->GetString());
 
@@ -1034,8 +1053,7 @@
   params.push_back(base::Value("foo "));
   params.push_back(base::Value("bar"));
   params.push_back(base::Value(false));
-  result = web::test::CallJavaScriptFunction(
-      web_state(), "fill.combineAndCollapseWhitespace", params);
+  result = CallJavaScriptFunction("fill.combineAndCollapseWhitespace", params);
   ASSERT_TRUE(result->is_string());
   EXPECT_EQ("foo bar", result->GetString());
 
@@ -1044,8 +1062,7 @@
   params.push_back(base::Value("foo"));
   params.push_back(base::Value(" bar"));
   params.push_back(base::Value(false));
-  result = web::test::CallJavaScriptFunction(
-      web_state(), "fill.combineAndCollapseWhitespace", params);
+  result = CallJavaScriptFunction("fill.combineAndCollapseWhitespace", params);
   ASSERT_TRUE(result->is_string());
   EXPECT_EQ("foo bar", result->GetString());
 
@@ -1054,8 +1071,7 @@
   params.push_back(base::Value("foo"));
   params.push_back(base::Value(" bar"));
   params.push_back(base::Value(true));
-  result = web::test::CallJavaScriptFunction(
-      web_state(), "fill.combineAndCollapseWhitespace", params);
+  result = CallJavaScriptFunction("fill.combineAndCollapseWhitespace", params);
   ASSERT_TRUE(result->is_string());
   EXPECT_EQ("foo bar", result->GetString());
 
@@ -1064,8 +1080,7 @@
   params.push_back(base::Value("foo  "));
   params.push_back(base::Value("  bar"));
   params.push_back(base::Value(false));
-  result = web::test::CallJavaScriptFunction(
-      web_state(), "fill.combineAndCollapseWhitespace", params);
+  result = CallJavaScriptFunction("fill.combineAndCollapseWhitespace", params);
   ASSERT_TRUE(result->is_string());
   EXPECT_EQ("foo bar", result->GetString());
 
@@ -1074,8 +1089,7 @@
   params.push_back(base::Value("foo"));
   params.push_back(base::Value("bar "));
   params.push_back(base::Value(false));
-  result = web::test::CallJavaScriptFunction(
-      web_state(), "fill.combineAndCollapseWhitespace", params);
+  result = CallJavaScriptFunction("fill.combineAndCollapseWhitespace", params);
   ASSERT_TRUE(result->is_string());
   EXPECT_EQ("foobar ", result->GetString());
 
@@ -1084,8 +1098,7 @@
   params.push_back(base::Value(" foo"));
   params.push_back(base::Value("bar"));
   params.push_back(base::Value(true));
-  result = web::test::CallJavaScriptFunction(
-      web_state(), "fill.combineAndCollapseWhitespace", params);
+  result = CallJavaScriptFunction("fill.combineAndCollapseWhitespace", params);
   ASSERT_TRUE(result->is_string());
   EXPECT_EQ(" foo bar", result->GetString());
 }
@@ -1103,12 +1116,11 @@
         stringWithFormat:@"window.document.getElementsByTagName('%@')[%" PRIuNS
                           "]",
                          tag_name, i - 1];
-    id actual = web::test::ExecuteJavaScript(
+    id actual = ExecuteJavaScript(
         [NSString stringWithFormat:@"%@(%@) === %@", javascripts_statement,
                                    get_element_javascripts,
                                    [[test_data objectAtIndex:i]
-                                       objectForKey:attribute_name]],
-        web_state());
+                                       objectForKey:attribute_name]]);
     EXPECT_NSEQ(@YES, actual);
   }
 }
@@ -1294,13 +1306,11 @@
     NSString* new_value = [values objectAtIndex:i];
     EXPECT_NSEQ(
         new_value,
-        web::test::ExecuteJavaScript(
-            [NSString stringWithFormat:
-                          @"var element=%@;var data={'value':'%@'};"
-                          @"__gCrWeb.autofill.fillFormField(data, element);"
-                          @"element.value",
-                          get_element_javascript, new_value],
-            web_state()));
+        ExecuteJavaScript([NSString
+            stringWithFormat:@"var element=%@;var data={'value':'%@'};"
+                             @"__gCrWeb.autofill.fillFormField(data, element);"
+                             @"element.value",
+                             get_element_javascript, new_value]));
   }
 
   // Test clickable elements, of which 'checked' should be updated.
@@ -1318,15 +1328,13 @@
 
     EXPECT_NSEQ(
         @(is_checked),
-        web::test::ExecuteJavaScript(
-            [NSString stringWithFormat:
-                          @"var element=%@; var value=element.value; "
-                          @"var data={'value':value,'is_checked':%@};"
-                          @"__gCrWeb.autofill.fillFormField(data, element); "
-                          @"element.checked",
-                          get_element_javascript,
-                          is_checked ? @"true" : @"false"],
-            web_state()));
+        ExecuteJavaScript([NSString
+            stringWithFormat:@"var element=%@; var value=element.value; "
+                             @"var data={'value':value,'is_checked':%@};"
+                             @"__gCrWeb.autofill.fillFormField(data, element); "
+                             @"element.checked",
+                             get_element_javascript,
+                             is_checked ? @"true" : @"false"]));
   }
 
   // Test elements of which the value should not be changed.
@@ -1338,14 +1346,13 @@
   for (size_t i = 0; i < std::size(unchanged_elements); ++i) {
     NSString* get_element_javascript =
         GetElementByNameJavaScript(unchanged_elements[i]);
-    NSString* actual = web::test::ExecuteJavaScript(
+    NSString* actual = ExecuteJavaScript(
         [NSString stringWithFormat:
                       @"var element=%@;"
                       @"var oldValue=element.value; var data={'value':'new'};"
                       @"__gCrWeb.autofill.fillFormField(data, element);"
                       @"element.value === oldValue",
-                      get_element_javascript],
-        web_state());
+                      get_element_javascript]);
     EXPECT_NSEQ(@YES, actual);
   }
 }
@@ -1418,14 +1425,12 @@
   for (NSUInteger index = 0; index < [expected count]; index++) {
     EXPECT_NSEQ(
         @YES,
-        web::test::ExecuteJavaScript(
-            [NSString
-                stringWithFormat:
-                    @"var controlElements="
-                     "__gCrWeb.autofill.extractAutofillableElementsInForm(%@);"
-                     "controlElements[%" PRIuNS "] === %@",
-                    parameter, index, expected[index]],
-            web_state()));
+        ExecuteJavaScript([NSString
+            stringWithFormat:
+                @"var controlElements="
+                 "__gCrWeb.autofill.extractAutofillableElementsInForm(%@);"
+                 "controlElements[%" PRIuNS "] === %@",
+                parameter, index, expected[index]]));
   }
 }
 
@@ -1453,29 +1458,25 @@
           @"field", extract_mask, expected, attributes_to_check, -1);
       EXPECT_NSEQ(
           @YES,
-          web::test::ExecuteJavaScript(
-              [NSString stringWithFormat:
-                            @"%@; var field = {};"
-                             "__gCrWeb.fill.webFormControlElementToFormField("
-                             "    element, %u, field);"
-                             "%@",
-                            get_element_to_test, extract_mask,
-                            verifying_javascripts],
-              web_state()))
+          ExecuteJavaScript([NSString
+              stringWithFormat:
+                  @"%@; var field = {};"
+                   "__gCrWeb.fill.webFormControlElementToFormField("
+                   "    element, %u, field);"
+                   "%@",
+                  get_element_to_test, extract_mask, verifying_javascripts]))
           << base::SysNSStringToUTF8([NSString
                  stringWithFormat:
                      @"webFormControlElementToFormField actual results are: "
                      @"%@, \n"
                       "expected to be verified by %@",
-                     web::test::ExecuteJavaScript(
-                         [NSString stringWithFormat:
-                                       @"%@; var field = {};"
-                                        "__gCrWeb.fill."
-                                        "webFormControlElementToFormField("
-                                        "    element, %u, "
-                                        "field);__gCrWeb.stringify(field);",
-                                       get_element_to_test, extract_mask],
-                         web_state()),
+                     ExecuteJavaScript([NSString
+                         stringWithFormat:@"%@; var field = {};"
+                                           "__gCrWeb.fill."
+                                           "webFormControlElementToFormField("
+                                           "    element, %u, "
+                                           "field);__gCrWeb.stringify(field);",
+                                          get_element_to_test, extract_mask]),
                      verifying_javascripts]);
     }
   }
@@ -1514,27 +1515,24 @@
     NSUInteger extract_mask,
     NSString* expected_result,
     NSString* verifying_javascripts) {
-  NSString* actual = web::test::ExecuteJavaScript(
+  NSString* actual = ExecuteJavaScript(
       [NSString stringWithFormat:@"var form={}; var field={};"
                                   "(__gCrWeb.fill.webFormElementToFormData("
                                   "window, %@, null, %" PRIuNS
                                   ", form, field) === %@) && %@",
                                  get_form_element_javascripts, extract_mask,
-                                 expected_result, verifying_javascripts],
-      web_state());
+                                 expected_result, verifying_javascripts]);
 
   EXPECT_NSEQ(@YES, actual) << base::SysNSStringToUTF8([NSString
       stringWithFormat:
           @"Actual:\n%@; expected to be verifyied by\n%@",
-          web::test::ExecuteJavaScript(
-              [NSString
-                  stringWithFormat:@"var form={};"
-                                    "__gCrWeb.fill."
-                                    "webFormElementToFormData(window, %@, null,"
-                                    "%" PRIuNS ", form, null);"
-                                    "__gCrWeb.stringify(form);",
-                                   get_form_element_javascripts, extract_mask],
-              web_state()),
+          ExecuteJavaScript([NSString
+              stringWithFormat:@"var form={};"
+                                "__gCrWeb.fill."
+                                "webFormElementToFormData(window, %@, null,"
+                                "%" PRIuNS ", form, null);"
+                                "__gCrWeb.stringify(form);",
+                               get_form_element_javascripts, extract_mask]),
           verifying_javascripts]);
 }
 
@@ -1660,24 +1658,20 @@
                       GetFormFieldAttributeListsToCheck(extract_mask))];
   }
 
-  NSString* actual = web::test::ExecuteJavaScript(
-      [NSString stringWithFormat:
-                    @"var forms = __gCrWeb.autofill.extractNewForms(%" PRIuS
-                     ", true); %@",
-                    autofill::kMinRequiredFieldsForHeuristics,
-                    [verifying_javascripts componentsJoinedByString:@"&&"]],
-      web_state());
+  NSString* actual = ExecuteJavaScript([NSString
+      stringWithFormat:@"var forms = __gCrWeb.autofill.extractNewForms(%" PRIuS
+                        ", true); %@",
+                       autofill::kMinRequiredFieldsForHeuristics,
+                       [verifying_javascripts componentsJoinedByString:@"&&"]]);
 
   EXPECT_NSEQ(@YES, actual) << base::SysNSStringToUTF8([NSString
       stringWithFormat:
           @"actually forms = %@, "
            "but it is expected to be verified by %@",
-          web::test::ExecuteJavaScript(
-              [NSString stringWithFormat:
-                            @"var forms = __gCrWeb.autofill.extractNewForms("
-                             "%" PRIuS ", true); __gCrWeb.stringify(forms)",
-                            autofill::kMinRequiredFieldsForHeuristics],
-              web_state()),
+          ExecuteJavaScript([NSString
+              stringWithFormat:@"var forms = __gCrWeb.autofill.extractNewForms("
+                                "%" PRIuS ", true); __gCrWeb.stringify(forms)",
+                               autofill::kMinRequiredFieldsForHeuristics]),
           verifying_javascripts]);
 }
 
@@ -1740,12 +1734,11 @@
                                    @"forms[0]['fields'][3]['name']==='name4' &&"
                                    @"forms[0]['fields'][3]['label']==='4'";
   EXPECT_NSEQ(
-      @YES, web::test::ExecuteJavaScript(
-                [NSString stringWithFormat:
-                              @"var forms = "
-                               "__gCrWeb.autofill.extractNewForms(1, true); %@",
-                              verifying_javascript],
-                web_state()));
+      @YES,
+      ExecuteJavaScript([NSString
+          stringWithFormat:@"var forms = "
+                            "__gCrWeb.autofill.extractNewForms(1, true); %@",
+                           verifying_javascript]));
 }
 
 TEST_F(AutofillControllerJsTest, ExtractForms) {
@@ -1779,8 +1772,7 @@
 
   // Wait for `SetUpForUniqueIDsWithInitialState` to complete.
   ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
-    return [web::test::ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]",
-                                         web_state()) intValue] ==
+    return [ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]") intValue] ==
            static_cast<int>(next_available_id);
   }));
 
@@ -1916,10 +1908,9 @@
     ]
   };
 
-  NSString* result = web::test::ExecuteJavaScript(
+  NSString* result = ExecuteJavaScript(
       [NSString stringWithFormat:@"__gCrWeb.autofill.extractForms(%zu, true)",
-                                 autofill::kMinRequiredFieldsForHeuristics],
-      web_state());
+                                 autofill::kMinRequiredFieldsForHeuristics]);
   NSArray* resultArray = [NSJSONSerialization
       JSONObjectWithData:[result dataUsingEncoding:NSUTF8StringEncoding]
                  options:0
@@ -1933,12 +1924,10 @@
   }];
 
   // Test with Object.prototype.toJSON override.
-  result = web::test::ExecuteJavaScript(
-      [NSString stringWithFormat:
-                    @"Object.prototype.toJSON=function(){return 'abcde';};"
-                     "__gCrWeb.autofill.extractForms(%zu, true)",
-                    autofill::kMinRequiredFieldsForHeuristics],
-      web_state());
+  result = ExecuteJavaScript([NSString
+      stringWithFormat:@"Object.prototype.toJSON=function(){return 'abcde';};"
+                        "__gCrWeb.autofill.extractForms(%zu, true)",
+                       autofill::kMinRequiredFieldsForHeuristics]);
   resultArray = [NSJSONSerialization
       JSONObjectWithData:[result dataUsingEncoding:NSUTF8StringEncoding]
                  options:0
@@ -1951,12 +1940,10 @@
   }];
 
   // Test with Array.prototype.toJSON override.
-  result = web::test::ExecuteJavaScript(
-      [NSString stringWithFormat:
-                    @"Array.prototype.toJSON=function(){return 'abcde';};"
-                     "__gCrWeb.autofill.extractForms(%zu, true)",
-                    autofill::kMinRequiredFieldsForHeuristics],
-      web_state());
+  result = ExecuteJavaScript([NSString
+      stringWithFormat:@"Array.prototype.toJSON=function(){return 'abcde';};"
+                        "__gCrWeb.autofill.extractForms(%zu, true)",
+                       autofill::kMinRequiredFieldsForHeuristics]);
   resultArray = [NSJSONSerialization
       JSONObjectWithData:[result dataUsingEncoding:NSUTF8StringEncoding]
                  options:0
@@ -1981,46 +1968,38 @@
 
   // Wait for `SetUpForUniqueIDsWithInitialState` to complete.
   ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
-    return [web::test::ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]",
-                                         web_state()) intValue] ==
+    return [ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]") intValue] ==
            static_cast<int>(next_available_id);
   }));
 
   // Simulate form parsing to set renderer IDs.
-  web::test::ExecuteJavaScript(@"__gCrWeb.autofill.extractForms(0, true)",
-                               web_state());
+  ExecuteJavaScript(@"__gCrWeb.autofill.extractForms(0, true)");
 
   NSString* newValue = @"new value";
-  EXPECT_NSEQ(
-      newValue,
-      web::test::ExecuteJavaScript(
-          [NSString
-              stringWithFormat:
-                  @"var element=document.getElementsByName('lastname')[0];"
-                   "element.focus();"
-                   "var "
-                   "data={\"name\":\"lastname\",\"value\":\"%@\","
-                   "\"identifier\":\"lastname\",\"unique_renderer_id\":3};"
-                   "__gCrWeb.autofill.fillActiveFormField(data);"
-                   "element.value",
-                  newValue],
-          web_state()));
+  EXPECT_NSEQ(newValue,
+              ExecuteJavaScript([NSString
+                  stringWithFormat:
+                      @"var element=document.getElementsByName('lastname')[0];"
+                       "element.focus();"
+                       "var "
+                       "data={\"name\":\"lastname\",\"value\":\"%@\","
+                       "\"identifier\":\"lastname\",\"unique_renderer_id\":3};"
+                       "__gCrWeb.autofill.fillActiveFormField(data);"
+                       "element.value",
+                      newValue]));
 
-  EXPECT_NSEQ(
-      @YES,
-      web::test::ExecuteJavaScript(
-          [NSString
-              stringWithFormat:
-                  @"var element=document.getElementsByName('gl')[0];"
-                   "element.focus();"
-                   "var oldValue = element.value;"
-                   "var "
-                   "data={\"name\":\"lastname\",\"value\":\"%@\","
-                   "\"identifier\":\"lastname\",\"unique_renderer_id\":3};"
-                   "__gCrWeb.autofill.fillActiveFormField(data);"
-                   "element.value === oldValue",
-                  newValue],
-          web_state()))
+  EXPECT_NSEQ(@YES,
+              ExecuteJavaScript([NSString
+                  stringWithFormat:
+                      @"var element=document.getElementsByName('gl')[0];"
+                       "element.focus();"
+                       "var oldValue = element.value;"
+                       "var "
+                       "data={\"name\":\"lastname\",\"value\":\"%@\","
+                       "\"identifier\":\"lastname\",\"unique_renderer_id\":3};"
+                       "__gCrWeb.autofill.fillActiveFormField(data);"
+                       "element.value === oldValue",
+                      newValue]))
       << "A non-form element's value should changed.";
 }
 
@@ -2066,10 +2045,9 @@
   for (NSDictionary* testCase in testCases) {
     web::test::LoadHtml(testCase[@"html"], web_state());
 
-    NSString* result = web::test::ExecuteJavaScript(
+    NSString* result = ExecuteJavaScript(
         [NSString stringWithFormat:@"__gCrWeb.autofill.extractForms(%zu, true)",
-                                   autofill::kMinRequiredFieldsForHeuristics],
-        web_state());
+                                   autofill::kMinRequiredFieldsForHeuristics]);
     NSArray* resultArray = [NSJSONSerialization
         JSONObjectWithData:[result dataUsingEncoding:NSUTF8StringEncoding]
                    options:0
@@ -2090,11 +2068,9 @@
     @[ @"  --  (()c)__  ", @NO ], @[ @"123-456-7890", @NO ], @[ @"", @YES ]
   ];
   for (NSArray* test in tests) {
-    NSString* result = web::test::ExecuteJavaScript(
-        [NSString
-            stringWithFormat:@"__gCrWeb.autofill.sanitizedFieldIsEmpty('%@');",
-                             test[0]],
-        web_state());
+    NSString* result = ExecuteJavaScript([NSString
+        stringWithFormat:@"__gCrWeb.autofill.sanitizedFieldIsEmpty('%@');",
+                         test[0]]);
     EXPECT_NSEQ(result, test[1]);
   }
 }
diff --git a/ios/chrome/browser/autofill/autofill_java_script_feature_unittest.mm b/ios/chrome/browser/autofill/autofill_java_script_feature_unittest.mm
index 806d32a..a62ea3b 100644
--- a/ios/chrome/browser/autofill/autofill_java_script_feature_unittest.mm
+++ b/ios/chrome/browser/autofill/autofill_java_script_feature_unittest.mm
@@ -107,16 +107,14 @@
 
     // Wait for `SetUpForUniqueIDsWithInitialState` to complete.
     ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
-      return [web::test::ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]",
-                                           web_state()) intValue] ==
-             static_cast<int>(next_available_id);
+      return [ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]")
+                 intValue] == static_cast<int>(next_available_id);
     }));
   }
 
   web::WebFrame* main_web_frame() {
     web::WebFramesManager* frames_manager =
-        autofill::AutofillJavaScriptFeature::GetInstance()->GetWebFramesManager(
-            web_state());
+        feature()->GetWebFramesManager(web_state());
 
     return frames_manager->GetMainWebFrame();
   }
@@ -139,6 +137,11 @@
     });
   }
 
+  id ExecuteJavaScript(NSString* java_script) {
+    return web::test::ExecuteJavaScriptForFeature(web_state(), java_script,
+                                                  feature());
+  }
+
   autofill::AutofillJavaScriptFeature* feature() {
     return autofill::AutofillJavaScriptFeature::GetInstance();
   }
@@ -154,8 +157,7 @@
 // Tests that `hasBeenInjected` returns YES after `inject` call.
 TEST_F(AutofillJavaScriptFeatureTest, InitAndInject) {
   LoadHtml(@"<html></html>");
-  EXPECT_NSEQ(@"object", web::test::ExecuteJavaScript(
-                             @"typeof __gCrWeb.autofill", web_state()));
+  EXPECT_NSEQ(@"object", ExecuteJavaScript(@"typeof __gCrWeb.autofill"));
 }
 
 // Tests forms extraction method
@@ -384,7 +386,7 @@
   NSString* get_element_javascript = @"document.getElementsByName('email')[0]";
   NSString* focus_element_javascript =
       [NSString stringWithFormat:@"%@.focus()", get_element_javascript];
-  web::test::ExecuteJavaScript(focus_element_javascript, web_state());
+  ExecuteJavaScript(focus_element_javascript);
   base::Value::Dict data;
   data.Set("name", "email");
   data.Set("identifier", "email");
@@ -402,8 +404,7 @@
       }));
   NSString* element_value_javascript =
       [NSString stringWithFormat:@"%@.value", get_element_javascript];
-  EXPECT_NSEQ(@"newemail@com", web::test::ExecuteJavaScript(
-                                   element_value_javascript, web_state()));
+  EXPECT_NSEQ(@"newemail@com", ExecuteJavaScript(element_value_javascript));
 }
 
 // Tests the generation of the name of the fields.
@@ -521,11 +522,9 @@
   RunFormsSearch();
 
   // Simulate interacting with the field that should be force filled.
-  web::test::ExecuteJavaScript(
-      @"var field = document.getElementById('firstname');"
-       "field.focus();"
-       "field.value = 'to_be_erased';",
-      web_state());
+  ExecuteJavaScript(@"var field = document.getElementById('firstname');"
+                     "field.focus();"
+                     "field.value = 'to_be_erased';");
 
   base::Value::Dict autofillData;
   autofillData.Set("formName", "testform");
@@ -579,7 +578,7 @@
                                    field_data.first];
     NSString* focusScript =
         [NSString stringWithFormat:@"%@.focus()", getFieldScript];
-    web::test::ExecuteJavaScript(focusScript, web_state());
+    ExecuteJavaScript(focusScript);
     base::Value::Dict data;
     data.Set("unique_renderer_id", field_data.second);
     data.Set("value", "testvalue");
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 4cc3ee2f..454af883 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1488,9 +1488,9 @@
      flag_descriptions::kIOSBrowserEditMenuMetricsName,
      flag_descriptions::kIOSBrowserEditMenuMetricsDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kIOSBrowserEditMenuMetrics)},
-    {"sf-symbols-follow-up", flag_descriptions::kSFSymbolsFollowupName,
-     flag_descriptions::kSFSymbolsFollowupDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kSFSymbolsFollowup)},
+    {"sf-symbols-follow-up", flag_descriptions::kSFSymbolsFollowUpName,
+     flag_descriptions::kSFSymbolsFollowUpDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(kSFSymbolsFollowUp)},
     {"enable-reading-list-account-storage",
      flag_descriptions::kEnableReadingListAccountStorageName,
      flag_descriptions::kEnableReadingListAccountStorageDescription,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 39f28c2..6ce8ac4 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -998,8 +998,8 @@
     "when Google is the selected search engine, accessible from the omnibox or "
     "popup menu.";
 
-const char kSFSymbolsFollowupName[] = "SF Symbol follow up";
-const char kSFSymbolsFollowupDescription[] = "Change the + button.";
+const char kSFSymbolsFollowUpName[] = "SF Symbol follow up";
+const char kSFSymbolsFollowUpDescription[] = "Change the + button.";
 
 const char kTabGridRecencySortName[] = "Change TabGrid sorting";
 const char kTabGridRecencySortDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 16bcfef..4d92ea3 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -868,8 +868,8 @@
 extern const char kEnableLensInOmniboxCopiedImageDescription[];
 
 // Title and description for the flag to enable the follow up of the SF Symbols.
-extern const char kSFSymbolsFollowupName[];
-extern const char kSFSymbolsFollowupDescription[];
+extern const char kSFSymbolsFollowUpName[];
+extern const char kSFSymbolsFollowUpDescription[];
 
 // Title and description for the flag to sort the tab by recency in the TabGrid.
 extern const char kTabGridRecencySortName[];
diff --git a/ios/chrome/browser/ntp/features.h b/ios/chrome/browser/ntp/features.h
index bb3d259..0e06021 100644
--- a/ios/chrome/browser/ntp/features.h
+++ b/ios/chrome/browser/ntp/features.h
@@ -116,15 +116,25 @@
 // Whether the Discover service is created early, alongside the app creation.
 bool IsDiscoverFeedServiceCreatedEarly();
 
-// Whether feed background refresh is enabled. Returns the value in
-// NSUserDefaults set by `SaveFeedBackgroundRefreshEnabledForNextColdStart()`.
-// This function always returns false if the `IOS_BACKGROUND_MODE_ENABLED`
-// buildflag is not defined.
+// Whether feed background refresh is enabled and the capability was enabled at
+// startup.
 bool IsFeedBackgroundRefreshEnabled();
 
-// Saves the current value for feature `kEnableFeedBackgroundRefresh`. This call
+// Whether feed background refresh capability is enabled. Returns the value in
+// NSUserDefaults set by
+// `SaveFeedBackgroundRefreshCapabilityEnabledForNextColdStart()`. This is used
+// because registering for background refreshes must happen early in app
+// initialization and FeatureList is not yet available. Enabling or disabling
+// background refresh features will always take effect after two cold starts
+// after the feature has been changed on the server (once for the Finch
+// configuration, and another for reading the stored value from NSUserDefaults).
+// This function always returns false if the `IOS_BACKGROUND_MODE_ENABLED`
+// buildflag is not defined.
+bool IsFeedBackgroundRefreshCapabilityEnabled();
+
+// Saves whether any background refresh experiment is enabled. This call
 // DCHECKs on the availability of `base::FeatureList`.
-void SaveFeedBackgroundRefreshEnabledForNextColdStart();
+void SaveFeedBackgroundRefreshCapabilityEnabledForNextColdStart();
 
 // Sets `timestamp` for key `NSUserDefaultsKey` to be displayed in Experimental
 // Settings in the Settings App. This is not available in stable.
@@ -174,7 +184,7 @@
 bool IsFeedAppCloseForegroundRefreshEnabled();
 
 // Whether feed is refreshed in the background soon after the app is
-// backgrounded.
+// backgrounded, and the capability was enabled at startup.
 bool IsFeedAppCloseBackgroundRefreshEnabled();
 
 // Returns the engagement criteria type for a feed refresh.
diff --git a/ios/chrome/browser/ntp/features.mm b/ios/chrome/browser/ntp/features.mm
index b04b793..0e4e4176 100644
--- a/ios/chrome/browser/ntp/features.mm
+++ b/ios/chrome/browser/ntp/features.mm
@@ -16,6 +16,26 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+
+// Whether feed background refresh is enabled. This only checks if the feature
+// is enabled, not if the capability was enabled at startup.
+bool IsFeedBackgroundRefreshEnabledOnly() {
+  return base::FeatureList::IsEnabled(kEnableFeedBackgroundRefresh);
+}
+
+// Whether feed is refreshed in the background soon after the app is
+// backgrounded. This only checks if the feature is enabled, not if the
+// capability was enabled at startup.
+bool IsFeedAppCloseBackgroundRefreshEnabledOnly() {
+  return base::GetFieldTrialParamByFeatureAsBool(
+      kEnableFeedInvisibleForegroundRefresh,
+      kEnableFeedAppCloseBackgroundRefresh,
+      /*default=*/false);
+}
+
+}  // namespace
+
 BASE_FEATURE(kEnableWebChannels,
              "EnableWebChannels",
              base::FEATURE_DISABLED_BY_DEFAULT);
@@ -51,14 +71,14 @@
 BASE_FEATURE(kIOSSetUpList, "IOSSetUpList", base::FEATURE_DISABLED_BY_DEFAULT);
 
 // Key for NSUserDefaults containing a bool indicating whether the next run
-// should enable feed background refresh. This is used because registering for
-// background refreshes must happen early in app initialization and FeatureList
-// is not yet available. Changing the `kEnableFeedBackgroundRefresh` feature
-// will always take effect after two cold starts after the feature has been
-// changed on the server (once for the Finch configuration, and another for
-// reading the stored value from NSUserDefaults).
-NSString* const kEnableFeedBackgroundRefreshForNextColdStart =
-    @"EnableFeedBackgroundRefreshForNextColdStart";
+// should enable feed background refresh capability. This is used because
+// registering for background refreshes must happen early in app initialization
+// and FeatureList is not yet available. Enabling or disabling background
+// refresh features will always take effect after two cold starts after the
+// feature has been changed on the server (once for the Finch configuration, and
+// another for reading the stored value from NSUserDefaults).
+NSString* const kEnableFeedBackgroundRefreshCapabilityForNextColdStart =
+    @"EnableFeedBackgroundRefreshCapabilityForNextColdStart";
 
 const char kEnableFollowingFeedBackgroundRefresh[] =
     "EnableFollowingFeedBackgroundRefresh";
@@ -97,21 +117,28 @@
 }
 
 bool IsFeedBackgroundRefreshEnabled() {
+  return IsFeedBackgroundRefreshCapabilityEnabled() &&
+         IsFeedBackgroundRefreshEnabledOnly();
+}
+
+bool IsFeedBackgroundRefreshCapabilityEnabled() {
 #if !BUILDFLAG(IOS_BACKGROUND_MODE_ENABLED)
   return false;
 #else
   static bool feedBackgroundRefreshEnabled =
       [[NSUserDefaults standardUserDefaults]
-          boolForKey:kEnableFeedBackgroundRefreshForNextColdStart];
+          boolForKey:kEnableFeedBackgroundRefreshCapabilityForNextColdStart];
   return feedBackgroundRefreshEnabled;
 #endif  // BUILDFLAG(IOS_BACKGROUND_MODE_ENABLED)
 }
 
-void SaveFeedBackgroundRefreshEnabledForNextColdStart() {
+void SaveFeedBackgroundRefreshCapabilityEnabledForNextColdStart() {
   DCHECK(base::FeatureList::GetInstance());
+  BOOL enabled = IsFeedBackgroundRefreshEnabledOnly() ||
+                 IsFeedAppCloseBackgroundRefreshEnabledOnly();
   [[NSUserDefaults standardUserDefaults]
-      setBool:base::FeatureList::IsEnabled(kEnableFeedBackgroundRefresh)
-       forKey:kEnableFeedBackgroundRefreshForNextColdStart];
+      setBool:enabled
+       forKey:kEnableFeedBackgroundRefreshCapabilityForNextColdStart];
 }
 
 void SetFeedRefreshTimestamp(NSDate* timestamp, NSString* NSUserDefaultsKey) {
@@ -136,7 +163,7 @@
   if (GetChannel() == version_info::Channel::STABLE) {
     return false;
   }
-  return IsFeedBackgroundRefreshEnabled() &&
+  return IsFeedBackgroundRefreshCapabilityEnabled() &&
          [[NSUserDefaults standardUserDefaults]
              boolForKey:@"FeedBackgroundRefreshNotificationEnabled"];
 }
@@ -216,10 +243,8 @@
 }
 
 bool IsFeedAppCloseBackgroundRefreshEnabled() {
-  return base::GetFieldTrialParamByFeatureAsBool(
-      kEnableFeedInvisibleForegroundRefresh,
-      kEnableFeedAppCloseBackgroundRefresh,
-      /*default=*/false);
+  return IsFeedBackgroundRefreshCapabilityEnabled() &&
+         IsFeedAppCloseBackgroundRefreshEnabledOnly();
 }
 
 FeedRefreshEngagementCriteriaType GetFeedRefreshEngagementCriteriaType() {
diff --git a/ios/chrome/browser/shared/public/features/features.cc b/ios/chrome/browser/shared/public/features/features.cc
index 6cce415..a9d2539 100644
--- a/ios/chrome/browser/shared/public/features/features.cc
+++ b/ios/chrome/browser/shared/public/features/features.cc
@@ -128,8 +128,8 @@
              "UseSFSymbolsInOmnibox",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kSFSymbolsFollowup,
-             "SFSymbolsFollowup",
+BASE_FEATURE(kSFSymbolsFollowUp,
+             "SFSymbolsFollowUp",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
 BASE_FEATURE(kCalendarExperienceKit,
diff --git a/ios/chrome/browser/shared/public/features/features.h b/ios/chrome/browser/shared/public/features/features.h
index fc466f30..287ce407 100644
--- a/ios/chrome/browser/shared/public/features/features.h
+++ b/ios/chrome/browser/shared/public/features/features.h
@@ -108,7 +108,7 @@
 BASE_DECLARE_FEATURE(kUseSFSymbolsInOmnibox);
 
 // Feature flag for the follow up of the SF Symbols.
-BASE_DECLARE_FEATURE(kSFSymbolsFollowup);
+BASE_DECLARE_FEATURE(kSFSymbolsFollowUp);
 
 // Feature flag to enable Calendar event in experience kit.
 BASE_DECLARE_FEATURE(kCalendarExperienceKit);
diff --git a/ios/chrome/browser/ui/bring_android_tabs/BUILD.gn b/ios/chrome/browser/ui/bring_android_tabs/BUILD.gn
index 6299bf2..5dfaf2c5 100644
--- a/ios/chrome/browser/ui/bring_android_tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/bring_android_tabs/BUILD.gn
@@ -26,13 +26,24 @@
 }
 
 source_set("bring_android_tabs_ui") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [ "bring_android_tabs_prompt_view_controller_delegate.h" ]
   deps = [
+    ":constants",
     "//base",
     "//ios/chrome/browser/shared/public/commands",
   ]
 }
 
+source_set("constants") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "constants.h",
+    "constants.mm",
+  ]
+  frameworks = [ "Foundation.framework" ]
+}
+
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
diff --git a/ios/chrome/browser/ui/bring_android_tabs/constants.h b/ios/chrome/browser/ui/bring_android_tabs/constants.h
new file mode 100644
index 0000000..67afece
--- /dev/null
+++ b/ios/chrome/browser/ui/bring_android_tabs/constants.h
@@ -0,0 +1,18 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_BRING_ANDROID_TABS_CONSTANTS_H_
+#define IOS_CHROME_BROWSER_UI_BRING_ANDROID_TABS_CONSTANTS_H_
+
+#import <Foundation/Foundation.h>
+
+// Accessibility identifier for the "Bring Android Tabs" confirmation alert
+// prompt view controller.
+extern NSString* const kBringAndroidTabsPromptConfirmationAlertAXId;
+
+// Accessibility identifier for the "Bring Android Tabs" bottom message prompt
+// view controller.
+extern NSString* const kBringAndroidTabsPromptBottomMessageAXId;
+
+#endif  // IOS_CHROME_BROWSER_UI_BRING_ANDROID_TABS_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/bring_android_tabs/constants.mm b/ios/chrome/browser/ui/bring_android_tabs/constants.mm
new file mode 100644
index 0000000..c15d52cc
--- /dev/null
+++ b/ios/chrome/browser/ui/bring_android_tabs/constants.mm
@@ -0,0 +1,15 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/bring_android_tabs/constants.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+NSString* const kBringAndroidTabsPromptConfirmationAlertAXId =
+    @"kBringAndroidTabsPromptConfirmationAlertAccessibilityIdentifier";
+
+NSString* const kBringAndroidTabsPromptBottomMessageAXId =
+    @"kBringAndroidTabsPromptBottomMessageAccessibilityIdentifier";
diff --git a/ios/chrome/browser/ui/menu/action_factory.h b/ios/chrome/browser/ui/menu/action_factory.h
index a3e7a42..88e2469b 100644
--- a/ios/chrome/browser/ui/menu/action_factory.h
+++ b/ios/chrome/browser/ui/menu/action_factory.h
@@ -91,8 +91,11 @@
 // Creates a UIAction instance for editing a bookmark.
 - (UIAction*)actionToEditBookmarkWithBlock:(ProceduralBlock)block;
 
-// Creates a UIAction instance for closing a tab.
-- (UIAction*)actionToCloseTabWithBlock:(ProceduralBlock)block;
+// Creates a UIAction instance for closing a regular tab.
+- (UIAction*)actionToCloseRegularTabWithBlock:(ProceduralBlock)block;
+
+// Creates a UIAction instance for closing a pinned tab.
+- (UIAction*)actionToClosePinnedTabWithBlock:(ProceduralBlock)block;
 
 // Creates a UIAction instance for saving an image.
 - (UIAction*)actionSaveImageWithBlock:(ProceduralBlock)block;
diff --git a/ios/chrome/browser/ui/menu/action_factory.mm b/ios/chrome/browser/ui/menu/action_factory.mm
index 530a0d13..1425dbc 100644
--- a/ios/chrome/browser/ui/menu/action_factory.mm
+++ b/ios/chrome/browser/ui/menu/action_factory.mm
@@ -234,16 +234,15 @@
                 block:block];
 }
 
-- (UIAction*)actionToCloseTabWithBlock:(ProceduralBlock)block {
-  UIImage* image =
-      DefaultSymbolWithPointSize(kXMarkSymbol, kSymbolActionPointSize);
-  UIAction* action = [self
-      actionWithTitle:l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_CLOSETAB)
-                image:image
-                 type:MenuActionType::CloseTab
-                block:block];
-  action.attributes = UIMenuElementAttributesDestructive;
-  return action;
+- (UIAction*)actionToCloseRegularTabWithBlock:(ProceduralBlock)block {
+  NSString* title = l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_CLOSETAB);
+  return [self actionToCloseTabWithTitle:title block:block];
+}
+
+- (UIAction*)actionToClosePinnedTabWithBlock:(ProceduralBlock)block {
+  NSString* title =
+      l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_CLOSEPINNEDTAB);
+  return [self actionToCloseTabWithTitle:title block:block];
 }
 
 - (UIAction*)actionSaveImageWithBlock:(ProceduralBlock)block {
@@ -328,4 +327,19 @@
   };
 }
 
+#pragma mark - Private
+
+// Creates a UIAction instance for closing a tab with a provided `title`.
+- (UIAction*)actionToCloseTabWithTitle:(NSString*)title
+                                 block:(ProceduralBlock)block {
+  UIImage* image =
+      DefaultSymbolWithPointSize(kXMarkSymbol, kSymbolActionPointSize);
+  UIAction* action = [self actionWithTitle:title
+                                     image:image
+                                      type:MenuActionType::CloseTab
+                                     block:block];
+  action.attributes = UIMenuElementAttributesDestructive;
+  return action;
+}
+
 @end
diff --git a/ios/chrome/browser/ui/menu/action_factory_unittest.mm b/ios/chrome/browser/ui/menu/action_factory_unittest.mm
index 0305ac2..94a8a74 100644
--- a/ios/chrome/browser/ui/menu/action_factory_unittest.mm
+++ b/ios/chrome/browser/ui/menu/action_factory_unittest.mm
@@ -83,8 +83,8 @@
   EXPECT_EQ(expectedImage, action.image);
 }
 
-// Tests that the close action has the right title and image.
-TEST_F(ActionFactoryTest, CloseAction) {
+// Tests that the close regular tab action has the right title and image.
+TEST_F(ActionFactoryTest, CloseRegularTabAction) {
   ActionFactory* factory =
       [[ActionFactory alloc] initWithScenario:kTestMenuScenario];
 
@@ -93,7 +93,24 @@
   NSString* expectedTitle =
       l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_CLOSETAB);
 
-  UIAction* action = [factory actionToCloseTabWithBlock:^{
+  UIAction* action = [factory actionToCloseRegularTabWithBlock:^{
+  }];
+
+  EXPECT_TRUE([expectedTitle isEqualToString:action.title]);
+  EXPECT_EQ(expectedImage, action.image);
+}
+
+// Tests that the close pinned tab action has the right title and image.
+TEST_F(ActionFactoryTest, ClosePinnedTabAction) {
+  ActionFactory* factory =
+      [[ActionFactory alloc] initWithScenario:kTestMenuScenario];
+
+  UIImage* expectedImage =
+      DefaultSymbolWithPointSize(kXMarkSymbol, kSymbolActionPointSize);
+  NSString* expectedTitle =
+      l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_CLOSEPINNEDTAB);
+
+  UIAction* action = [factory actionToClosePinnedTabWithBlock:^{
   }];
 
   EXPECT_TRUE([expectedTitle isEqualToString:action.title]);
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn
index 5b0a98b..d7850c3 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn
@@ -160,6 +160,7 @@
     "//ios/chrome/browser/passwords:store_factory",
     "//ios/chrome/browser/policy:test_support",
     "//ios/chrome/browser/prefs:pref_names",
+    "//ios/chrome/browser/promos_manager:test_support",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/shared/ui/util",
     "//ios/chrome/browser/ui/popup_menu:constants",
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator_unittest.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator_unittest.mm
index a789e58..214c343c 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator_unittest.mm
@@ -38,6 +38,7 @@
 #import "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
 #import "ios/chrome/browser/policy/enterprise_policy_test_helper.h"
 #import "ios/chrome/browser/prefs/pref_names.h"
+#import "ios/chrome/browser/promos_manager/mock_promos_manager.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/constants.h"
@@ -637,6 +638,39 @@
   EXPECT_FALSE(HasItem(kToolsMenuWhatsNewId, /*enabled=*/NO));
 }
 
+// This tests that crbug.com/1404673 does not regress. It isn't perfect, as
+// that bug was never reproduced, but it tests part of the issue.
+TEST_F(OverflowMenuMediatorTest, TestOpenWhatsNewDoesntCrashWithNoTracker) {
+  base::test::ScopedFeatureList feature_on;
+  feature_on.InitAndEnableFeature(kWhatsNewIOS);
+
+  // Create Mediator and DO NOT set the Tracker on it.
+  CreateMediator(/*is_incognito=*/NO);
+
+  std::unique_ptr<MockPromosManager> promos_manager =
+      std::make_unique<MockPromosManager>();
+  EXPECT_CALL(*promos_manager, DeregisterPromo(testing::_));
+  mediator_.promosManager = promos_manager.get();
+
+  // Force creation of the model.
+  [mediator_ overflowMenuModel];
+
+  // Find the What's New destination.
+  OverflowMenuDestination* whatsNewDestination;
+  for (OverflowMenuDestination* destination in mediator_.overflowMenuModel
+           .destinations) {
+    if (destination.accessibilityIdentifier == kToolsMenuWhatsNewId) {
+      whatsNewDestination = destination;
+      break;
+    }
+  }
+
+  EXPECT_NSNE(nil, whatsNewDestination);
+
+  // Call What's New Destination's handler, which should not crash.
+  whatsNewDestination.handler();
+}
+
 // Tests that the Settings destination is badged with an error dot and
 // positioned at at most kNewDestinationsInsertionIndex when there is an
 // eligible identity error that can be resolved from the Settings menu.
diff --git a/ios/chrome/browser/ui/settings/password/password_details/add_password_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/add_password_view_controller.mm
index 9e668ac..fd3712a 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/add_password_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/add_password_view_controller.mm
@@ -381,6 +381,14 @@
     didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
   TableViewModel* model = self.tableViewModel;
   NSInteger itemType = [model itemTypeForIndexPath:indexPath];
+  if (itemType == ItemTypeNote) {
+    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
+    TableViewMultiLineTextEditCell* textFieldCell =
+        base::mac::ObjCCastStrict<TableViewMultiLineTextEditCell>(cell);
+    [textFieldCell.textView becomeFirstResponder];
+    return;
+  }
+
   if (itemType != ItemTypeDuplicateCredentialButton) {
     return;
   }
@@ -406,7 +414,8 @@
 - (BOOL)tableView:(UITableView*)tableView
     shouldHighlightRowAtIndexPath:(NSIndexPath*)indexPath {
   NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
-  return itemType == ItemTypeDuplicateCredentialButton;
+  return itemType == ItemTypeDuplicateCredentialButton ||
+         itemType == ItemTypeNote;
 }
 
 - (CGFloat)tableView:(UITableView*)tableView
@@ -470,10 +479,14 @@
       textFieldCell.textField.delegate = self;
       break;
     }
-    case ItemTypeDuplicateCredentialButton:
+    case ItemTypeDuplicateCredentialButton: {
       cell.selectionStyle = UITableViewCellSelectionStyleNone;
       break;
-    case ItemTypeNote:
+    }
+    case ItemTypeNote: {
+      cell.selectionStyle = UITableViewCellSelectionStyleNone;
+      break;
+    }
     case ItemTypeDuplicateCredentialMessage:
     case ItemTypeFooter:
       break;
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
index 58f974f..8527b7f 100644
--- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
@@ -498,6 +498,13 @@
         [self.applicationCommandsHandler closeSettingsUIAndOpenURL:command];
       }
       break;
+    case PasswordDetailsItemTypeNote: {
+      UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
+      TableViewMultiLineTextEditCell* textFieldCell =
+          base::mac::ObjCCastStrict<TableViewMultiLineTextEditCell>(cell);
+      [textFieldCell.textView becomeFirstResponder];
+      break;
+    }
     case PasswordDetailsItemTypeChangePasswordRecommendation:
     case PasswordDetailsItemTypeDeleteButton:
     case PasswordDetailsItemTypeMoveToAccountButton:
@@ -533,7 +540,8 @@
 
 - (BOOL)tableView:(UITableView*)tableView
     shouldHighlightRowAtIndexPath:(NSIndexPath*)indexPath {
-  return !self.editing;
+  NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
+  return !self.editing || itemType == PasswordDetailsItemTypeNote;
 }
 
 - (CGFloat)tableView:(UITableView*)tableView
@@ -610,7 +618,10 @@
       [cell setTag:indexPath.section];
       break;
     }
-    case PasswordDetailsItemTypeNote:
+    case PasswordDetailsItemTypeNote: {
+      cell.selectionStyle = UITableViewCellSelectionStyleNone;
+      break;
+    }
     case PasswordDetailsItemTypeNoteFooter:
     case PasswordDetailsItemTypeWebsite:
     case PasswordDetailsItemTypeFederation:
diff --git a/ios/chrome/browser/ui/settings/password/password_issues/BUILD.gn b/ios/chrome/browser/ui/settings/password/password_issues/BUILD.gn
index 5e35f5b..a39ef7a 100644
--- a/ios/chrome/browser/ui/settings/password/password_issues/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/password/password_issues/BUILD.gn
@@ -72,6 +72,7 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
+    "password_issue_unittest.mm",
     "password_issues_mediator_unittest.mm",
     "password_issues_table_view_controller_unittest.mm",
   ]
diff --git a/ios/chrome/browser/ui/settings/password/password_issues/password_issue.mm b/ios/chrome/browser/ui/settings/password/password_issues/password_issue.mm
index 5a5bda9..886ee71 100644
--- a/ios/chrome/browser/ui/settings/password/password_issues/password_issue.mm
+++ b/ios/chrome/browser/ui/settings/password/password_issues/password_issue.mm
@@ -41,8 +41,11 @@
 - (NSString*)compromisedDescription {
   if (_compromisedDescriptionEnabled) {
     if (_credential.IsLeaked()) {
-      return l10n_util::GetNSString(
-          IDS_IOS_COMPROMISED_PASSWORD_ISSUES_LEAKED_DESCRIPTION);
+      return _credential.IsPhished()
+                 ? l10n_util::GetNSString(
+                       IDS_IOS_COMPROMISED_PASSWORD_ISSUES_PHISHED_AND_LEAKED_DESCRIPTION)
+                 : l10n_util::GetNSString(
+                       IDS_IOS_COMPROMISED_PASSWORD_ISSUES_LEAKED_DESCRIPTION);
     }
 
     if (_credential.IsPhished()) {
diff --git a/ios/chrome/browser/ui/settings/password/password_issues/password_issue_unittest.mm b/ios/chrome/browser/ui/settings/password/password_issues/password_issue_unittest.mm
new file mode 100644
index 0000000..3f2356a
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_issues/password_issue_unittest.mm
@@ -0,0 +1,96 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/settings/password/password_issues/password_issue.h"
+
+#import "components/password_manager/core/browser/password_form.h"
+#import "components/password_manager/core/browser/ui/credential_ui_entry.h"
+#import "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#import "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+using PasswordIssueTest = PlatformTest;
+
+using password_manager::CredentialUIEntry;
+using password_manager::InsecureType;
+using password_manager::InsecurityMetadata;
+using password_manager::PasswordForm;
+
+namespace {
+
+// Creates a PasswordIssue for testing with the provided insecurity issues.
+// Pass `enable_compromised_description` as true if the compromised description
+// property should have a value for compromised credentials.
+PasswordIssue* MakeTestPasswordIssue(
+    const std::vector<InsecureType>& insecure_types,
+    bool enable_compromised_description) {
+  PasswordForm form;
+  form.signon_realm = "https://example.com";
+  form.username_value = u"user";
+  form.password_value = u"password";
+  form.password_issues = base::flat_map<InsecureType, InsecurityMetadata>();
+
+  for (auto insecure_type : insecure_types) {
+    form.password_issues[insecure_type] = InsecurityMetadata();
+  }
+
+  CredentialUIEntry entry = CredentialUIEntry(form);
+
+  return
+      [[PasswordIssue alloc] initWithCredential:entry
+                   enableCompromisedDescription:enable_compromised_description];
+}
+
+}  // namespace
+
+// Verifies the compromised description property for leaked passwords.
+TEST_F(PasswordIssueTest, TestLeakedCompromisedDescription) {
+  PasswordIssue* issue = MakeTestPasswordIssue({InsecureType::kLeaked}, true);
+
+  EXPECT_NSEQ(issue.compromisedDescription, @"Found in data breach");
+}
+
+// Verifies the compromised description property for phished passwords.
+TEST_F(PasswordIssueTest, TestPhishedCompromisedDescription) {
+  PasswordIssue* issue = MakeTestPasswordIssue({InsecureType::kPhished}, true);
+
+  EXPECT_NSEQ(issue.compromisedDescription, @"Entered on deceptive site");
+}
+
+// Verifies the compromised description property for passwords that were leaked
+// and phished.
+TEST_F(PasswordIssueTest, TestLeakedAndPhishedCompromisedDescription) {
+  PasswordIssue* issue = MakeTestPasswordIssue(
+      {InsecureType::kPhished, InsecureType::kLeaked}, true);
+
+  EXPECT_NSEQ(issue.compromisedDescription,
+              @"Entered on a deceptive site and found in a data breach");
+}
+
+// Verifies the compromised description property doesn't have value when
+// disabled.
+TEST_F(PasswordIssueTest, TestDisabledCompromisedDescription) {
+  PasswordIssue* issue = MakeTestPasswordIssue(
+      {InsecureType::kPhished, InsecureType::kLeaked}, false);
+
+  EXPECT_FALSE(issue.compromisedDescription);
+}
+
+// Verifies the compromised description property doesn't have value for non
+// compromised passwords.
+TEST_F(PasswordIssueTest,
+       TestCompromisedDescriptionForNonCompromisedPasswords) {
+  PasswordIssue* password_without_issues = MakeTestPasswordIssue({}, true);
+
+  EXPECT_FALSE(password_without_issues.compromisedDescription);
+
+  PasswordIssue* password_with_other_insecurity_types =
+      MakeTestPasswordIssue({InsecureType::kWeak, InsecureType::kReused}, true);
+
+  EXPECT_FALSE(password_with_other_insecurity_types.compromisedDescription);
+}
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_cell.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_cell.mm
index 90b3589..01c9f26 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_cell.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_cell.mm
@@ -92,12 +92,18 @@
 @end
 
 @implementation PinnedCell {
+  // Container for the title label.
+  UIView* _titleLabelContainer;
   // Container for the `_faviconView`.
   UIView* _faviconContainerView;
   // View for displaying the favicon.
   UIImageView* _faviconView;
   // Activity Indicator view that animates while WebState is loading.
   MDCActivityIndicator* _activityIndicator;
+  // Title label's leading constraint.
+  NSLayoutConstraint* _titleLabelLeadingConstraint;
+  // Title label's trailing constraint.
+  NSLayoutConstraint* _titleLabelTrailingConstraint;
   // Title label's fader leading constraint.
   NSLayoutConstraint* _titleLabelFaderLeadingConstraint;
   // Title label's fader trailing constraint.
@@ -181,9 +187,14 @@
 }
 
 - (void)setTitle:(NSString*)title {
+  NSTextAlignment titleTextAligment =
+      [self determineBestAlignmentForText:title];
+
   _titleLabel.text = [title copy];
+  _titleLabel.textAlignment = titleTextAligment;
   self.accessibilityLabel = [title copy];
 
+  [self updateTitleLabelAppearance];
   [self updateTitleLabelFaderAppearance];
 }
 
@@ -380,28 +391,44 @@
 - (void)setupTitleLabel {
   UILabel* titleLabel = [[UILabel alloc] init];
   titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
-  titleLabel.lineBreakMode = NSLineBreakByClipping;
   titleLabel.adjustsFontForContentSizeCategory = YES;
   titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
   titleLabel.textColor =
       GetInterfaceStyleDarkColor([UIColor colorNamed:kTextPrimaryColor]);
 
-  [_headerView addSubview:titleLabel];
+  UIView* titleLabelContainer = [[UIView alloc] init];
+  titleLabelContainer.translatesAutoresizingMaskIntoConstraints = NO;
+  titleLabelContainer.clipsToBounds = YES;
+  [titleLabelContainer addSubview:titleLabel];
+
+  [_headerView addSubview:titleLabelContainer];
 
   [NSLayoutConstraint activateConstraints:@[
-    [titleLabel.leadingAnchor
+    [titleLabelContainer.heightAnchor
+        constraintLessThanOrEqualToAnchor:_headerView.heightAnchor],
+    [titleLabelContainer.centerYAnchor
+        constraintEqualToAnchor:_faviconContainerView.centerYAnchor],
+    [titleLabelContainer.leadingAnchor
         constraintEqualToAnchor:_faviconContainerView.trailingAnchor
                        constant:kPinnedCellTitleLeadingPadding],
-    [titleLabel.trailingAnchor
+    [titleLabelContainer.trailingAnchor
         constraintEqualToAnchor:_headerView.trailingAnchor
                        constant:-kPinnedCellHorizontalPadding],
-    [titleLabel.heightAnchor
-        constraintLessThanOrEqualToAnchor:_headerView.heightAnchor],
-    [titleLabel.centerYAnchor
-        constraintEqualToAnchor:_faviconContainerView.centerYAnchor],
+    [titleLabelContainer.heightAnchor
+        constraintEqualToAnchor:titleLabel.heightAnchor],
+    [titleLabelContainer.centerYAnchor
+        constraintEqualToAnchor:titleLabel.centerYAnchor]
   ]];
 
+  _titleLabelLeadingConstraint = [titleLabelContainer.leadingAnchor
+      constraintEqualToAnchor:titleLabel.leadingAnchor];
+  _titleLabelTrailingConstraint = [titleLabelContainer.trailingAnchor
+      constraintEqualToAnchor:titleLabel.trailingAnchor];
+
+  _titleLabelContainer = titleLabelContainer;
   _titleLabel = titleLabel;
+
+  [self updateTitleLabelAppearance];
 }
 
 // Sets up the gradient view that fades out the title label.
@@ -424,25 +451,47 @@
     [gradientView.widthAnchor
         constraintEqualToConstant:kPinnedCellFaderGradientWidth],
     [gradientView.heightAnchor
-        constraintEqualToAnchor:_titleLabel.heightAnchor],
+        constraintEqualToAnchor:_titleLabelContainer.heightAnchor],
     [gradientView.centerYAnchor
-        constraintEqualToAnchor:_titleLabel.centerYAnchor],
+        constraintEqualToAnchor:_titleLabelContainer.centerYAnchor],
   ]];
 
   _titleLabelFaderLeadingConstraint = [gradientView.leadingAnchor
-      constraintEqualToAnchor:_titleLabel.leadingAnchor];
+      constraintEqualToAnchor:_titleLabelContainer.leadingAnchor];
   _titleLabelFaderTrailingConstraint = [gradientView.trailingAnchor
-      constraintEqualToAnchor:_titleLabel.trailingAnchor];
+      constraintEqualToAnchor:_titleLabelContainer.trailingAnchor];
 
   _titleLabelFader = gradientView;
 
   [self updateTitleLabelFaderAppearance];
 }
 
+- (void)updateTitleLabelAppearance {
+  NSTextAlignment titleTextAligment = _titleLabel.textAlignment;
+
+  if (UseRTLLayout()) {
+    if (titleTextAligment == NSTextAlignmentLeft) {
+      _titleLabelLeadingConstraint.active = NO;
+      _titleLabelTrailingConstraint.active = YES;
+    } else {
+      _titleLabelTrailingConstraint.active = NO;
+      _titleLabelLeadingConstraint.active = YES;
+    }
+  } else {
+    if (titleTextAligment == NSTextAlignmentLeft) {
+      _titleLabelTrailingConstraint.active = NO;
+      _titleLabelLeadingConstraint.active = YES;
+    } else {
+      _titleLabelLeadingConstraint.active = NO;
+      _titleLabelTrailingConstraint.active = YES;
+    }
+  }
+}
+
 // Updates the position and direction of the gradient view that fades out the
 // title label.
 - (void)updateTitleLabelFaderAppearance {
-  NSTextAlignment titleTextAligment = [self determineTitleTextAlignment];
+  NSTextAlignment titleTextAligment = _titleLabel.textAlignment;
 
   if (UseRTLLayout()) {
     if (titleTextAligment == NSTextAlignmentLeft) {
@@ -467,13 +516,8 @@
   }
 }
 
-// Determines the aligment of the title text.
-- (NSTextAlignment)determineTitleTextAlignment {
-  return [self bestAlignmentForText:_titleLabel.text];
-}
-
-// Returns the aligment of the provided `text`.
-- (NSTextAlignment)bestAlignmentForText:(NSString*)text {
+// Determines the best aligment for the provided `text`.
+- (NSTextAlignment)determineBestAlignmentForText:(NSString*)text {
   if (text.length) {
     NSString* lang = CFBridgingRelease(CFStringTokenizerCopyBestStringLanguage(
         (CFStringRef)text, CFRangeMake(0, text.length)));
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_context_menu_helper.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_context_menu_helper.mm
index daff9f2..ae1efb1 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_context_menu_helper.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_context_menu_helper.mm
@@ -169,12 +169,23 @@
                   }]];
   }
 
-  [menuElements addObject:[actionFactory actionToCloseTabWithBlock:^{
-                  [self.contextMenuDelegate
-                      closeTabWithIdentifier:cell.itemIdentifier
-                                   incognito:self.incognito
-                                      pinned:pinned];
-                }]];
+  UIAction* closeTabAction;
+  ProceduralBlock closeTabActionBlock = ^{
+    [self.contextMenuDelegate closeTabWithIdentifier:cell.itemIdentifier
+                                           incognito:self.incognito
+                                              pinned:pinned];
+  };
+
+  if (IsPinnedTabsEnabled() && !self.incognito && pinned) {
+    closeTabAction =
+        [actionFactory actionToClosePinnedTabWithBlock:closeTabActionBlock];
+  } else {
+    closeTabAction =
+        [actionFactory actionToCloseRegularTabWithBlock:closeTabActionBlock];
+  }
+
+  [menuElements addObject:closeTabAction];
+
   return menuElements;
 }
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_bottom_toolbar.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_bottom_toolbar.mm
index 9c19a80a..5766f2f5 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_bottom_toolbar.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_bottom_toolbar.mm
@@ -336,7 +336,7 @@
     // When a11y font size is used, long press on UIBarButtonItem will show a
     // built-in a11y modal panel with image and title if set. The size is not
     // taken into account.
-    if (base::FeatureList::IsEnabled(kSFSymbolsFollowup)) {
+    if (base::FeatureList::IsEnabled(kSFSymbolsFollowUp)) {
       _newTabButtonItem.image =
           CustomSymbolWithPointSize(kPlusCircleFillSymbol, 0);
     } else {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_new_tab_button.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_new_tab_button.mm
index de97a0e1..83da581 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_new_tab_button.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_new_tab_button.mm
@@ -44,7 +44,7 @@
   self = [super initWithFrame:CGRectZero];
   if (self) {
     CGFloat symbolSize = largeSize ? kLargeSymbolSize : kSmallSymbolSize;
-    if (base::FeatureList::IsEnabled(kSFSymbolsFollowup)) {
+    if (base::FeatureList::IsEnabled(kSFSymbolsFollowUp)) {
       _symbol = CustomSymbolWithPointSize(kPlusCircleFillSymbol, symbolSize);
     } else {
       _symbol =
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_context_menu_helper.mm b/ios/chrome/browser/ui/tabs/tab_strip_context_menu_helper.mm
index 3fe25d5..92be9e2f 100644
--- a/ios/chrome/browser/ui/tabs/tab_strip_context_menu_helper.mm
+++ b/ios/chrome/browser/ui/tabs/tab_strip_context_menu_helper.mm
@@ -143,9 +143,21 @@
     }
   }
 
-  [menuElements addObject:[actionFactory actionToCloseTabWithBlock:^{
-                  [self.delegate closeTabWithIdentifier:identifier];
-                }]];
+  UIAction* closeTabAction;
+  ProceduralBlock closeTabActionBlock = ^{
+    [self.delegate closeTabWithIdentifier:identifier];
+  };
+
+  if (pinnedActionsAvailable && pinnedState) {
+    closeTabAction =
+        [actionFactory actionToClosePinnedTabWithBlock:closeTabActionBlock];
+  } else {
+    closeTabAction =
+        [actionFactory actionToCloseRegularTabWithBlock:closeTabActionBlock];
+  }
+
+  [menuElements addObject:closeTabAction];
+
   return menuElements;
 }
 
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
index 83f2c34b..99aca07 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
@@ -168,7 +168,7 @@
 - (ToolbarButton*)openNewTabButton {
   ToolbarButton* newTabButton;
   if (@available(iOS 15, *)) {
-    NSString* symbolName = base::FeatureList::IsEnabled(kSFSymbolsFollowup)
+    NSString* symbolName = base::FeatureList::IsEnabled(kSFSymbolsFollowUp)
                                ? kPlusCircleFillSymbol
                                : kLegacyPlusCircleFillSymbol;
     UIImage* image = SymbolWithPalette(
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
index ab7a070..92c1151 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-fd6c4a5da8489b93cb6f93090033e87b6959caea
\ No newline at end of file
+bec9ff4cd2e3d343059ccb31316cf56ef23ceaa2
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
index 46455ae8..2962c01 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-2979b378307418999955a7fa306bd513a9e06e10
\ No newline at end of file
+16ced8a87a3a5dc6f0f06ba09aa3b0e88dc5ca3a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index b6bcfb5..7e919b9 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-7e0574b7efb73ff540d116d65c627c5196644b64
\ No newline at end of file
+c53ba9cd614cc221c6c8663e7dbb265da8a5e664
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index cfbce2e..dcef59e9 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-d0ff713352443ab0705b845712bf7bcbb540e2a4
\ No newline at end of file
+c792b0c7395f75ea744741d422f85ca601679d7b
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index 5182391..1f73af4 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-786cca5237ffc3ec7f1b59d4e8d3296bae42eb49
\ No newline at end of file
+99f2d344e0ee7385cfc72ee20492e2463aed8e2a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index d79520f..bf95647 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-6d29e7f3bfa7506841b54488e116597802396ca1
\ No newline at end of file
+b3891c46b8cc91db72724b0df2f52b1c1867edc3
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
index 97235167..e0fed00 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-3a06841daa50499370a53d8fd8492c79a4bbcb0f
\ No newline at end of file
+c606cb1548fd94b6064e7bb8ab61baf6f5fda8c8
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
index 3ffda008..1660bf4b 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-4d959a7bc5a01d34e990e9b13be19179488bcf73
\ No newline at end of file
+51f8c31a8cb212ab873934cf3c9ab9cf2e574a5c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 6a66c2e1..2849e52 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-7ea6950f61f94c3038b6f701042e96aad7239b13
\ No newline at end of file
+20236c05ea46c9ceaad032f78bf6b241b26ac135
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index cf6e6db..663cce3 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-4ae1eb05aa9cd52e9ebe1a4726dd5f23d728d4d7
\ No newline at end of file
+96e0c4588db205d37e35a4541917aa40ee9ee1b1
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index b711442..9d1804a 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-763a94ed7adbee3b16da5daa3b03cca442ffb12d
\ No newline at end of file
+fdc3e9baaf547703262bf6235b2bc91b4bdd3671
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index 61fba1ce..1476c744c 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-cd39664e9b1086fffbf2b12964c88cabe453da1e
\ No newline at end of file
+cc8cb402e87d62daf7ab5f5738ef79514f7419b8
\ No newline at end of file
diff --git a/ios/web/content/BUILD.gn b/ios/web/content/BUILD.gn
index 7d79300d..036472c 100644
--- a/ios/web/content/BUILD.gn
+++ b/ios/web/content/BUILD.gn
@@ -23,6 +23,8 @@
     "navigation/content_navigation_manager.mm",
     "web_state/content_web_state.h",
     "web_state/content_web_state.mm",
+    "web_state/content_web_state_builder.h",
+    "web_state/content_web_state_builder.mm",
     "web_state/crc_web_view_proxy_impl.h",
     "web_state/crc_web_view_proxy_impl.mm",
   ]
diff --git a/ios/web/content/web_state/content_web_state.h b/ios/web/content/web_state/content_web_state.h
index 7ecac24..81fb373 100644
--- a/ios/web/content/web_state/content_web_state.h
+++ b/ios/web/content/web_state/content_web_state.h
@@ -38,6 +38,11 @@
 class ContentWebState : public WebState, public content::WebContentsObserver {
  public:
   explicit ContentWebState(const CreateParams& params);
+
+  // Constructor for ContentWebState created for deserialized sessions
+  ContentWebState(const CreateParams& params,
+                  CRWSessionStorage* session_storage);
+
   ~ContentWebState() override;
 
   // WebState implementation.
diff --git a/ios/web/content/web_state/content_web_state.mm b/ios/web/content/web_state/content_web_state.mm
index 0c3f131..3a2a5e0f 100644
--- a/ios/web/content/web_state/content_web_state.mm
+++ b/ios/web/content/web_state/content_web_state.mm
@@ -9,6 +9,7 @@
 #import "content/public/browser/web_contents.h"
 #import "ios/web/content/content_browser_context.h"
 #import "ios/web/content/navigation/content_navigation_context.h"
+#import "ios/web/content/web_state/content_web_state_builder.h"
 #import "ios/web/content/web_state/crc_web_view_proxy_impl.h"
 #import "ios/web/find_in_page/java_script_find_in_page_manager_impl.h"
 #import "ios/web/public/favicon/favicon_url.h"
@@ -65,7 +66,11 @@
 
 }  // namespace
 
-ContentWebState::ContentWebState(const CreateParams& params) {
+ContentWebState::ContentWebState(const CreateParams& params)
+    : ContentWebState(params, nil) {}
+
+ContentWebState::ContentWebState(const CreateParams& params,
+                                 CRWSessionStorage* session_storage) {
   content::BrowserContext* browser_context =
       ContentBrowserContext::FromBrowserState(params.browser_state);
   scoped_refptr<content::SiteInstance> site_instance;
@@ -100,7 +105,13 @@
   web::JavaScriptFindInPageManagerImpl::CreateForWebState(this);
   web::TextFragmentsManagerImpl::CreateForWebState(this);
 
-  UUID_ = [[NSUUID UUID] UUIDString];
+  if (session_storage) {
+    ExtractContentSessionStorage(this, controller, params.browser_state,
+                                 session_storage);
+    UUID_ = [session_storage.stableIdentifier copy];
+  } else {
+    UUID_ = [[[NSUUID UUID] UUIDString] copy];
+  }
 }
 
 ContentWebState::~ContentWebState() {
@@ -200,7 +211,7 @@
 }
 
 CRWSessionStorage* ContentWebState::BuildSessionStorage() {
-  return [[CRWSessionStorage alloc] init];
+  return BuildContentSessionStorage(this, navigation_manager_.get());
 }
 
 void ContentWebState::LoadData(NSData* data,
diff --git a/ios/web/content/web_state/content_web_state_builder.h b/ios/web/content/web_state/content_web_state_builder.h
new file mode 100644
index 0000000..e1a2caa
--- /dev/null
+++ b/ios/web/content/web_state/content_web_state_builder.h
@@ -0,0 +1,35 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_CONTENT_WEB_STATE_CONTENT_WEB_STATE_BUILDER_H_
+#define IOS_WEB_CONTENT_WEB_STATE_CONTENT_WEB_STATE_BUILDER_H_
+
+@class CRWSessionStorage;
+namespace content {
+class NavigationController;
+}
+namespace web {
+class BrowserState;
+class ContentNavigationManager;
+class ContentWebState;
+}  // namespace web
+
+namespace web {
+
+// Populates `web_state` and its `controller` with `session_storage`'s
+// session information.
+void ExtractContentSessionStorage(ContentWebState* web_state,
+                                  content::NavigationController* controller,
+                                  web::BrowserState* browser_state,
+                                  CRWSessionStorage* session_storage);
+
+// Creates a serializable session storage from `web_state` and
+// `navigation_manager`.
+CRWSessionStorage* BuildContentSessionStorage(
+    ContentWebState* web_state,
+    ContentNavigationManager* navigation_manager);
+
+}  // namespace web
+
+#endif  // IOS_WEB_CONTENT_WEB_STATE_CONTENT_WEB_STATE_BUILDER_H_
diff --git a/ios/web/content/web_state/content_web_state_builder.mm b/ios/web/content/web_state/content_web_state_builder.mm
new file mode 100644
index 0000000..63c22bb
--- /dev/null
+++ b/ios/web/content/web_state/content_web_state_builder.mm
@@ -0,0 +1,155 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/web/content/web_state/content_web_state_builder.h"
+
+#import "base/strings/sys_string_conversions.h"
+#import "content/public/browser/navigation_controller.h"
+#import "content/public/browser/navigation_entry.h"
+#import "content/public/browser/restore_type.h"
+#import "ios/web/content/content_browser_context.h"
+#import "ios/web/content/web_state/content_web_state.h"
+#import "ios/web/public/navigation/navigation_item.h"
+#import "ios/web/public/session/crw_navigation_item_storage.h"
+#import "ios/web/public/session/crw_session_certificate_policy_cache_storage.h"
+#import "ios/web/public/session/crw_session_storage.h"
+#import "ios/web/public/session/serializable_user_data_manager.h"
+#import "net/http/http_util.h"
+#import "services/network/public/cpp/shared_url_loader_factory.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace web {
+
+void ExtractContentSessionStorage(ContentWebState* web_state,
+                                  content::NavigationController* controller,
+                                  web::BrowserState* browser_state,
+                                  CRWSessionStorage* session_storage) {
+  web_state->SetHasOpener(session_storage.hasOpener);
+  NSArray<CRWNavigationItemStorage*>* item_storages =
+      session_storage.itemStorages;
+  std::vector<std::unique_ptr<content::NavigationEntry>> items(
+      item_storages.count);
+
+  content::BrowserContext* browser_context =
+      ContentBrowserContext::FromBrowserState(browser_state);
+
+  for (size_t index = 0; index < item_storages.count; ++index) {
+    CRWNavigationItemStorage* navigation_item_storage = item_storages[index];
+    std::unique_ptr<content::NavigationEntry> new_entry =
+        content::NavigationController::CreateNavigationEntry(
+            navigation_item_storage.virtualURL, content::Referrer(),
+            /* initiator_origin= */ absl::nullopt,
+            /* initiator_base_url= */ absl::nullopt, ui::PAGE_TRANSITION_RELOAD,
+            /* is_renderer_initiated= */ false, std::string(), browser_context,
+            /* blob_url_loader_factory= */ nullptr);
+    new_entry->SetOriginalRequestURL(navigation_item_storage.URL);
+    if (navigation_item_storage.URL.SchemeIsHTTPOrHTTPS()) {
+      new_entry->SetURL(navigation_item_storage.URL);
+      new_entry->SetVirtualURL(navigation_item_storage.virtualURL);
+    } else {
+      new_entry->SetURL(navigation_item_storage.virtualURL);
+    }
+    new_entry->SetTimestamp(navigation_item_storage.timestamp);
+    new_entry->SetTitle(navigation_item_storage.title);
+    new_entry->SetTransitionType(ui::PAGE_TRANSITION_RELOAD);
+    std::ostringstream ss;
+    for (id key in navigation_item_storage.HTTPRequestHeaders) {
+      auto key_utf8 = base::SysNSStringToUTF8(key);
+      auto value_utf8 = base::SysNSStringToUTF8(
+          [navigation_item_storage.HTTPRequestHeaders objectForKey:key]);
+      if (!net::HttpUtil::IsValidHeaderName(key_utf8) ||
+          !net::HttpUtil::IsValidHeaderValue(value_utf8)) {
+        continue;
+      }
+      ss << key_utf8 << ": " << value_utf8 << "\n";
+    }
+    if (!ss.str().empty()) {
+      new_entry->AddExtraHeaders(ss.str());
+    }
+
+    GURL url = new_entry->GetURL();
+    if (web::BrowserURLRewriter::GetInstance()->RewriteURLIfNecessary(
+            &url, browser_state)) {
+      GURL virtual_url = new_entry->GetURL();
+      new_entry->SetURL(url);
+      new_entry->SetVirtualURL(virtual_url);
+    }
+
+    items[index] = std::move(new_entry);
+  }
+  controller->Restore(session_storage.lastCommittedItemIndex,
+                      content::RestoreType::kRestored, &items);
+
+  SerializableUserDataManager::FromWebState(web_state)->SetUserDataFromSession(
+      session_storage.userData);
+}
+
+CRWSessionStorage* BuildContentSessionStorage(
+    ContentWebState* web_state,
+    ContentNavigationManager* navigation_manager) {
+  CRWSessionStorage* session_storage = [[CRWSessionStorage alloc] init];
+  session_storage.lastActiveTime = web_state->GetLastActiveTime();
+  session_storage.creationTime = web_state->GetCreationTime();
+  session_storage.stableIdentifier = web_state->GetStableIdentifier();
+  session_storage.hasOpener = web_state->HasOpener();
+  session_storage.lastCommittedItemIndex =
+      navigation_manager->GetLastCommittedItemIndex();
+  if (session_storage.lastCommittedItemIndex == -1) {
+    // This can happen when a session is saved during restoration. Instead,
+    // default to GetItemCount() - 1.
+    session_storage.lastCommittedItemIndex =
+        navigation_manager->GetItemCount() - 1;
+  }
+
+  NSMutableArray<CRWNavigationItemStorage*>* item_storages =
+      [[NSMutableArray alloc] init];
+  const size_t original_index = session_storage.lastCommittedItemIndex;
+  const size_t navigation_items =
+      static_cast<size_t>(navigation_manager->GetItemCount());
+
+  // Drop URLs larger than a certain threshold.
+  for (size_t index = 0; index < navigation_items; ++index) {
+    const NavigationItem* item = navigation_manager->GetItemAtIndex(index);
+    if (item->GetURL().spec().size() > url::kMaxURLChars) {
+      if (index <= original_index) {
+        session_storage.lastCommittedItemIndex--;
+      }
+      continue;
+    }
+
+    CRWNavigationItemStorage* storage = [[CRWNavigationItemStorage alloc] init];
+    storage.virtualURL = item->GetVirtualURL();
+    storage.URL = item->GetURL();
+    // Use default referrer if URL is longer than allowed. Navigation items with
+    // these long URLs will not be serialized, so there is no point in keeping
+    // referrer URL.
+    if (item->GetReferrer().url.spec().size() <= url::kMaxURLChars) {
+      storage.referrer = item->GetReferrer();
+    }
+    storage.timestamp = item->GetTimestamp();
+    storage.title = item->GetTitle();
+    storage.displayState = item->GetPageDisplayState();
+    storage.userAgentType = item->GetUserAgentType();
+    storage.HTTPRequestHeaders = item->GetHttpRequestHeaders();
+    [item_storages addObject:storage];
+  }
+  session_storage.itemStorages = item_storages;
+  session_storage.certPolicyCacheStorage =
+      [[CRWSessionCertificatePolicyCacheStorage alloc] init];
+  session_storage.certPolicyCacheStorage.certificateStorages =
+      [NSMutableSet set];
+  const SerializableUserDataManager* user_data_manager =
+      SerializableUserDataManager::FromWebState(web_state);
+  if (user_data_manager) {
+    session_storage.userData = user_data_manager->GetUserDataForSession();
+  }
+  session_storage.userAgentType = UserAgentType::AUTOMATIC;
+
+  return session_storage;
+}
+
+}  // namespace web
diff --git a/ios/web/web_state/web_state_factory.mm b/ios/web/web_state/web_state_factory.mm
index 106d089..a8f5465 100644
--- a/ios/web/web_state/web_state_factory.mm
+++ b/ios/web/web_state/web_state_factory.mm
@@ -34,7 +34,7 @@
     CRWSessionStorage* session_storage) {
   DCHECK(session_storage);
 #if BUILDFLAG(USE_BLINK)
-  return std::make_unique<ContentWebState>(params);
+  return std::make_unique<ContentWebState>(params, session_storage);
 #else
   return std::make_unique<WebStateImpl>(params, session_storage);
 #endif  // USE_BLINK
diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc
index 1efd1cf..45c62d6 100644
--- a/media/audio/pulse/audio_manager_pulse.cc
+++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -32,8 +32,6 @@
 constexpr int kDefaultInputBufferSize = 1024;
 constexpr int kDefaultSampleRate = 48000;
 constexpr int kDefaultChannelCount = 2;
-constexpr int kMinChannelCount = 1;
-constexpr int kMaxChannelCount = PA_CHANNELS_MAX;
 
 AudioManagerPulse::AudioManagerPulse(std::unique_ptr<AudioThread> audio_thread,
                                      AudioLogFactory* audio_log_factory,
@@ -45,8 +43,7 @@
       devices_(nullptr),
       native_input_sample_rate_(kDefaultSampleRate),
       native_channel_count_(kDefaultChannelCount),
-      output_sample_rate_(kDefaultSampleRate),
-      output_channel_count_(kDefaultChannelCount) {
+      default_source_is_monitor_(false) {
   DCHECK(input_mainloop_);
   DCHECK(input_context_);
   SetMaxOutputStreamsAllowed(kMaxOutputStreams);
@@ -214,40 +211,19 @@
 AudioParameters AudioManagerPulse::GetPreferredOutputStreamParameters(
     const std::string& output_device_id,
     const AudioParameters& input_params) {
+  // TODO(tommi): Support |output_device_id|.
+  VLOG_IF(0, !output_device_id.empty()) << "Not implemented!";
+
   int buffer_size = kMinimumOutputBufferSize;
 
   // Query native parameters where applicable; Pulse does not require these to
   // be respected though, so prefer the input parameters for channel count.
   UpdateNativeAudioHardwareInfo();
-  output_sample_rate_ = native_input_sample_rate_ ? native_input_sample_rate_
-                                                  : kDefaultSampleRate;
-  output_channel_count_ =
-      native_channel_count_ ? native_channel_count_ : kDefaultChannelCount;
-  {
-    AutoPulseLock auto_lock(input_mainloop_);
-    auto* operation = pa_context_get_sink_info_by_name(
-        input_context_,
-        (output_device_id.empty() ? default_sink_name_ : output_device_id)
-            .c_str(),
-        UpdateOutputInfoCallback, this);
-    WaitForOperationCompletion(input_mainloop_, operation, input_context_);
-  }
+  int sample_rate = native_input_sample_rate_ ? native_input_sample_rate_
+                                              : kDefaultSampleRate;
+  ChannelLayoutConfig channel_layout_config = ChannelLayoutConfig::Guess(
+      native_channel_count_ ? native_channel_count_ : 2);
 
-  if ((output_channel_count_ < kMinChannelCount) ||
-      (output_channel_count_ > kMaxChannelCount)) {
-    DLOG(WARNING) << "output_channel_count_ (" << output_channel_count_
-                  << ") is outside the valid range of [" << kMinChannelCount
-                  << "," << kMaxChannelCount << "], setting to default ("
-                  << kDefaultChannelCount << ").";
-    output_channel_count_ = kDefaultChannelCount;
-  }
-
-  auto channel_layout_config =
-      ChannelLayoutConfig::Guess(output_channel_count_);
-  if (channel_layout_config.channel_layout() == CHANNEL_LAYOUT_UNSUPPORTED) {
-    channel_layout_config =
-        ChannelLayoutConfig(CHANNEL_LAYOUT_DISCRETE, output_channel_count_);
-  }
   if (input_params.IsValid()) {
     // Use the system's output channel count for the DISCRETE layout. This is to
     // avoid a crash due to the lack of support on the multi-channel beyond 8 in
@@ -265,8 +241,7 @@
     buffer_size = user_buffer_size;
 
   return AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
-                         channel_layout_config, output_sample_rate_,
-                         buffer_size);
+                         channel_layout_config, sample_rate, buffer_size);
 }
 
 AudioOutputStream* AudioManagerPulse::MakeOutputStream(
@@ -344,22 +319,6 @@
   manager->devices_->push_back(AudioDeviceName(info->description, info->name));
 }
 
-void AudioManagerPulse::UpdateOutputInfoCallback(pa_context* context,
-                                                 const pa_sink_info* info,
-                                                 int eol,
-                                                 void* user_data) {
-  AudioManagerPulse* manager = reinterpret_cast<AudioManagerPulse*>(user_data);
-
-  if (eol) {
-    // Signal the pulse object that it is done.
-    pa_threaded_mainloop_signal(manager->input_mainloop_, 0);
-    return;
-  }
-
-  manager->output_sample_rate_ = info->sample_spec.rate;
-  manager->output_channel_count_ = info->sample_spec.channels;
-}
-
 void AudioManagerPulse::AudioHardwareInfoCallback(pa_context* context,
                                                   const pa_server_info* info,
                                                   void* user_data) {
@@ -369,9 +328,6 @@
   manager->native_channel_count_ = info->sample_spec.channels;
   if (info->default_source_name)
     manager->default_source_name_ = info->default_source_name;
-  if (info->default_sink_name) {
-    manager->default_sink_name_ = info->default_sink_name;
-  }
   pa_threaded_mainloop_signal(manager->input_mainloop_, 0);
 }
 
diff --git a/media/audio/pulse/audio_manager_pulse.h b/media/audio/pulse/audio_manager_pulse.h
index 4df70d5..e8f7acd7 100644
--- a/media/audio/pulse/audio_manager_pulse.h
+++ b/media/audio/pulse/audio_manager_pulse.h
@@ -78,10 +78,6 @@
                                         const pa_sink_info* info,
                                         int eol,
                                         void* user_data);
-  static void UpdateOutputInfoCallback(pa_context* context,
-                                       const pa_sink_info* info,
-                                       int eol,
-                                       void* user_data);
 
   // Callback to get the native sample rate of PulseAudio, used by
   // UpdateNativeAudioHardwareInfo().
@@ -112,11 +108,8 @@
   raw_ptr<AudioDeviceNames> devices_;
   int native_input_sample_rate_;
   int native_channel_count_;
-  int output_sample_rate_;
-  int output_channel_count_;
   std::string default_source_name_;
-  std::string default_sink_name_;
-  bool default_source_is_monitor_ = false;
+  bool default_source_is_monitor_;
 };
 
 }  // namespace media
diff --git a/media/audio/pulse/pulse.sigs b/media/audio/pulse/pulse.sigs
index 5164af3d..2c55eac 100644
--- a/media/audio/pulse/pulse.sigs
+++ b/media/audio/pulse/pulse.sigs
@@ -24,7 +24,6 @@
 pa_operation* pa_context_get_source_info_by_name(pa_context* c, const char* name, pa_source_info_cb_t cb, void *userdata);
 pa_operation* pa_context_get_source_info_list(pa_context* c, pa_source_info_cb_t cb, void* userdata);
 pa_operation* pa_context_get_sink_info_list(pa_context* c, pa_sink_info_cb_t cb, void* userdata);
-pa_operation* pa_context_get_sink_info_by_name(pa_context* c, const char* name, pa_sink_info_cb_t cb, void* userdata);
 pa_context_state_t pa_context_get_state(const_pa_context_ptr c);
 pa_context* pa_context_new(pa_mainloop_api* mainloop, const char* name);
 pa_operation* pa_context_set_source_volume_by_index(pa_context* c, uint32_t idx, const pa_cvolume* volume, pa_context_success_cb_t cb, void* userdata);
diff --git a/media/capture/video/chromeos/mojom/camera3.mojom b/media/capture/video/chromeos/mojom/camera3.mojom
index 1a81d203..bf10128 100644
--- a/media/capture/video/chromeos/mojom/camera3.mojom
+++ b/media/capture/video/chromeos/mojom/camera3.mojom
@@ -55,8 +55,7 @@
 enum Camera3StreamType {
   CAMERA3_STREAM_OUTPUT = 0,
   CAMERA3_STREAM_INPUT = 1,
-  CAMERA3_STREAM_BIDIRECTIONAL = 2,
-  CAMERA3_NUM_STREAM_TYPES,
+  CAMERA3_STREAM_BIDIRECTIONAL = 2
 };
 
 enum Camera3StreamRotation {
@@ -129,16 +128,14 @@
 
 enum Camera3MsgType {
   CAMERA3_MSG_ERROR = 1,
-  CAMERA3_MSG_SHUTTER = 2,
-  CAMERA3_NUM_MESSAGES,
+  CAMERA3_MSG_SHUTTER = 2
 };
 
 enum Camera3ErrorMsgCode {
   CAMERA3_MSG_ERROR_DEVICE = 1,
   CAMERA3_MSG_ERROR_REQUEST = 2,
   CAMERA3_MSG_ERROR_RESULT = 3,
-  CAMERA3_MSG_ERROR_BUFFER = 4,
-  CAMERA3_MSG_NUM_ERRORS,
+  CAMERA3_MSG_ERROR_BUFFER = 4
 };
 
 struct Camera3ErrorMsg {
@@ -168,8 +165,7 @@
   CAMERA3_BUF_REQ_FAILED_PARTIAL = 1,
   CAMERA3_BUF_REQ_FAILED_CONFIGURING = 2,
   CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS = 3,
-  CAMERA3_BUF_REQ_FAILED_UNKNOWN = 4,
-  CAMERA3_BUF_REQ_NUM_STATUS
+  CAMERA3_BUF_REQ_FAILED_UNKNOWN = 4
 };
 
 enum Camera3StreamBufferReqStatus {
@@ -177,8 +173,7 @@
   CAMERA3_PS_BUF_REQ_NO_BUFFER_AVAILABLE = 1,
   CAMERA3_PS_BUF_REQ_MAX_BUFFER_EXCEEDED = 2,
   CAMERA3_PS_BUF_REQ_STREAM_DISCONNECTED = 3,
-  CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR = 4,
-  CAMERA3_PS_BUF_REQ_NUM_STATUS
+  CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR = 4
 };
 
 struct Camera3BufferRequest {
diff --git a/media/filters/audio_decoder_unittest.cc b/media/filters/audio_decoder_unittest.cc
index e9c98b8..0f70fb1a 100644
--- a/media/filters/audio_decoder_unittest.cc
+++ b/media/filters/audio_decoder_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/hash/md5.h"
-#include "base/memory/raw_ptr_exclusion.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/sys_byteorder.h"
@@ -26,6 +25,7 @@
 #include "media/base/audio_hash.h"
 #include "media/base/decoder_buffer.h"
 #include "media/base/media_util.h"
+#include "media/base/supported_types.h"
 #include "media/base/test_data_util.h"
 #include "media/base/test_helpers.h"
 #include "media/base/timestamp_constants.h"
@@ -60,7 +60,7 @@
 namespace {
 
 // The number of packets to read and then decode from each file.
-const size_t kDecodeRuns = 3;
+constexpr size_t kDecodeRuns = 3;
 
 struct DecodedBufferExpectations {
   int64_t timestamp;
@@ -68,15 +68,16 @@
   const char* hash;
 };
 
+using DataExpectations = std::array<DecodedBufferExpectations, kDecodeRuns>;
+
 struct TestParams {
   AudioCodec codec;
   const char* filename;
-  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
-  // #global-scope
-  RAW_PTR_EXCLUSION const DecodedBufferExpectations* expectations;
+  DataExpectations expectations;
   int first_packet_pts;
   int samples_per_second;
   ChannelLayout channel_layout;
+  AudioCodecProfile profile = AudioCodecProfile::kUnknown;
 };
 
 // Tells gtest how to print our TestParams structure.
@@ -169,6 +170,13 @@
       return false;
     }
 #endif  // BUILDFLAG(IS_MAC)
+#if BUILDFLAG(IS_ANDROID)
+    if (decoder_type_ == AudioDecoderType::kMediaCodec &&
+        params_.profile == AudioCodecProfile::kXHE_AAC) {
+      return IsSupportedAudioType(
+          {AudioCodec::kAAC, AudioCodecProfile::kXHE_AAC, false});
+    }
+#endif
     return true;
   }
 
@@ -220,7 +228,8 @@
 #if BUILDFLAG(IS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS)
     // MediaCodec type requires config->extra_data() for AAC codec. For ADTS
     // streams we need to extract it with a separate procedure.
-    if (decoder_type_ == AudioDecoderType::kMediaCodec &&
+    if ((decoder_type_ == AudioDecoderType::kMediaCodec ||
+         decoder_type_ == AudioDecoderType::kMediaFoundation) &&
         params_.codec == AudioCodec::kAAC && config.extra_data().empty()) {
       int sample_rate;
       ChannelLayout channel_layout;
@@ -359,11 +368,13 @@
     buffer->ReadFrames(buffer->frame_count(), 0, 0, output.get());
 
     // Generate a lossy hash of the audio used for comparison across platforms.
-    AudioHash audio_hash;
-    audio_hash.Update(output.get(), output->frames());
-    EXPECT_TRUE(audio_hash.IsEquivalent(sample_info.hash, 0.03))
-        << "Audio hashes differ. Expected: " << sample_info.hash
-        << " Actual: " << audio_hash.ToString();
+    if (sample_info.hash) {
+      AudioHash audio_hash;
+      audio_hash.Update(output.get(), output->frames());
+      EXPECT_TRUE(audio_hash.IsEquivalent(sample_info.hash, 0.03))
+          << "Audio hashes differ. Expected: " << sample_info.hash
+          << " Actual: " << audio_hash.ToString();
+    }
 
     if (!exact_hash.empty()) {
       EXPECT_EQ(exact_hash, GetDecodedAudioMD5(i));
@@ -408,146 +419,179 @@
   base::TimeDelta start_timestamp_;
 };
 
-const DecodedBufferExpectations kBearOpusExpectations[] = {
+constexpr DataExpectations kBearOpusExpectations = {{
     {500, 3500, "-0.26,0.87,1.36,0.84,-0.30,-1.22,"},
     {4000, 10000, "0.09,0.23,0.21,0.03,-0.17,-0.24,"},
     {14000, 10000, "0.10,0.24,0.23,0.04,-0.14,-0.23,"},
-};
+}};
 
 // Test params to test decoder reinitialization. Choose opus because it is
 // supported on all platforms we test on.
-const TestParams kReinitializeTestParams = {
+constexpr TestParams kReinitializeTestParams = {
     AudioCodec::kOpus,    "bear-opus.ogg", kBearOpusExpectations, 24, 48000,
     CHANNEL_LAYOUT_STEREO};
 
 #if BUILDFLAG(IS_ANDROID)
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-const DecodedBufferExpectations kSfxAdtsMcExpectations[] = {
-    {0, 23219, "-1.80,-1.49,-0.23,1.11,1.54,-0.11,"},
-    {23219, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"},
-    {46439, 23219, "0.54,0.88,2.19,3.54,3.24,1.63,"},
-};
-
-const DecodedBufferExpectations kHeAacMcExpectations[] = {
-    {0, 42666, "-1.76,-0.12,1.72,1.45,0.10,-1.32,"},
-    {42666, 42666, "-1.78,-0.13,1.70,1.44,0.09,-1.32,"},
-    {85333, 42666, "-1.78,-0.13,1.70,1.44,0.08,-1.33,"},
-};
-#endif  // defined(USE_PROPRIETARY_CODECS)
-
-const TestParams kMediaCodecTestParams[] = {
+constexpr TestParams kMediaCodecTestParams[] = {
     {AudioCodec::kOpus, "bear-opus.ogg", kBearOpusExpectations, 24, 48000,
      CHANNEL_LAYOUT_STEREO},
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
-    {AudioCodec::kAAC, "sfx.adts", kSfxAdtsMcExpectations, 0, 44100,
+    {AudioCodec::kAAC,
+     "sfx.adts",
+     {{
+         {0, 23219, "-1.80,-1.49,-0.23,1.11,1.54,-0.11,"},
+         {23219, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"},
+         {46439, 23219, "0.54,0.88,2.19,3.54,3.24,1.63,"},
+     }},
+     0,
+     44100,
      CHANNEL_LAYOUT_MONO},
-    {AudioCodec::kAAC, "bear-audio-implicit-he-aac-v2.aac",
-     kHeAacMcExpectations, 0, 24000, CHANNEL_LAYOUT_MONO},
+    {AudioCodec::kAAC,
+     "bear-audio-implicit-he-aac-v2.aac",
+     {{
+         {0, 42666, "-1.76,-0.12,1.72,1.45,0.10,-1.32,"},
+         {42666, 42666, "-1.78,-0.13,1.70,1.44,0.09,-1.32,"},
+         {85333, 42666, "-1.78,-0.13,1.70,1.44,0.08,-1.33,"},
+     }},
+     0,
+     24000,
+     CHANNEL_LAYOUT_MONO},
 #endif  // defined(USE_PROPRIETARY_CODECS)
 };
-
 #endif  // BUILDFLAG(IS_ANDROID)
 
-#if BUILDFLAG(IS_MAC) && BUILDFLAG(USE_PROPRIETARY_CODECS)
-const DecodedBufferExpectations kNoiseXheAAcExpectations[] = {
-    {0, 42666, "6.09,2.44,-4.73,4.06,6.47,1.29,"},
-    {42666, 42666, "-5.16,0.94,3.14,2.52,5.26,-0.24,"},
-    {85333, 42666, "7.90,-0.09,-3.65,1.41,-4.26,-1.32,"},
+#if (BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)) && \
+    BUILDFLAG(USE_PROPRIETARY_CODECS)
+// Note: We don't test hashes for xHE-AAC content since the decoder is provided
+// by the operating system and will apply DRC based on device specific params.
+constexpr TestParams kXheAacTestParams[] = {
+    {AudioCodec::kAAC,
+     "noise-xhe-aac.mp4",
+     {{
+         {0, 42666, nullptr},
+         {42666, 42666, nullptr},
+         {85333, 42666, nullptr},
+     }},
+     0,
+     48000,
+     CHANNEL_LAYOUT_STEREO,
+     AudioCodecProfile::kXHE_AAC},
+    {AudioCodec::kAAC,
+     "noise-xhe-aac-mono.mp4",
+     {{
+         {0, 34829, nullptr},
+         {34829, 34829, nullptr},
+         {69659, 34829, nullptr},
+     }},
+     0,
+     29400,
+     CHANNEL_LAYOUT_MONO,
+     AudioCodecProfile::kXHE_AAC},
+    {AudioCodec::kAAC,
+     "noise-xhe-aac-44kHz.mp4",
+     {{
+         {0, 23219, nullptr},
+         {23219, 23219, nullptr},
+         {46439, 23219, nullptr},
+     }},
+     0,
+     44100,
+     CHANNEL_LAYOUT_STEREO,
+     AudioCodecProfile::kXHE_AAC},
 };
-const DecodedBufferExpectations kNoiseMonoXheAAcExpectations[] = {
-    {0, 34829, "-1.94,-1.64,-0.37,0.94,1.36,-0.26,"},
-    {34829, 34829, "-1.43,-1.14,0.13,1.43,1.86,0.24,"},
-    {69659, 34829, "-1.13,-0.84,0.42,1.71,2.14,0.53,"},
-};
+#endif  // (BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)) &&
+        // BUILDFLAG(USE_PROPRIETARY_CODECS)
 
-const TestParams kAudioToolboxTestParams[] = {
-    {AudioCodec::kAAC, "noise-xhe-aac.mp4", kNoiseXheAAcExpectations, 0, 48000,
-     CHANNEL_LAYOUT_STEREO},
-    {AudioCodec::kAAC, "noise-xhe-aac-mono.mp4", kNoiseMonoXheAAcExpectations,
-     0, 29400, CHANNEL_LAYOUT_MONO},
-};
-#endif  // BUILDFLAG(IS_MAC) && BUILDFLAG(USE_PROPRIETARY_CODECS)
-
-const DecodedBufferExpectations kSfxMp3Expectations[] = {
-    {0, 1065, "2.81,3.99,4.53,4.10,3.08,2.46,"},
-    {1065, 26122, "-3.81,-4.14,-3.90,-3.36,-3.03,-3.23,"},
-    {27188, 26122, "4.24,3.95,4.22,4.78,5.13,4.93,"},
-};
-
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-const DecodedBufferExpectations kSfxAdtsExpectations[] = {
-    {0, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"},
-    {23219, 23219, "0.54,0.88,2.19,3.54,3.24,1.63,"},
-    {46439, 23219, "1.42,1.69,2.95,4.23,4.02,2.36,"},
-};
-#endif
-
-const DecodedBufferExpectations kSfxFlacExpectations[] = {
+constexpr DataExpectations kSfxFlacExpectations = {{
     {0, 104489, "-2.42,-1.12,0.71,1.70,1.09,-0.68,"},
     {104489, 104489, "-1.99,-0.67,1.18,2.19,1.60,-0.16,"},
     {208979, 79433, "2.84,2.70,3.23,4.06,4.59,4.44,"},
-};
+}};
 
-const DecodedBufferExpectations kSfxWaveExpectations[] = {
-    {0, 23219, "-1.23,-0.87,0.47,1.85,1.88,0.29,"},
-    {23219, 23219, "0.75,1.10,2.43,3.78,3.53,1.93,"},
-    {46439, 23219, "1.27,1.56,2.83,4.13,3.87,2.23,"},
-};
-
-const DecodedBufferExpectations kFourChannelWaveExpectations[] = {
-    {0, 11609, "-1.68,1.68,0.89,-3.45,1.52,1.15,"},
-    {11609, 11609, "43.26,9.06,18.27,35.98,19.45,7.46,"},
-    {23219, 11609, "36.37,9.45,16.04,27.67,18.81,10.15,"},
-};
-
-const DecodedBufferExpectations kSfxOggExpectations[] = {
-    {0, 13061, "-0.33,1.25,2.86,3.26,2.09,0.14,"},
-    {13061, 23219, "-2.79,-2.42,-1.06,0.33,0.93,-0.64,"},
-    {36281, 23219, "-1.19,-0.80,0.57,1.97,2.08,0.51,"},
-};
-
-const DecodedBufferExpectations kBearOgvExpectations[] = {
-    {0, 13061, "-1.25,0.10,2.11,2.29,1.50,-0.68,"},
-    {13061, 23219, "-1.80,-1.41,-0.13,1.30,1.65,0.01,"},
-    {36281, 23219, "-1.43,-1.25,0.11,1.29,1.86,0.14,"},
-};
-
-#if defined(OPUS_FIXED_POINT)
-const DecodedBufferExpectations kSfxOpusExpectations[] = {
-    {0, 13500, "-2.70,-1.41,-0.78,-1.27,-2.56,-3.73,"},
-    {13500, 20000, "5.48,5.93,6.05,5.83,5.54,5.46,"},
-    {33500, 20000, "-3.44,-3.34,-3.57,-4.11,-4.74,-5.13,"},
-};
-#else
-const DecodedBufferExpectations kSfxOpusExpectations[] = {
-    {0, 13500, "-2.70,-1.41,-0.78,-1.27,-2.56,-3.73,"},
-    {13500, 20000, "5.48,5.93,6.04,5.83,5.54,5.45,"},
-    {33500, 20000, "-3.45,-3.35,-3.57,-4.12,-4.74,-5.14,"},
-};
-#endif
-
-const TestParams kFFmpegTestParams[] = {
-    {AudioCodec::kMP3, "sfx.mp3", kSfxMp3Expectations, 0, 44100,
+constexpr TestParams kFFmpegTestParams[] = {
+    {AudioCodec::kMP3,
+     "sfx.mp3",
+     {{
+         {0, 1065, "2.81,3.99,4.53,4.10,3.08,2.46,"},
+         {1065, 26122, "-3.81,-4.14,-3.90,-3.36,-3.03,-3.23,"},
+         {27188, 26122, "4.24,3.95,4.22,4.78,5.13,4.93,"},
+     }},
+     0,
+     44100,
      CHANNEL_LAYOUT_MONO},
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
-    {AudioCodec::kAAC, "sfx.adts", kSfxAdtsExpectations, 0, 44100,
+    {AudioCodec::kAAC,
+     "sfx.adts",
+     {{
+         {0, 23219, "-1.90,-1.53,-0.15,1.28,1.23,-0.33,"},
+         {23219, 23219, "0.54,0.88,2.19,3.54,3.24,1.63,"},
+         {46439, 23219, "1.42,1.69,2.95,4.23,4.02,2.36,"},
+     }},
+     0,
+     44100,
      CHANNEL_LAYOUT_MONO},
 #endif
     {AudioCodec::kFLAC, "sfx-flac.mp4", kSfxFlacExpectations, 0, 44100,
      CHANNEL_LAYOUT_MONO},
     {AudioCodec::kFLAC, "sfx.flac", kSfxFlacExpectations, 0, 44100,
      CHANNEL_LAYOUT_MONO},
-    {AudioCodec::kPCM, "sfx_f32le.wav", kSfxWaveExpectations, 0, 44100,
+    {AudioCodec::kPCM,
+     "sfx_f32le.wav",
+     {{
+         {0, 23219, "-1.23,-0.87,0.47,1.85,1.88,0.29,"},
+         {23219, 23219, "0.75,1.10,2.43,3.78,3.53,1.93,"},
+         {46439, 23219, "1.27,1.56,2.83,4.13,3.87,2.23,"},
+     }},
+     0,
+     44100,
      CHANNEL_LAYOUT_MONO},
-    {AudioCodec::kPCM, "4ch.wav", kFourChannelWaveExpectations, 0, 44100,
+    {AudioCodec::kPCM,
+     "4ch.wav",
+     {{
+         {0, 11609, "-1.68,1.68,0.89,-3.45,1.52,1.15,"},
+         {11609, 11609, "43.26,9.06,18.27,35.98,19.45,7.46,"},
+         {23219, 11609, "36.37,9.45,16.04,27.67,18.81,10.15,"},
+     }},
+     0,
+     44100,
      CHANNEL_LAYOUT_QUAD},
-    {AudioCodec::kVorbis, "sfx.ogg", kSfxOggExpectations, 0, 44100,
+    {AudioCodec::kVorbis,
+     "sfx.ogg",
+     {{
+         {0, 13061, "-0.33,1.25,2.86,3.26,2.09,0.14,"},
+         {13061, 23219, "-2.79,-2.42,-1.06,0.33,0.93,-0.64,"},
+         {36281, 23219, "-1.19,-0.80,0.57,1.97,2.08,0.51,"},
+     }},
+     0,
+     44100,
      CHANNEL_LAYOUT_MONO},
     // Note: bear.ogv is incorrectly muxed such that valid samples are given
     // negative timestamps, this marks them for discard per the ogg vorbis spec.
-    {AudioCodec::kVorbis, "bear.ogv", kBearOgvExpectations, -704, 44100,
+    {AudioCodec::kVorbis,
+     "bear.ogv",
+     {{
+         {0, 13061, "-1.25,0.10,2.11,2.29,1.50,-0.68,"},
+         {13061, 23219, "-1.80,-1.41,-0.13,1.30,1.65,0.01,"},
+         {36281, 23219, "-1.43,-1.25,0.11,1.29,1.86,0.14,"},
+     }},
+     -704,
+     44100,
      CHANNEL_LAYOUT_STEREO},
-    {AudioCodec::kOpus, "sfx-opus.ogg", kSfxOpusExpectations, -312, 48000,
+    {AudioCodec::kOpus,
+     "sfx-opus.ogg",
+     {{
+#if defined(OPUS_FIXED_POINT)
+         {0, 13500, "-2.70,-1.41,-0.78,-1.27,-2.56,-3.73,"},
+         {13500, 20000, "5.48,5.93,6.05,5.83,5.54,5.46,"},
+         {33500, 20000, "-3.44,-3.34,-3.57,-4.11,-4.74,-5.13,"},
+#else
+         {0, 13500, "-2.70,-1.41,-0.78,-1.27,-2.56,-3.73,"},
+         {13500, 20000, "5.48,5.93,6.04,5.83,5.54,5.45,"},
+         {33500, 20000, "-3.45,-3.35,-3.57,-4.12,-4.74,-5.14,"},
+#endif
+     }},
+     -312,
+     48000,
      CHANNEL_LAYOUT_MONO},
     {AudioCodec::kOpus, "bear-opus.ogg", kBearOpusExpectations, 24, 48000,
      CHANNEL_LAYOUT_STEREO},
@@ -557,11 +601,11 @@
 #if BUILDFLAG(IS_MAC) && BUILDFLAG(USE_PROPRIETARY_CODECS)
   // AudioToolbox only supports xHE-AAC, so we can't use the Opus params. We can
   // instead just swap between the two test parameter sets.
-  if (decoder_type_ == AudioDecoderType::kAudioToolbox) {
-    set_params(params_.channel_layout ==
-                       kAudioToolboxTestParams[0].channel_layout
-                   ? kAudioToolboxTestParams[1]
-                   : kAudioToolboxTestParams[0]);
+  if (decoder_type_ == AudioDecoderType::kAudioToolbox ||
+      decoder_type_ == AudioDecoderType::kMediaFoundation) {
+    set_params(params_.channel_layout == kXheAacTestParams[0].channel_layout
+                   ? kXheAacTestParams[1]
+                   : kXheAacTestParams[0]);
     return;
   }
 #endif
@@ -663,17 +707,28 @@
                                  ValuesIn(kFFmpegTestParams)));
 
 #if BUILDFLAG(IS_ANDROID)
+std::vector<TestParams> GetAndroidParams() {
+  std::vector<TestParams> params;
+  params.insert(params.end(), std::cbegin(kMediaCodecTestParams),
+                std::cend(kMediaCodecTestParams));
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+  params.insert(params.end(), std::cbegin(kXheAacTestParams),
+                std::cend(kXheAacTestParams));
+#endif
+  return params;
+}
+
 INSTANTIATE_TEST_SUITE_P(MediaCodec,
                          AudioDecoderTest,
                          Combine(Values(AudioDecoderType::kMediaCodec),
-                                 ValuesIn(kMediaCodecTestParams)));
-#endif  // BUILDFLAG(IS_ANDROID)
+                                 ValuesIn(GetAndroidParams())));
+#endif
 
-#if BUILDFLAG(IS_MAC) && BUILDFLAG(USE_PROPRIETARY_CODECS)
+#if BUILDFLAG(USE_PROPRIETARY_CODECS) && BUILDFLAG(IS_MAC)
 INSTANTIATE_TEST_SUITE_P(AudioToolbox,
                          AudioDecoderTest,
                          Combine(Values(AudioDecoderType::kAudioToolbox),
-                                 ValuesIn(kAudioToolboxTestParams)));
-#endif  // BUILDFLAG(IS_MAC) && BUILDFLAG(USE_PROPRIETARY_CODECS)
+                                 ValuesIn(kXheAacTestParams)));
+#endif
 
 }  // namespace media
diff --git a/media/test/data/README.md b/media/test/data/README.md
index 9e55d2b..2776dab 100644
--- a/media/test/data/README.md
+++ b/media/test/data/README.md
@@ -64,6 +64,7 @@
 ```
 ffmpeg -fflags nofillin -i noise_2ch_48khz_aot42_19_lufs_mp4.m4a -acodec copy -t 1 -movflags frag_keyframe+empty_moov+default_base_moof noise-xhe-aac.mp4
 ffmpeg -fflags nofillin -i noise_1ch_29_4khz_aot42_19_lufs_drc_config_change_mp4.m4a -acodec copy -t 1 -movflags frag_keyframe+empty_moov+default_base_moof noise-xhe-aac-mono.mp4
+ffmpeg -fflags nofillin -i noise_2ch_44_1khz_aot42_19_lufs_config_change_mp4.m4a -acodec copy -t 1 -movflags frag_keyframe+empty_moov+default_base_moof noise-xhe-aac-44kHz.mp4
 ```
 
 ### FLAC
diff --git a/media/test/data/noise-xhe-aac-44kHz.mp4 b/media/test/data/noise-xhe-aac-44kHz.mp4
new file mode 100644
index 0000000..58e80fb
--- /dev/null
+++ b/media/test/data/noise-xhe-aac-44kHz.mp4
Binary files differ
diff --git a/media/test/media_bundle_data.filelist b/media/test/media_bundle_data.filelist
index 546663cb..6a0e364 100644
--- a/media/test/media_bundle_data.filelist
+++ b/media/test/media_bundle_data.filelist
@@ -353,6 +353,7 @@
 data/negative_ts.flac
 data/no_audio_video.webm
 data/no_streams.webm
+data/noise-xhe-aac-44kHz.mp4
 data/noise-xhe-aac-mono.mp4
 data/noise-xhe-aac.mp4
 data/nonzero-start-time.webm
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc
index 0f01574..84bfe0e0 100644
--- a/media/test/pipeline_integration_test.cc
+++ b/media/test/pipeline_integration_test.cc
@@ -26,6 +26,7 @@
 #include "media/base/media_switches.h"
 #include "media/base/media_tracks.h"
 #include "media/base/mock_media_log.h"
+#include "media/base/supported_types.h"
 #include "media/base/test_data_util.h"
 #include "media/base/timestamp_constants.h"
 #include "media/cdm/aes_decryptor.h"
@@ -38,6 +39,10 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "url/gurl.h"
 
+#if BUILDFLAG(IS_ANDROID)
+#include "media/filters/android/media_codec_audio_decoder.h"
+#endif
+
 #if BUILDFLAG(IS_MAC)
 #include "media/filters/mac/audio_toolbox_audio_decoder.h"
 #endif
@@ -2096,20 +2101,28 @@
   // EXPECT_HASH_EQ("3.77,4.53,4.75,3.48,3.67,3.76,", GetAudioHash());
 }
 
-// TODO(crbug.com/1289825): Make this work on Android.
+#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
+std::unique_ptr<AudioDecoder> CreateXheAacDecoder(
+    scoped_refptr<base::SequencedTaskRunner> task_runner) {
 #if BUILDFLAG(IS_MAC)
-constexpr char kXHE_AACAudioHash[] = "34.02,8.92,-11.02,12.15,16.11,10.75,";
+  return std::make_unique<AudioToolboxAudioDecoder>();
+#elif BUILDFLAG(IS_ANDROID)
+  return std::make_unique<MediaCodecAudioDecoder>(task_runner);
+#else
+#error "xHE-AAC decoding is not supported on this platform.";
+#endif
+}
 
 TEST_F(PipelineIntegrationTest, BasicPlaybackXHE_AAC) {
-  if (__builtin_available(macOS 10.15, *)) {
-    // Annoyingly !__builtin_available() doesn't work.
-  } else {
+  if (!IsSupportedAudioType(
+          {AudioCodec::kAAC, AudioCodecProfile::kXHE_AAC, false})) {
     GTEST_SKIP() << "Unsupported platform.";
   }
 
-  auto prepend_audio_decoders_cb = base::BindLambdaForTesting([]() {
+  auto prepend_audio_decoders_cb = base::BindLambdaForTesting([this]() {
     std::vector<std::unique_ptr<AudioDecoder>> audio_decoders;
-    audio_decoders.push_back(std::make_unique<AudioToolboxAudioDecoder>());
+    audio_decoders.push_back(
+        CreateXheAacDecoder(task_environment_.GetMainThreadTaskRunner()));
     return audio_decoders;
   });
 
@@ -2119,24 +2132,24 @@
   Play();
   ASSERT_TRUE(WaitUntilOnEnded());
 
-  // Hash testing may be a poor choice here since we're using the OS decoders,
-  // but lets wait to see what the test says on Android before removing.
-  EXPECT_HASH_EQ(kXHE_AACAudioHash, GetAudioHash());
+  // Note: We don't test hashes for xHE-AAC content since the decoder is
+  // provided by the operating system and will apply DRC based on device
+  // specific params.
 
   // TODO(crbug.com/1289825): Seeking doesn't always work properly when using
   // ffmpeg since it doesn't handle non-keyframe xHE-AAC samples properly.
 }
 
 TEST_F(PipelineIntegrationTest, MSE_BasicPlaybackXHE_AAC) {
-  if (__builtin_available(macOS 10.15, *)) {
-    // Annoyingly !__builtin_available() doesn't work.
-  } else {
+  if (!IsSupportedAudioType(
+          {AudioCodec::kAAC, AudioCodecProfile::kXHE_AAC, false})) {
     GTEST_SKIP() << "Unsupported platform.";
   }
 
-  auto prepend_audio_decoders_cb = base::BindLambdaForTesting([]() {
+  auto prepend_audio_decoders_cb = base::BindLambdaForTesting([this]() {
     std::vector<std::unique_ptr<AudioDecoder>> audio_decoders;
-    audio_decoders.push_back(std::make_unique<AudioToolboxAudioDecoder>());
+    audio_decoders.push_back(
+        CreateXheAacDecoder(task_environment_.GetMainThreadTaskRunner()));
     return audio_decoders;
   });
 
@@ -2148,9 +2161,9 @@
   ASSERT_TRUE(WaitUntilOnEnded());
   Pause();
 
-  // Hash testing may be a poor choice here since we're using the OS decoders,
-  // but lets wait to see what the test says on Android before removing.
-  EXPECT_HASH_EQ(kXHE_AACAudioHash, GetAudioHash());
+  // Note: We don't test hashes for xHE-AAC content since the decoder is
+  // provided by the operating system and will apply DRC based on device
+  // specific params.
 
   // Seek to ensure a flushing and playback resumption works properly.
   auto seek_time = pipeline_->GetMediaDuration() / 2;
@@ -2160,7 +2173,7 @@
   Play();
   ASSERT_TRUE(WaitUntilOnEnded());
 }
-#endif  // BUILDFLAG(IS_MAC)
+#endif  // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID)
 
 TEST_F(PipelineIntegrationTest, BasicPlaybackHi10P) {
   ASSERT_EQ(PIPELINE_OK, Start("bear-320x180-hi10p.mp4"));
diff --git a/media/unit_tests_bundle_data.filelist b/media/unit_tests_bundle_data.filelist
index 57f446a..391c48e 100644
--- a/media/unit_tests_bundle_data.filelist
+++ b/media/unit_tests_bundle_data.filelist
@@ -350,6 +350,7 @@
 //media/test/data/negative_ts.flac
 //media/test/data/no_audio_video.webm
 //media/test/data/no_streams.webm
+//media/test/data/noise-xhe-aac-44kHz.mp4
 //media/test/data/noise-xhe-aac-mono.mp4
 //media/test/data/noise-xhe-aac.mp4
 //media/test/data/nonzero-start-time.webm
diff --git a/net/disk_cache/blockfile/block_files.cc b/net/disk_cache/blockfile/block_files.cc
index aefc8031..98f86cb 100644
--- a/net/disk_cache/blockfile/block_files.cc
+++ b/net/disk_cache/blockfile/block_files.cc
@@ -639,7 +639,6 @@
   if (file_size != expected) {
     int max_expected = header->entry_size * kMaxBlocks + file_header.Size();
     if (file_size < expected || header->empty[3] || file_size > max_expected) {
-      NOTREACHED();
       LOG(ERROR) << "Unexpected file size";
       return false;
     }
diff --git a/net/dns/dns_query.h b/net/dns/dns_query.h
index ec05a1e..5b66fdba 100644
--- a/net/dns/dns_query.h
+++ b/net/dns/dns_query.h
@@ -12,6 +12,7 @@
 #include <string>
 
 #include "base/containers/span.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
@@ -115,7 +116,9 @@
   scoped_refptr<IOBufferWithSize> io_buffer_;
 
   // Pointer to the dns header section.
-  dns_protocol::Header* header_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION dns_protocol::Header* header_ = nullptr;
 };
 
 }  // namespace net
diff --git a/net/dns/dns_udp_tracker.h b/net/dns/dns_udp_tracker.h
index 360c4f9f..d878f4b 100644
--- a/net/dns/dns_udp_tracker.h
+++ b/net/dns/dns_udp_tracker.h
@@ -41,7 +41,18 @@
   static constexpr size_t kRecognizedIdMismatchThreshold = 128;
 
   // Number of reuses of the same port required to set the |low_entropy_| flag.
-  static constexpr int kPortReuseThreshold = 2;
+  // Note: The original value of this parameter was 2, but it caused a problem
+  // on Windows (crbug.com/1413620). The low entropy checker in DnsUdpTracker
+  // was too sensitive and caused many TCP fallbacks. This happened because the
+  // dynamic port range for UDP on Windows is too small (only 16384 ports). This
+  // meant that there was a high probability (about 1%) of reusing the same port
+  // number three or more times out of 256 records. To avoid these unnecessary
+  // TCP fallbacks, the value was changed to 3. The probability of reusing the
+  // same port number to 4 or more times out of 256 records is 3.92566e-05. And
+  // if the available port count is 2048, the probability: 0.0182851. So it is
+  // likely to activate when getting into the low entropy.
+  // (See crrev.com/c/4374511 for the calculation).
+  static constexpr int kPortReuseThreshold = 3;
 
   DnsUdpTracker();
   ~DnsUdpTracker();
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 8fc1c92c..86ca725 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -26,6 +26,7 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/location.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/power_monitor/power_monitor.h"
@@ -2640,7 +2641,9 @@
   // can stop iterating kSpecialHeaders.
   //
   static const struct {
-    const HeaderNameAndValue* search;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #global-scope
+    RAW_PTR_EXCLUSION const HeaderNameAndValue* search;
     int load_flag;
   } kSpecialHeaders[] = {
     { kPassThroughHeaders, LOAD_DISABLE_CACHE },
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 690601d..b7ef641 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -15,6 +15,7 @@
 #include <string>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
@@ -632,7 +633,9 @@
   ValidationHeaders external_validation_;
   base::WeakPtr<HttpCache> cache_;
   raw_ptr<HttpCache::ActiveEntry, DanglingUntriaged> entry_ = nullptr;
-  HttpCache::ActiveEntry* new_entry_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION HttpCache::ActiveEntry* new_entry_ = nullptr;
   std::unique_ptr<HttpTransaction> network_trans_;
   CompletionOnceCallback callback_;  // Consumer's callback.
   HttpResponseInfo response_;
diff --git a/net/http/http_cache_writers_unittest.cc b/net/http/http_cache_writers_unittest.cc
index 4b43e5d..130d904 100644
--- a/net/http/http_cache_writers_unittest.cc
+++ b/net/http/http_cache_writers_unittest.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/functional/bind.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/run_loop.h"
 #include "crypto/secure_hash.h"
 #include "net/http/http_cache.h"
@@ -497,7 +498,9 @@
   ScopedMockTransaction scoped_transaction_;
   MockHttpCache cache_;
   std::unique_ptr<HttpCache::Writers> writers_;
-  disk_cache::Entry* disk_entry_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION disk_cache::Entry* disk_entry_ = nullptr;
   std::unique_ptr<HttpCache::ActiveEntry> entry_;
   TestHttpCache test_cache_;
 
diff --git a/net/http/transport_security_state_ct_policies.inc b/net/http/transport_security_state_ct_policies.inc
index d500ae5..4c94891 100644
--- a/net/http/transport_security_state_ct_policies.inc
+++ b/net/http/transport_security_state_ct_policies.inc
@@ -14,7 +14,8 @@
   // chains to or through one of the values contained in |roots|, which
   // contains the SHA-256 hash of the issuing CA's SubjectPublicKeyInfo,
   // the same format as HTTP Public Key Pinning.
-  const SHA256HashValue* roots;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for: #global-scope
+  RAW_PTR_EXCLUSION const SHA256HashValue* roots;
 
   // The number of entries in |roots|.
   size_t roots_length;
@@ -28,7 +29,8 @@
   // |exceptions|, which also contains the SHA-256 hashes of the
   // issuing CA's SubjectPublicKeyInfo, then even though it chained
   // through |roots|, it will be exempt from CT requirements.
-  const SHA256HashValue* exceptions;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for: #global-scope
+  RAW_PTR_EXCLUSION const SHA256HashValue* exceptions;
 
   // The number of entries in |exceptions|.
   size_t exceptions_length;
diff --git a/net/http/transport_security_state_source.h b/net/http/transport_security_state_source.h
index e9fd998..36e578a 100644
--- a/net/http/transport_security_state_source.h
+++ b/net/http/transport_security_state_source.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "base/memory/raw_ptr_exclusion.h"
 #include "net/base/net_export.h"
 
 namespace net {
@@ -17,8 +18,12 @@
 
 struct TransportSecurityStateSource {
   struct Pinset {
-    const char* const* const accepted_pins;
-    const char* const* const rejected_pins;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #global-scope
+    RAW_PTR_EXCLUSION const char* const* const accepted_pins;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #global-scope
+    RAW_PTR_EXCLUSION const char* const* const rejected_pins;
     const char* const report_uri;
   };
 
@@ -27,7 +32,9 @@
   const uint8_t* preloaded_data;
   size_t preloaded_bits;
   size_t root_position;
-  const Pinset* pinsets;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #global-scope
+  RAW_PTR_EXCLUSION const Pinset* pinsets;
   size_t pinsets_count;
 };
 
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
index 71ec9a2..a8f1ca5 100644
--- a/net/http/transport_security_state_unittest.cc
+++ b/net/http/transport_security_state_unittest.cc
@@ -848,6 +848,8 @@
       cert1.get(), cert2.get(), pkp_state.spki_hashes));
   EXPECT_EQ(network_anonymization_key,
             mock_report_sender.latest_network_anonymization_key());
+
+  state.SetReportSender(nullptr);
 }
 
 // Tests that report URIs are thrown out if they point to the same host,
@@ -905,6 +907,8 @@
   EXPECT_EQ(http_report_uri, mock_report_sender.latest_report_uri());
   EXPECT_EQ(network_anonymization_key,
             mock_report_sender.latest_network_anonymization_key());
+
+  state.SetReportSender(nullptr);
 }
 
 // Simple test for the HSTS preload process. The trie (generated from
@@ -2073,6 +2077,8 @@
   EXPECT_EQ(std::string(), mock_report_sender.latest_report());
   EXPECT_EQ(NetworkAnonymizationKey(),
             mock_report_sender.latest_network_anonymization_key());
+
+  state.SetReportSender(nullptr);
 }
 
 TEST_F(TransportSecurityStateStaticTest, HPKPReporting) {
@@ -2187,6 +2193,8 @@
                                           good_hashes));
   EXPECT_EQ(network_anonymization_key,
             mock_report_sender.latest_network_anonymization_key());
+
+  state.SetReportSender(nullptr);
 }
 
 TEST_F(TransportSecurityStateTest, WriteSizeDecodeSize) {
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index e3cba1b..6641224 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -20,6 +20,7 @@
 
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
 #include "base/strings/string_piece.h"
@@ -366,7 +367,10 @@
     // is asynchronous, i.e. it returned quic::QUIC_PENDING, and remains valid
     // until |OnRendezvouResult()| fires or |push_handle_->Cancel()| is
     // invoked.
-    quic::QuicClientPushPromiseIndex::TryHandle* push_handle_ = nullptr;
+    // This field is not a raw_ptr<> because it was filtered by the rewriter
+    // for: #addr-of
+    RAW_PTR_EXCLUSION quic::QuicClientPushPromiseIndex::TryHandle*
+        push_handle_ = nullptr;
     CompletionOnceCallback push_callback_;
     std::unique_ptr<QuicChromiumClientStream::Handle> push_stream_;
 
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 774b13d8..a9faee0d 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -15,6 +15,7 @@
 #include "base/location.h"
 #include "base/memory/memory_pressure_monitor.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -577,7 +578,9 @@
   bool host_resolution_finished_ = false;
   bool quic_session_created_ = false;
   bool connection_retried_ = false;
-  QuicChromiumClientSession* session_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION QuicChromiumClientSession* session_ = nullptr;
   HostResolverEndpointResult endpoint_result_;
   // If connection migraiton is supported, |network_| denotes the network on
   // which |session_| is created.
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index a6cacee..cf8115e 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -20,6 +20,7 @@
 #include "base/functional/callback.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
@@ -449,7 +450,9 @@
   void Reset() override;
 
   StaticSocketDataHelper helper_;
-  SocketDataPrinter* printer_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION SocketDataPrinter* printer_ = nullptr;
   bool paused_ = false;
 };
 
@@ -492,7 +495,9 @@
   SSLInfo ssl_info;
 
   // Result for GetSSLCertRequestInfo().
-  SSLCertRequestInfo* cert_request_info = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #union
+  RAW_PTR_EXCLUSION SSLCertRequestInfo* cert_request_info = nullptr;
 
   // Result for GetECHRetryConfigs().
   std::vector<uint8_t> ech_retry_configs;
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h
index 2e77948..59f5bb0d 100644
--- a/net/spdy/spdy_http_stream.h
+++ b/net/spdy/spdy_http_stream.h
@@ -11,6 +11,7 @@
 #include <set>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_piece.h"
@@ -167,7 +168,9 @@
   // After InitializeStream() is called but before OnClose() is called,
   //   |*stream_| is guaranteed to be valid.
   // After OnClose() is called, stream_ == nullptr.
-  SpdyStream* stream_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #addr-of
+  RAW_PTR_EXCLUSION SpdyStream* stream_ = nullptr;
 
   // False before OnClose() is called, true after.
   bool stream_closed_ = false;
diff --git a/net/test/embedded_test_server/embedded_test_server.h b/net/test/embedded_test_server/embedded_test_server.h
index fa5fa3f..d18a335 100644
--- a/net/test/embedded_test_server/embedded_test_server.h
+++ b/net/test/embedded_test_server/embedded_test_server.h
@@ -15,6 +15,7 @@
 #include "base/files/file_path.h"
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_piece.h"
@@ -68,7 +69,9 @@
   friend class EmbeddedTestServer;
 
   explicit EmbeddedTestServerHandle(EmbeddedTestServer* test_server);
-  EmbeddedTestServer* test_server_ = nullptr;
+  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
+  // #constexpr-ctor-field-initializer
+  RAW_PTR_EXCLUSION EmbeddedTestServer* test_server_ = nullptr;
 };
 
 // Class providing an HTTP server for testing purpose. This is a basic server
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index 0bb6e6f4..0167508 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -228,6 +228,10 @@
   pkg_config("xkbcommon") {
     packages = [ "xkbcommon" ]
   }
+
+  pkg_config("libevdev") {
+    packages = [ "libevdev" ]
+  }
 }
 
 # This must be a static library instead of a source set because
@@ -500,6 +504,7 @@
   }
 
   if (remoting_use_x11) {
+    assert(use_glib)
     defines += [ "REMOTING_USE_X11" ]
     sources += [
       "curtain_mode_linux.cc",
@@ -523,6 +528,8 @@
       "linux/desktop_display_info_loader_wayland.h",
       "linux/desktop_resizer_wayland.cc",
       "linux/desktop_resizer_wayland.h",
+      "linux/ei_event_watcher_glib.cc",
+      "linux/ei_event_watcher_glib.h",
       "linux/input_injector_wayland.cc",
       "linux/input_injector_wayland.h",
       "linux/remote_desktop_portal.cc",
@@ -548,6 +555,11 @@
       "x11_display_util.cc",
       "x11_display_util.h",
     ]
+    configs += [
+      "//third_party/webrtc/modules/portal:gio",
+      ":libevdev",
+    ]
+    libs += [ "//third_party/libei/lib64/libei.a" ]
     public_deps += [
       "//third_party/wayland:wayland_client",
       "//third_party/wayland-protocols:xdg_output_protocol",
diff --git a/remoting/host/linux/DEPS b/remoting/host/linux/DEPS
new file mode 100644
index 0000000..2ebbf02
--- /dev/null
+++ b/remoting/host/linux/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+third_party/libei",
+]
diff --git a/remoting/host/linux/ei_event_watcher_glib.cc b/remoting/host/linux/ei_event_watcher_glib.cc
new file mode 100644
index 0000000..ec0b82f
--- /dev/null
+++ b/remoting/host/linux/ei_event_watcher_glib.cc
@@ -0,0 +1,122 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/linux/ei_event_watcher_glib.h"
+
+#include "base/check.h"
+#include "base/memory/raw_ptr.h"
+#include "third_party/libei/include/libei.h"
+
+namespace remoting {
+
+constexpr GSourceFuncs EiEventWatcherGlib::kWatchSourceFuncs;
+
+EiEventWatcherGlib::EiEventWatcherGlib(
+    int fd,
+    ei* ei,
+    EiEventWatcherGlib::EiEventHandler* handler)
+    : fd_(fd), ei_(ei_ref(ei)), handler_(handler) {}
+
+EiEventWatcherGlib::~EiEventWatcherGlib() {
+  StopProcessingEvents();
+}
+
+void EiEventWatcherGlib::StartProcessingEvents() {
+  DCHECK(!ei_source_);
+  ei_source_ = static_cast<GLibEiSource*>(g_source_new(
+      const_cast<GSourceFuncs*>(&kWatchSourceFuncs), sizeof(GLibEiSource)));
+  ei_source_->event_watcher = this;
+  ei_source_->poll_fd = {
+      .fd = fd_,
+      .events = G_IO_IN,
+      .revents = 0,
+  };
+
+  g_source_add_poll(ei_source_, &ei_source_->poll_fd);
+  g_source_set_can_recurse(ei_source_, TRUE);
+  auto* context = g_main_context_get_thread_default();
+  if (!context) {
+    context = g_main_context_default();
+  }
+  g_source_attach(ei_source_, context);
+  g_source_set_priority(ei_source_, kPriorityFdWatch);
+}
+
+void EiEventWatcherGlib::StopProcessingEvents() {
+  if (ei_) {
+    ei_unref(ei_);
+    ei_ = nullptr;
+  }
+  if (ei_source_) {
+    g_source_destroy(ei_source_);
+    g_source_unref(ei_source_);
+    ei_source_ = nullptr;
+  }
+}
+
+// static
+gboolean EiEventWatcherGlib::WatchSourcePrepare(GSource* source,
+                                                gint* timeout_ms) {
+  // Set an infinite timeout.
+  *timeout_ms = -1;
+
+  auto* event_watcher_glib =
+      static_cast<GLibEiSource*>(source)->event_watcher.get();
+  return event_watcher_glib->Prepare();
+}
+
+// static
+gboolean EiEventWatcherGlib::WatchSourceCheck(GSource* source) {
+  auto* glib_ei_source = static_cast<GLibEiSource*>(source);
+  gushort flags = glib_ei_source->poll_fd.revents;
+  return flags & G_IO_IN;
+}
+
+// static
+gboolean EiEventWatcherGlib::WatchSourceDispatch(GSource* source,
+                                                 GSourceFunc unused_func,
+                                                 gpointer data) {
+  auto* event_watcher_glib =
+      static_cast<GLibEiSource*>(source)->event_watcher.get();
+  event_watcher_glib->Dispatch();
+  return TRUE;
+}
+
+bool EiEventWatcherGlib::Prepare() {
+  if (!ei_) {
+    return false;
+  }
+
+  struct ei_event* event = ei_peek_event(ei_.get());
+  if (event) {
+    ei_event_unref(event);
+    return true;
+  }
+  return false;
+}
+
+void EiEventWatcherGlib::Dispatch() {
+  ei_dispatch(ei_);
+  struct ei_event* event;
+  // Checks for events in the queue (with `ei_peek_event`) and removes them from
+  // the queue (using `ei_get_event`)
+  while ((event = ei_peek_event(ei_))) {
+    ei_event_unref(event);
+    event = ei_get_event(ei_);
+
+    if (handler_) {
+      handler_->HandleEiEvent(event);
+    }
+
+    bool should_stop = ei_event_get_type(event) == EI_EVENT_DISCONNECT;
+    ei_event_unref(event);
+
+    if (should_stop) {
+      StopProcessingEvents();
+      break;
+    }
+  }
+}
+
+}  // namespace remoting
diff --git a/remoting/host/linux/ei_event_watcher_glib.h b/remoting/host/linux/ei_event_watcher_glib.h
new file mode 100644
index 0000000..6c52c99
--- /dev/null
+++ b/remoting/host/linux/ei_event_watcher_glib.h
@@ -0,0 +1,76 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_LINUX_EI_EVENT_WATCHER_GLIB_H_
+#define REMOTING_HOST_LINUX_EI_EVENT_WATCHER_GLIB_H_
+
+#include <glib.h>
+#include "base/memory/raw_ptr.h"
+
+struct ei;
+struct ei_event;
+
+// The priorities of the event sources are important to be set correctly so that
+// GTK event source is able to process the events it requires. This uses
+// the same priority as MessagePumpGlib for fd watching.
+constexpr int kPriorityFdWatch = G_PRIORITY_DEFAULT_IDLE - 10;
+
+namespace remoting {
+
+// Implementation to do Glib based polling/dispatching for libei events.
+class EiEventWatcherGlib {
+ public:
+  class EiEventHandler {
+   public:
+    virtual ~EiEventHandler() = default;
+    virtual void HandleEiEvent(struct ei_event* event) = 0;
+  };
+
+  EiEventWatcherGlib(int fd, ei* ei, EiEventHandler* handler);
+  EiEventWatcherGlib(const EiEventWatcherGlib&) = delete;
+  EiEventWatcherGlib& operator=(const EiEventWatcherGlib&) = delete;
+  ~EiEventWatcherGlib();
+
+  // Starts the event processing loop. Event processing will automatically stop
+  // if `EI_EVENT_DISCONNECT` event is observed.
+  void StartProcessingEvents();
+  // Stops the event processing loop, if it was not already stopped, otherwise
+  // it is a no-op.
+  void StopProcessingEvents();
+
+ private:
+  struct GLibEiSource : public GSource {
+    // Note: The GLibEiSource is created and destroyed by GLib. So its
+    // constructor/destructor may or may not get called. Similarly, the user
+    // data that is accepted by `g_source_new` is not deleted by Glib (i.e. Glib
+    // doesn't take ownership of this data).
+    raw_ptr<EiEventWatcherGlib> event_watcher;
+    GPollFD poll_fd;
+  };
+
+  static gboolean WatchSourcePrepare(GSource* source, gint* timeout_ms);
+  static gboolean WatchSourceCheck(GSource* source);
+  static gboolean WatchSourceDispatch(GSource* source,
+                                      GSourceFunc unused_func,
+                                      gpointer data);
+
+  static constexpr GSourceFuncs kWatchSourceFuncs = {
+      WatchSourcePrepare, WatchSourceCheck, WatchSourceDispatch, nullptr};
+
+  bool Prepare();
+  void Dispatch();
+
+  // The GLib event source for EI events.
+  raw_ptr<GLibEiSource> ei_source_ = nullptr;
+
+  // FD to watch for events.
+  int fd_ = -1;
+
+  base::raw_ptr<ei> ei_ = nullptr;
+  base::raw_ptr<EiEventHandler> handler_ = nullptr;
+};
+
+}  // namespace remoting
+
+#endif  // REMOTING_HOST_LINUX_EI_EVENT_WATCHER_GLIB_H_
diff --git a/remoting/host/linux/input_injector_wayland.cc b/remoting/host/linux/input_injector_wayland.cc
index c049cf7..2b839f9 100644
--- a/remoting/host/linux/input_injector_wayland.cc
+++ b/remoting/host/linux/input_injector_wayland.cc
@@ -452,6 +452,19 @@
   }
 }
 
+void InputInjectorWayland::Core::InjectPendingEvents(bool libei_succeeded) {
+  if (!libei_succeeded) {
+    LOG(WARNING) << "Setting up libei failed, going to rely on slower "
+                 << "input injection path";
+
+    // These are needed so that we can acquire keyboard/pointer capability.
+    InjectFakeKeyEvent();
+    InjectFakePointerEvent();
+  }
+
+  MaybeFlushPendingEvents();
+}
+
 void InputInjectorWayland::Core::SetRemoteDesktopSessionDetails(
     const SessionDetails& session_details) {
   if (!input_task_runner_->BelongsToCurrentThread()) {
@@ -464,11 +477,8 @@
   remotedesktop_portal_.SetSessionDetails(session_details);
   remote_desktop_initialized_ = true;
 
-  // These are needed so that we can acquire keyboard/pointer capability.
-  InjectFakeKeyEvent();
-  InjectFakePointerEvent();
-
-  MaybeFlushPendingEvents();
+  remotedesktop_portal_.SetupLibei(
+      base::BindOnce(&Core::InjectPendingEvents, this));
 }
 
 void InputInjectorWayland::Core::MaybeFlushPendingEvents() {
diff --git a/remoting/host/linux/input_injector_wayland.h b/remoting/host/linux/input_injector_wayland.h
index 89ef3db..aa07a1b 100644
--- a/remoting/host/linux/input_injector_wayland.h
+++ b/remoting/host/linux/input_injector_wayland.h
@@ -102,6 +102,7 @@
     void MovePointerTo(int x, int y);
     void MovePointerBy(int delta_x, int delta_y);
     void InjectKeyPress(unsigned int code, bool pressed, bool is_code = true);
+    void InjectPendingEvents(bool libei_scucceeded);
 
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
     std::set<int> pressed_keys_;
diff --git a/remoting/host/linux/remote_desktop_portal_injector.cc b/remoting/host/linux/remote_desktop_portal_injector.cc
index 1e35535..5bf9aeb 100644
--- a/remoting/host/linux/remote_desktop_portal_injector.cc
+++ b/remoting/host/linux/remote_desktop_portal_injector.cc
@@ -4,14 +4,20 @@
 
 #include "remoting/host/linux/remote_desktop_portal_injector.h"
 
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
 #include <glib-object.h>
+#include <poll.h>
 
+#include <libevdev/libevdev-uinput.h>
 #include <utility>
 
 #include "base/check.h"
+#include "base/notreached.h"
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "remoting/base/logging.h"
+#include "third_party/libei/include/libei.h"
 #include "third_party/webrtc/modules/desktop_capture/linux/wayland/portal_request_response.h"
 #include "third_party/webrtc/modules/desktop_capture/linux/wayland/scoped_glib.h"
 #include "third_party/webrtc/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h"
@@ -20,11 +26,75 @@
 
 using webrtc::Scoped;
 
+namespace {
+// TODO(crbug/1291247): See if these can be pulled from a common place.
+constexpr int BUTTON_LEFT_KEYCODE = 272;
+constexpr int BUTTON_RIGHT_KEYCODE = 273;
+constexpr int BUTTON_MIDDLE_KEYCODE = 274;
+constexpr int BUTTON_FORWARD_KEYCODE = 277;
+constexpr int BUTTON_BACK_KEYCODE = 278;
+constexpr int BTN_UNKNOWN = -1;
+
+// See:
+// https://libinput.pages.freedesktop.org/libei/api/group__libei.html#gaf2ec4b04f6b3c706bad0f1cae66bea34
+constexpr int EI_SCROLL_FACTOR = 120;
+
+int EvdevCodeToMouseButton(int code) {
+  switch (code) {
+    case BUTTON_LEFT_KEYCODE:
+      return BTN_LEFT;
+    case BUTTON_RIGHT_KEYCODE:
+      return BTN_RIGHT;
+    case BUTTON_MIDDLE_KEYCODE:
+      return BTN_MIDDLE;
+    case BUTTON_BACK_KEYCODE:
+      return BTN_BACK;
+    case BUTTON_FORWARD_KEYCODE:
+      return BTN_FORWARD;
+    default:
+      NOTREACHED() << "Undefined code: " << code;
+      return BTN_UNKNOWN;
+  }
+}
+
+}  // namespace
+
 RemoteDesktopPortalInjector::RemoteDesktopPortalInjector() {
   DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
-RemoteDesktopPortalInjector::~RemoteDesktopPortalInjector() {}
+RemoteDesktopPortalInjector::~RemoteDesktopPortalInjector() {
+  Cleanup();
+}
+
+void RemoteDesktopPortalInjector::Cleanup() {
+  if (ei_) {
+    ei_event_watcher_->StopProcessingEvents();
+  }
+  if (ei_keyboard_) {
+    ei_device_unref(ei_keyboard_);
+    ei_keyboard_ = nullptr;
+  }
+  if (ei_pointer_) {
+    ei_device_unref(ei_pointer_);
+    ei_pointer_ = nullptr;
+  }
+  if (ei_absolute_pointer_) {
+    ei_device_unref(ei_absolute_pointer_);
+    ei_absolute_pointer_ = nullptr;
+  }
+  if (ei_seat_) {
+    ei_seat_unref(ei_seat_);
+    ei_seat_ = nullptr;
+  }
+  if (ei_) {
+    ei_unref(ei_);
+    ei_ = nullptr;
+  }
+  ei_pointer_enabled_ = false;
+  ei_keyboard_enabled_ = false;
+  ei_absolute_pointer_enabled_ = false;
+}
 
 // static
 void RemoteDesktopPortalInjector::ValidateGDPBusProxyResult(
@@ -43,12 +113,26 @@
     if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
       return;
     }
-    LOG(ERROR) << "Error in input injection";
+    LOG(ERROR) << "Error in input injection (without EI)";
   }
 }
 
 void RemoteDesktopPortalInjector::InjectMouseButton(int code, bool pressed) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (use_ei_) {
+    if (ei_pointer_enabled_) {
+      ei_device_pointer_button(ei_pointer_, EvdevCodeToMouseButton(code),
+                               pressed);
+      ei_device_frame(ei_pointer_, ei_now(ei_));
+    } else {
+      // Non-ei injection is blocked by portal when EI has been enabled
+      // successfully previously.
+      LOG(ERROR)
+          << "Unable to inject mouse button since EI pointer is disabled";
+    }
+    return;
+  }
+
   DCHECK(proxy_);
   DCHECK(cancellable_);
   DCHECK(!session_handle_.empty());
@@ -64,6 +148,23 @@
 
 void RemoteDesktopPortalInjector::InjectMouseScroll(int axis, int steps) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (use_ei_) {
+    if (ei_absolute_pointer_enabled_) {
+      if (axis == ScrollType::VERTICAL_SCROLL) {
+        ei_device_pointer_scroll_discrete(ei_absolute_pointer_, 0,
+                                          steps * EI_SCROLL_FACTOR);
+      } else {
+        ei_device_pointer_scroll_discrete(ei_absolute_pointer_,
+                                          steps * EI_SCROLL_FACTOR, 0);
+      }
+      ei_device_pointer_scroll_stop(ei_absolute_pointer_, true, true);
+      ei_device_frame(ei_absolute_pointer_, ei_now(ei_));
+    } else {
+      LOG(ERROR) << "Unable to scroll mouse since EI pointer is disabled";
+    }
+    return;
+  }
+
   DCHECK(proxy_);
   DCHECK(cancellable_);
   DCHECK(!session_handle_.empty());
@@ -79,6 +180,17 @@
 
 void RemoteDesktopPortalInjector::MovePointerBy(int delta_x, int delta_y) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (use_ei_) {
+    if (ei_pointer_enabled_) {
+      ei_device_pointer_motion(ei_pointer_, delta_x, delta_y);
+      ei_device_frame(ei_pointer_, ei_now(ei_));
+    } else {
+      LOG(ERROR)
+          << "Unable to do relative mouse move since EI pointer is disabled";
+    }
+    return;
+  }
+
   DCHECK(proxy_);
   DCHECK(cancellable_);
   DCHECK(!session_handle_.empty());
@@ -93,8 +205,34 @@
       ValidateGDPBusProxyResult, this);
 }
 
+bool RemoteDesktopPortalInjector::InDeviceRegion(uint32_t x, uint32_t y) {
+  for (const auto& region : device_regions_) {
+    if ((x >= region.x && x < region.x + region.w) &&
+        (y >= region.y && y < region.y + region.h)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void RemoteDesktopPortalInjector::MovePointerTo(int x, int y) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (use_ei_) {
+    if (ei_absolute_pointer_enabled_) {
+      if (!InDeviceRegion(x, y)) {
+        LOG(WARNING) << "Absolute coordinates " << x << "," << y
+                     << "are not in any device region, ignoring";
+        return;
+      }
+      ei_device_pointer_motion_absolute(ei_absolute_pointer_, x, y);
+      ei_device_frame(ei_absolute_pointer_, ei_now(ei_));
+    } else {
+      LOG(ERROR)
+          << "Unable to do absolute mouse move since EI pointer is disabled";
+    }
+    return;
+  }
+
   DCHECK(proxy_);
   DCHECK(cancellable_);
   DCHECK(!session_handle_.empty());
@@ -116,6 +254,16 @@
                                                  bool pressed,
                                                  bool is_code) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (use_ei_) {
+    if (ei_keyboard_enabled_) {
+      ei_device_keyboard_key(ei_keyboard_, code, pressed);
+      ei_device_frame(ei_keyboard_, ei_now(ei_));
+    } else {
+      LOG(ERROR) << "Unable to inject key press since EI keyboard is disabled";
+    }
+    return;
+  }
+
   DCHECK(proxy_);
   DCHECK(cancellable_);
   DCHECK(!session_handle_.empty());
@@ -141,4 +289,263 @@
   pipewire_stream_node_id_ = session_details.pipewire_stream_node_id;
 }
 
+static void ei_loghandler(struct ei* ei,
+                          enum ei_log_priority priority,
+                          const char* message,
+                          struct ei_log_context* ctx) {
+  HOST_LOG << "[EI_LOGGER] " << ei_log_context_get_func(ctx) << " : "
+           << message;
+}
+
+// static
+void RemoteDesktopPortalInjector::OnEiFdRequested(GObject* object,
+                                                  GAsyncResult* result,
+                                                  gpointer user_data) {
+  auto* proxy = reinterpret_cast<GDBusProxy*>(object);
+  RemoteDesktopPortalInjector* that =
+      static_cast<RemoteDesktopPortalInjector*>(user_data);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(that->sequence_checker_);
+
+  Scoped<GError> error;
+  Scoped<GUnixFDList> outlist;
+  Scoped<GVariant> variant(g_dbus_proxy_call_with_unix_fd_list_finish(
+      proxy, outlist.receive(), result, error.receive()));
+  if (!variant) {
+    if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+      return;
+    }
+    LOG(ERROR) << "Failed to get the EI fd: " << error->message;
+    std::move(that->on_libei_setup_done_).Run(false);
+    return;
+  }
+
+  int32_t index;
+  g_variant_get(variant.get(), "(h)", &index);
+
+  that->ei_fd_ = g_unix_fd_list_get(outlist.get(), index, error.receive());
+
+  if (that->ei_fd_ == -1) {
+    LOG(ERROR) << "Failed to get file descriptor from the list: "
+               << error->message;
+    std::move(that->on_libei_setup_done_).Run(false);
+    return;
+  }
+
+  that->ei_ = ei_new_sender(nullptr);
+  ei_configure_name(that->ei_, "crd-input");
+  ei_log_set_priority(that->ei_, EI_LOG_PRIORITY_INFO);
+  ei_log_set_handler(that->ei_, ei_loghandler);
+  ei_setup_backend_fd(that->ei_.get(), that->ei_fd_);
+
+  that->ei_event_watcher_ =
+      std::make_unique<EiEventWatcherGlib>(that->ei_fd_, that->ei_, that);
+
+  that->ei_event_watcher_->StartProcessingEvents();
+  that->use_ei_ = true;
+  HOST_LOG << "Using LIBEI for input injection";
+  std::move(that->on_libei_setup_done_).Run(true);
+}
+
+void RemoteDesktopPortalInjector::HandleRegions(struct ei_device* device) {
+  uint32_t idx = 0;
+  struct ei_region* region;
+
+  while ((region = ei_device_get_region(device, idx++))) {
+    DeviceRegion device_region{.x = ei_region_get_x(region),
+                               .y = ei_region_get_y(region),
+                               .w = ei_region_get_width(region),
+                               .h = ei_region_get_height(region)};
+
+    HOST_LOG << "EI Device: " << ei_device_get_name(device) << " has region "
+             << device_region.w << "x" << device_region.h << "@"
+             << device_region.x << "," << device_region.y;
+    device_regions_.push_back(std::move(device_region));
+  }
+}
+
+void RemoteDesktopPortalInjector::OnEiSeatAddedEvent(struct ei_event* event) {
+  if (ei_seat_) {
+    return;
+  }
+
+  ei_seat_ = ei_seat_ref(ei_event_get_seat(event));
+  HOST_LOG << "EI seat added: " << ei_seat_get_name(ei_seat_);
+  ei_seat_bind_capability(ei_seat_, EI_DEVICE_CAP_POINTER);
+  ei_seat_bind_capability(ei_seat_, EI_DEVICE_CAP_KEYBOARD);
+  ei_seat_bind_capability(ei_seat_, EI_DEVICE_CAP_POINTER_ABSOLUTE);
+}
+
+void RemoteDesktopPortalInjector::OnEiSeatRemovedEvent(struct ei_event* event) {
+  // Don't need to close the devices, libei will give us the right events.
+  if (ei_event_get_seat(event) == ei_seat_.get()) {
+    ei_seat_ = ei_seat_unref(ei_seat_);
+    ei_seat_ = nullptr;
+  }
+}
+
+void RemoteDesktopPortalInjector::OnEiDeviceAddedEvent(struct ei_event* event) {
+  struct ei_device* device = ei_device_ref(ei_event_get_device(event));
+
+  if (ei_device_has_capability(device, EI_DEVICE_CAP_POINTER)) {
+    HOST_LOG << "EI New pointer device: " << ei_device_get_name(device);
+    if (ei_pointer_) {
+      ei_device_unref(ei_pointer_);
+    }
+    ei_pointer_ = device;
+  }
+  if (ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD)) {
+    HOST_LOG << "EI New keyboard device: " << ei_device_get_name(device);
+    if (ei_keyboard_) {
+      ei_device_unref(ei_keyboard_);
+    }
+    ei_keyboard_ = device;
+  }
+  if (ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE)) {
+    HOST_LOG << "EI New absolute pointer device: "
+             << ei_device_get_name(device);
+    if (ei_absolute_pointer_) {
+      ei_device_unref(ei_absolute_pointer_);
+    }
+    ei_absolute_pointer_ = device;
+    HandleRegions(ei_absolute_pointer_);
+  }
+}
+
+void RemoteDesktopPortalInjector::OnEiDeviceResumedEvent(
+    struct ei_event* event) {
+  struct ei_device* event_device = ei_event_get_device(event);
+  if (!event_device) {
+    return;
+  }
+
+  if (event_device == ei_pointer_.get()) {
+    HOST_LOG << "EI Emulating the pointer device now";
+    ei_device_start_emulating(ei_pointer_, ++device_serial_);
+    ei_pointer_enabled_ = true;
+  } else if (event_device == ei_keyboard_.get()) {
+    HOST_LOG << "EI Emulating the keyboard device now";
+    ei_device_start_emulating(ei_keyboard_, ++device_serial_);
+    ei_keyboard_enabled_ = true;
+  } else if (event_device == ei_absolute_pointer_.get()) {
+    HOST_LOG << "EI Emulating the absolute pointer device now";
+    ei_device_start_emulating(ei_absolute_pointer_, ++device_serial_);
+    ei_absolute_pointer_enabled_ = true;
+  } else {
+    LOG(WARNING) << "EI unknown device resumed: "
+                 << ei_device_get_name(event_device);
+  }
+}
+
+void RemoteDesktopPortalInjector::OnEiDevicePausedEvent(
+    struct ei_event* event) {
+  struct ei_device* event_device = ei_event_get_device(event);
+  if (!event_device) {
+    return;
+  }
+
+  if (event_device == ei_pointer_.get()) {
+    HOST_LOG << "EI Pointer device paused";
+    ei_device_stop_emulating(ei_pointer_);
+    ei_pointer_enabled_ = false;
+  } else if (event_device == ei_keyboard_.get()) {
+    HOST_LOG << "EI Keyboard device paused";
+    ei_device_stop_emulating(ei_keyboard_);
+    ei_keyboard_enabled_ = false;
+  } else if (event_device == ei_absolute_pointer_.get()) {
+    HOST_LOG << "EI Absolute pointer device paused";
+    ei_device_stop_emulating(ei_absolute_pointer_);
+    ei_absolute_pointer_enabled_ = false;
+  } else {
+    LOG(WARNING) << "EI Unknown device paused: "
+                 << ei_device_get_name(event_device);
+  }
+}
+
+void RemoteDesktopPortalInjector::OnEiDeviceRemovedEvent(
+    struct ei_event* event) {
+  struct ei_device* event_device = ei_event_get_device(event);
+  if (!event_device) {
+    return;
+  }
+
+  if (event_device == ei_pointer_.get()) {
+    HOST_LOG << "EI Pointer device removed";
+    ei_device_unref(ei_pointer_);
+    ei_pointer_ = nullptr;
+    ei_pointer_enabled_ = false;
+  } else if (event_device == ei_keyboard_.get()) {
+    HOST_LOG << "EI Keyboard device removed";
+    ei_device_unref(ei_keyboard_);
+    ei_keyboard_ = nullptr;
+    ei_keyboard_enabled_ = false;
+  } else if (event_device == ei_absolute_pointer_.get()) {
+    HOST_LOG << "EI Absolute pointer device removed";
+    ei_device_unref(ei_absolute_pointer_);
+    ei_absolute_pointer_ = nullptr;
+    ei_absolute_pointer_enabled_ = false;
+    device_regions_.clear();
+  } else {
+    LOG(WARNING) << "EI unknown device removed: "
+                 << ei_device_get_name(event_device);
+  }
+}
+
+void RemoteDesktopPortalInjector::HandleEiEvent(struct ei_event* event) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  switch (ei_event_get_type(event)) {
+    case EI_EVENT_CONNECT:
+      HOST_LOG << "EI connected";
+      break;
+    case EI_EVENT_DISCONNECT: {
+      HOST_LOG << "EI disconnected";
+      Cleanup();
+      break;
+    }
+    case EI_EVENT_SEAT_ADDED:
+      OnEiSeatAddedEvent(event);
+      break;
+    case EI_EVENT_SEAT_REMOVED:
+      OnEiSeatRemovedEvent(event);
+      break;
+    case EI_EVENT_DEVICE_ADDED:
+      OnEiDeviceAddedEvent(event);
+      break;
+    case EI_EVENT_DEVICE_RESUMED:
+      OnEiDeviceResumedEvent(event);
+      break;
+    case EI_EVENT_DEVICE_PAUSED:
+      OnEiDevicePausedEvent(event);
+      break;
+    case EI_EVENT_DEVICE_REMOVED:
+      OnEiDeviceRemovedEvent(event);
+      break;
+    case EI_EVENT_FRAME:
+    case EI_EVENT_DEVICE_START_EMULATING:
+    case EI_EVENT_DEVICE_STOP_EMULATING:
+    case EI_EVENT_POINTER_MOTION:
+    case EI_EVENT_POINTER_MOTION_ABSOLUTE:
+    case EI_EVENT_POINTER_BUTTON:
+    case EI_EVENT_POINTER_SCROLL:
+    case EI_EVENT_POINTER_SCROLL_DISCRETE:
+    case EI_EVENT_KEYBOARD_KEY:
+      break;
+    default:
+      LOG(WARNING) << "Unexpected EI event observed type: "
+                   << ei_event_get_type(event);
+  }
+}
+
+void RemoteDesktopPortalInjector::SetupLibei(
+    base::OnceCallback<void(bool)> OnLibeiDone) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  on_libei_setup_done_ = std::move(OnLibeiDone);
+  GVariantBuilder builder;
+  g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
+  g_dbus_proxy_call_with_unix_fd_list(
+      proxy_, "ConnectToEIS",
+      g_variant_new("(oa{sv})", session_handle_.c_str(), &builder),
+      G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*fd_list=*/nullptr, cancellable_,
+      OnEiFdRequested, this);
+}
+
 }  // namespace remoting::xdg_portal
diff --git a/remoting/host/linux/remote_desktop_portal_injector.h b/remoting/host/linux/remote_desktop_portal_injector.h
index a65b7756..05ea39fa 100644
--- a/remoting/host/linux/remote_desktop_portal_injector.h
+++ b/remoting/host/linux/remote_desktop_portal_injector.h
@@ -10,9 +10,12 @@
 #include <memory>
 #include <string>
 
+#include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/sequence_checker.h"
+#include "remoting/host/linux/ei_event_watcher_glib.h"
+#include "third_party/libei/include/libei.h"
 #include "third_party/webrtc/modules/desktop_capture/linux/wayland/screen_capture_portal_interface.h"
 #include "third_party/webrtc/modules/desktop_capture/linux/wayland/screencast_portal.h"
 #include "third_party/webrtc/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h"
@@ -20,9 +23,16 @@
 
 namespace remoting::xdg_portal {
 
+struct DeviceRegion {
+  uint32_t x;
+  uint32_t y;
+  uint32_t w;
+  uint32_t h;
+};
+
 // This class is used by the `ChromotingInputThread` to inject input into the
 // wayland remote host using XDG desktop portal APIs.
-class RemoteDesktopPortalInjector {
+class RemoteDesktopPortalInjector : public EiEventWatcherGlib::EiEventHandler {
  public:
   enum ScrollType {
     VERTICAL_SCROLL = 0,
@@ -34,7 +44,7 @@
   RemoteDesktopPortalInjector(const RemoteDesktopPortalInjector&) = delete;
   RemoteDesktopPortalInjector& operator=(const RemoteDesktopPortalInjector&) =
       delete;
-  ~RemoteDesktopPortalInjector();
+  ~RemoteDesktopPortalInjector() override;
 
   // This method populates the session details for this object. Session details
   // are borrowed from the wayland desktop capturer.
@@ -47,12 +57,31 @@
   void MovePointerBy(int delta_x, int delta_y);
   void InjectKeyPress(int code, bool pressed, bool is_code = true);
 
+  // EiEventWatcherGlib::EiEventHandler interface
+  void HandleEiEvent(struct ei_event* event) override;
+
+  void SetupLibei(base::OnceCallback<void(bool)> OnLibeiDone);
+
  private:
   SEQUENCE_CHECKER(sequence_checker_);
 
+  void Cleanup();
+
   static void ValidateGDPBusProxyResult(GObject* proxy,
                                         GAsyncResult* result,
                                         gpointer user_data);
+  static void OnEiFdRequested(GObject* object,
+                              GAsyncResult* result,
+                              gpointer user_data);
+  void HandleRegions(struct ei_device* device);
+  bool InDeviceRegion(uint32_t x, uint32_t y);
+
+  void OnEiSeatAddedEvent(struct ei_event* event);
+  void OnEiSeatRemovedEvent(struct ei_event* event);
+  void OnEiDeviceAddedEvent(struct ei_event* event);
+  void OnEiDeviceResumedEvent(struct ei_event* event);
+  void OnEiDevicePausedEvent(struct ei_event* event);
+  void OnEiDeviceRemovedEvent(struct ei_event* event);
 
   raw_ptr<GDBusConnection> connection_ GUARDED_BY_CONTEXT(sequence_checker_) =
       nullptr;
@@ -62,6 +91,22 @@
 
   uint32_t pipewire_stream_node_id_ GUARDED_BY_CONTEXT(sequence_checker_);
   std::string session_handle_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // EI related fields.
+  raw_ptr<ei> ei_ = nullptr;
+  raw_ptr<struct ei_seat> ei_seat_ = nullptr;
+  raw_ptr<ei_device> ei_pointer_ = nullptr;
+  raw_ptr<ei_device> ei_keyboard_ = nullptr;
+  raw_ptr<ei_device> ei_absolute_pointer_ = nullptr;
+  bool ei_pointer_enabled_ = false;
+  bool ei_absolute_pointer_enabled_ = false;
+  bool ei_keyboard_enabled_ = false;
+  bool use_ei_ = false;
+  std::unique_ptr<EiEventWatcherGlib> ei_event_watcher_;
+  int ei_fd_ = -1;
+  int device_serial_ = 1;
+  std::vector<DeviceRegion> device_regions_{};
+  base::OnceCallback<void(bool)> on_libei_setup_done_;
 };
 
 }  // namespace remoting::xdg_portal
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 8803b206..71eade24 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -167,11 +167,11 @@
 ResultExpr RestrictPrctl() {
   // Will need to add seccomp compositing in the future. PR_SET_PTRACER is
   // used by breakpad but not needed anymore.
-  const Arg<int> option(0);
+  const Arg<int> option(0), arg(1);
   return Switch(option)
       .Cases({PR_GET_NAME, PR_SET_NAME, PR_GET_DUMPABLE, PR_SET_DUMPABLE
 #if BUILDFLAG(IS_ANDROID)
-              , PR_SET_VMA, PR_SET_PTRACER, PR_SET_TIMERSLACK
+              , PR_SET_PTRACER, PR_SET_TIMERSLACK
               , PR_GET_NO_NEW_PRIVS, PR_PAC_RESET_KEYS
 
 // Enable PR_SET_TIMERSLACK_PID, an Android custom prctl which is used in:
@@ -203,6 +203,10 @@
 #endif  // BUILDFLAG(IS_ANDROID)
               },
              Allow())
+#if BUILDFLAG(IS_ANDROID)
+      .Cases({PR_SET_VMA},
+             If(arg == PR_SET_VMA_ANON_NAME, Allow()).Else(CrashSIGSYSPrctl()))
+#endif
       .Default(
           If(option == PR_SET_PTRACER, Error(EPERM)).Else(CrashSIGSYSPrctl()));
 }
diff --git a/services/tracing/public/cpp/perfetto/perfetto_traced_process.h b/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
index 8c3fff1..debc27c4 100644
--- a/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
+++ b/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
@@ -158,7 +158,7 @@
 
    private:
     PerfettoTracedProcess::DataSourceBase* const data_source_ = nullptr;
-    PerfettoTracedProcess::DataSourceBase* const* data_source_ptr_ =
+    raw_ptr<PerfettoTracedProcess::DataSourceBase* const> data_source_ptr_ =
         &data_source_;
     perfetto::DataSourceConfig data_source_config_;
   };
diff --git a/testing/buildbot/chromium.angle.json b/testing/buildbot/chromium.angle.json
index 5a3e8d1..d06bd30 100644
--- a/testing/buildbot/chromium.angle.json
+++ b/testing/buildbot/chromium.angle.json
@@ -84,7 +84,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "containment_type": "AUTO",
@@ -142,7 +142,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "containment_type": "AUTO",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index bfc5d84..8ead669 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5886,9 +5886,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -5900,8 +5900,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -6057,9 +6057,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -6071,8 +6071,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -6209,9 +6209,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -6223,8 +6223,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 8a678732..2a07713 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -40437,7 +40437,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40489,7 +40489,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40541,7 +40541,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40593,7 +40593,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40645,7 +40645,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40697,7 +40697,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40749,7 +40749,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40801,7 +40801,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40853,7 +40853,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40905,7 +40905,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -40957,7 +40957,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41009,7 +41009,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41061,7 +41061,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41113,7 +41113,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41165,7 +41165,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41217,7 +41217,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41269,7 +41269,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41321,7 +41321,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41393,7 +41393,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41440,7 +41440,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41487,7 +41487,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41534,7 +41534,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41581,7 +41581,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41628,7 +41628,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41675,7 +41675,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41722,7 +41722,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41769,7 +41769,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41816,7 +41816,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41863,7 +41863,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41910,7 +41910,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -41957,7 +41957,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -42004,7 +42004,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -42051,7 +42051,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -42098,7 +42098,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -42145,7 +42145,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -42192,7 +42192,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index 2e25899..614db23 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -10129,7 +10129,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10183,7 +10183,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10237,7 +10237,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10291,7 +10291,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10345,7 +10345,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10399,7 +10399,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10453,7 +10453,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10507,7 +10507,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10561,7 +10561,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10615,7 +10615,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10669,7 +10669,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10723,7 +10723,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10777,7 +10777,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10831,7 +10831,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10885,7 +10885,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10939,7 +10939,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10993,7 +10993,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11047,7 +11047,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11101,7 +11101,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11155,7 +11155,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11209,7 +11209,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11263,7 +11263,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11317,7 +11317,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11371,7 +11371,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11425,7 +11425,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11479,7 +11479,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11533,7 +11533,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11587,7 +11587,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11641,7 +11641,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11695,7 +11695,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11749,7 +11749,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11803,7 +11803,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11857,7 +11857,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11911,7 +11911,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11965,7 +11965,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12019,7 +12019,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12073,7 +12073,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12127,7 +12127,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12181,7 +12181,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12235,7 +12235,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12289,7 +12289,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12343,7 +12343,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12398,7 +12398,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12453,7 +12453,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12508,7 +12508,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12563,7 +12563,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12618,7 +12618,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12673,7 +12673,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12728,7 +12728,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12783,7 +12783,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12838,7 +12838,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12894,7 +12894,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12950,7 +12950,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13006,7 +13006,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13062,7 +13062,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13118,7 +13118,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13174,7 +13174,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13230,7 +13230,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13286,7 +13286,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13342,7 +13342,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13398,7 +13398,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13454,7 +13454,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13510,7 +13510,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13566,7 +13566,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13622,7 +13622,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13678,7 +13678,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13734,7 +13734,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13790,7 +13790,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13846,7 +13846,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13902,7 +13902,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13958,7 +13958,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14014,7 +14014,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14070,7 +14070,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14126,7 +14126,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14182,7 +14182,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14237,7 +14237,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14292,7 +14292,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14347,7 +14347,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14402,7 +14402,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14457,7 +14457,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14512,7 +14512,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14567,7 +14567,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14622,7 +14622,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14678,7 +14678,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14734,7 +14734,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14790,7 +14790,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14846,7 +14846,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14902,7 +14902,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14958,7 +14958,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15014,7 +15014,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15069,7 +15069,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15123,7 +15123,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15177,7 +15177,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15231,7 +15231,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15285,7 +15285,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15339,7 +15339,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15393,7 +15393,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15447,7 +15447,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15501,7 +15501,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15555,7 +15555,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15610,7 +15610,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15666,7 +15666,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15722,7 +15722,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15778,7 +15778,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15834,7 +15834,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15890,7 +15890,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15946,7 +15946,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16002,7 +16002,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16057,7 +16057,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16111,7 +16111,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16165,7 +16165,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16220,7 +16220,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16275,7 +16275,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16329,7 +16329,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16384,7 +16384,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16439,7 +16439,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16494,7 +16494,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16549,7 +16549,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16604,7 +16604,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16659,7 +16659,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16714,7 +16714,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16769,7 +16769,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16823,7 +16823,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16877,7 +16877,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16931,7 +16931,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16985,7 +16985,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17039,7 +17039,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17093,7 +17093,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17147,7 +17147,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17201,7 +17201,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17255,7 +17255,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17309,7 +17309,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17363,7 +17363,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17417,7 +17417,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17472,7 +17472,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17527,7 +17527,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17582,7 +17582,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17637,7 +17637,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17692,7 +17692,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17747,7 +17747,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17802,7 +17802,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17857,7 +17857,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17911,7 +17911,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17965,7 +17965,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18019,7 +18019,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18073,7 +18073,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18127,7 +18127,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18181,7 +18181,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18235,7 +18235,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18289,7 +18289,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18343,7 +18343,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18397,7 +18397,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18451,7 +18451,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18505,7 +18505,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18559,7 +18559,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18613,7 +18613,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18667,7 +18667,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18721,7 +18721,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18775,7 +18775,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18829,7 +18829,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18883,7 +18883,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18937,7 +18937,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18991,7 +18991,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19045,7 +19045,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19099,7 +19099,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19153,7 +19153,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19207,7 +19207,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19261,7 +19261,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19315,7 +19315,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19369,7 +19369,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19423,7 +19423,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19477,7 +19477,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19531,7 +19531,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19585,7 +19585,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19639,7 +19639,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19693,7 +19693,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19747,7 +19747,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19801,7 +19801,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19855,7 +19855,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19909,7 +19909,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19963,7 +19963,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20017,7 +20017,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20071,7 +20071,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20125,7 +20125,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20179,7 +20179,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20233,7 +20233,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20287,7 +20287,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20341,7 +20341,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20395,7 +20395,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20449,7 +20449,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20503,7 +20503,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20557,7 +20557,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20611,7 +20611,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20665,7 +20665,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20719,7 +20719,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20773,7 +20773,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20827,7 +20827,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20881,7 +20881,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20935,7 +20935,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20989,7 +20989,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25738,9 +25738,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -25752,8 +25752,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -25909,9 +25909,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -25923,8 +25923,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -26061,9 +26061,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -26075,8 +26075,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index afd4f804..1695647 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -6063,7 +6063,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6116,7 +6116,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6169,7 +6169,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6222,7 +6222,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6275,7 +6275,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6328,7 +6328,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6381,7 +6381,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6434,7 +6434,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6487,7 +6487,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6540,7 +6540,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6593,7 +6593,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6646,7 +6646,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6699,7 +6699,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6752,7 +6752,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6805,7 +6805,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6858,7 +6858,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6911,7 +6911,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -6964,7 +6964,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7017,7 +7017,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7070,7 +7070,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7123,7 +7123,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7176,7 +7176,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7229,7 +7229,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7282,7 +7282,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7335,7 +7335,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7388,7 +7388,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7441,7 +7441,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7494,7 +7494,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7547,7 +7547,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7600,7 +7600,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7658,7 +7658,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7713,7 +7713,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7768,7 +7768,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7824,7 +7824,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7880,7 +7880,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7936,7 +7936,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -7992,7 +7992,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8048,7 +8048,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8104,7 +8104,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8159,7 +8159,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8214,7 +8214,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8270,7 +8270,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8326,7 +8326,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8382,7 +8382,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8438,7 +8438,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8493,7 +8493,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8548,7 +8548,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8603,7 +8603,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8663,7 +8663,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8715,7 +8715,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8767,7 +8767,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8819,7 +8819,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8871,7 +8871,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8923,7 +8923,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -8975,7 +8975,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9027,7 +9027,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9079,7 +9079,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9131,7 +9131,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9183,7 +9183,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9235,7 +9235,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9287,7 +9287,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9339,7 +9339,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9391,7 +9391,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9443,7 +9443,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9495,7 +9495,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9547,7 +9547,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9602,7 +9602,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9657,7 +9657,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9712,7 +9712,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9767,7 +9767,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9823,7 +9823,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9879,7 +9879,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9935,7 +9935,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -9991,7 +9991,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10047,7 +10047,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10103,7 +10103,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10159,7 +10159,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10215,7 +10215,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10271,7 +10271,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10327,7 +10327,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10382,7 +10382,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10437,7 +10437,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10492,7 +10492,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10548,7 +10548,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10604,7 +10604,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10657,7 +10657,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10709,7 +10709,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10761,7 +10761,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10813,7 +10813,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10868,7 +10868,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10924,7 +10924,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -10980,7 +10980,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11033,7 +11033,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11085,7 +11085,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11138,7 +11138,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11193,7 +11193,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11248,7 +11248,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11303,7 +11303,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11355,7 +11355,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11407,7 +11407,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11459,7 +11459,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11511,7 +11511,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11563,7 +11563,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11618,7 +11618,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11673,7 +11673,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11728,7 +11728,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11783,7 +11783,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11835,7 +11835,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11887,7 +11887,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11939,7 +11939,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11991,7 +11991,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12043,7 +12043,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12095,7 +12095,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12147,7 +12147,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12199,7 +12199,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12251,7 +12251,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12303,7 +12303,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12355,7 +12355,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12407,7 +12407,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12459,7 +12459,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12511,7 +12511,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12563,7 +12563,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12615,7 +12615,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12667,7 +12667,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12719,7 +12719,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12771,7 +12771,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12823,7 +12823,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12875,7 +12875,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12927,7 +12927,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12979,7 +12979,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13031,7 +13031,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13087,7 +13087,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13143,7 +13143,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13199,7 +13199,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13251,7 +13251,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13303,7 +13303,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13355,7 +13355,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13407,7 +13407,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13459,7 +13459,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13511,7 +13511,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13563,7 +13563,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13615,7 +13615,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13668,7 +13668,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13721,7 +13721,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13775,7 +13775,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13829,7 +13829,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13883,7 +13883,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13936,7 +13936,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13989,7 +13989,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14042,7 +14042,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14095,7 +14095,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14147,7 +14147,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14200,7 +14200,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14253,7 +14253,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14305,7 +14305,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14357,7 +14357,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14410,7 +14410,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14462,7 +14462,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14514,7 +14514,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14566,7 +14566,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14618,7 +14618,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14670,7 +14670,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14722,7 +14722,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14774,7 +14774,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14826,7 +14826,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14878,7 +14878,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14936,7 +14936,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14990,7 +14990,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15044,7 +15044,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15098,7 +15098,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15152,7 +15152,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15206,7 +15206,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15260,7 +15260,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15314,7 +15314,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15368,7 +15368,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15422,7 +15422,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15476,7 +15476,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15530,7 +15530,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15584,7 +15584,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15638,7 +15638,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15692,7 +15692,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15746,7 +15746,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15800,7 +15800,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15854,7 +15854,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15909,7 +15909,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15964,7 +15964,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16019,7 +16019,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16075,7 +16075,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16131,7 +16131,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16187,7 +16187,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16243,7 +16243,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16299,7 +16299,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16355,7 +16355,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16410,7 +16410,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16465,7 +16465,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16521,7 +16521,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16576,7 +16576,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16630,7 +16630,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16685,7 +16685,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16741,7 +16741,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16796,7 +16796,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16850,7 +16850,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16904,7 +16904,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16959,7 +16959,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17014,7 +17014,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17068,7 +17068,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17123,7 +17123,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17178,7 +17178,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17232,7 +17232,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17286,7 +17286,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17340,7 +17340,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17394,7 +17394,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17449,7 +17449,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17504,7 +17504,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17558,7 +17558,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17612,7 +17612,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17666,7 +17666,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17720,7 +17720,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17774,7 +17774,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17828,7 +17828,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17882,7 +17882,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17936,7 +17936,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17990,7 +17990,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18044,7 +18044,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18098,7 +18098,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18152,7 +18152,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18206,7 +18206,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18260,7 +18260,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18314,7 +18314,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18368,7 +18368,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18422,7 +18422,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18476,7 +18476,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18531,7 +18531,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18598,7 +18598,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18650,7 +18650,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18702,7 +18702,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18754,7 +18754,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18806,7 +18806,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18858,7 +18858,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18910,7 +18910,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18962,7 +18962,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19014,7 +19014,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19066,7 +19066,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19118,7 +19118,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19170,7 +19170,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19222,7 +19222,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19274,7 +19274,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19326,7 +19326,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19378,7 +19378,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19430,7 +19430,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19482,7 +19482,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19537,7 +19537,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19592,7 +19592,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19647,7 +19647,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19702,7 +19702,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19757,7 +19757,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19812,7 +19812,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19868,7 +19868,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19924,7 +19924,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19980,7 +19980,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20036,7 +20036,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20092,7 +20092,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20148,7 +20148,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20204,7 +20204,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20260,7 +20260,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20316,7 +20316,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20372,7 +20372,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20428,7 +20428,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20484,7 +20484,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20540,7 +20540,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20596,7 +20596,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20651,7 +20651,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20706,7 +20706,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20761,7 +20761,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20816,7 +20816,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20871,7 +20871,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20927,7 +20927,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20983,7 +20983,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21039,7 +21039,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21095,7 +21095,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21148,7 +21148,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21200,7 +21200,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21252,7 +21252,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21304,7 +21304,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21359,7 +21359,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21415,7 +21415,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21471,7 +21471,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21527,7 +21527,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21583,7 +21583,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21636,7 +21636,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21689,7 +21689,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21741,7 +21741,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21794,7 +21794,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21849,7 +21849,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21904,7 +21904,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21959,7 +21959,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22014,7 +22014,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22069,7 +22069,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22122,7 +22122,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22175,7 +22175,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22227,7 +22227,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22279,7 +22279,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22331,7 +22331,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22383,7 +22383,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22435,7 +22435,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22490,7 +22490,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22545,7 +22545,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22600,7 +22600,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22655,7 +22655,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22707,7 +22707,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22759,7 +22759,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22811,7 +22811,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22863,7 +22863,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22915,7 +22915,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22967,7 +22967,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23019,7 +23019,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23071,7 +23071,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23123,7 +23123,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23175,7 +23175,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23227,7 +23227,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23279,7 +23279,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23331,7 +23331,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23383,7 +23383,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23435,7 +23435,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23487,7 +23487,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23539,7 +23539,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23591,7 +23591,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23643,7 +23643,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23695,7 +23695,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23747,7 +23747,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23799,7 +23799,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23851,7 +23851,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23903,7 +23903,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23969,7 +23969,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24023,7 +24023,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24077,7 +24077,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24131,7 +24131,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24185,7 +24185,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24239,7 +24239,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24293,7 +24293,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24347,7 +24347,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24401,7 +24401,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24455,7 +24455,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24509,7 +24509,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24563,7 +24563,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24617,7 +24617,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24671,7 +24671,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24725,7 +24725,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24779,7 +24779,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24833,7 +24833,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24887,7 +24887,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24941,7 +24941,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24995,7 +24995,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25049,7 +25049,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25103,7 +25103,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25157,7 +25157,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25211,7 +25211,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25265,7 +25265,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25319,7 +25319,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25373,7 +25373,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25427,7 +25427,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25481,7 +25481,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25535,7 +25535,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25589,7 +25589,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25643,7 +25643,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25697,7 +25697,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25751,7 +25751,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25805,7 +25805,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25859,7 +25859,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25913,7 +25913,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25967,7 +25967,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26021,7 +26021,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26075,7 +26075,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26129,7 +26129,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26183,7 +26183,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26237,7 +26237,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26291,7 +26291,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26345,7 +26345,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26399,7 +26399,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26453,7 +26453,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26507,7 +26507,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26561,7 +26561,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26615,7 +26615,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26669,7 +26669,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26723,7 +26723,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26777,7 +26777,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26831,7 +26831,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26885,7 +26885,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26939,7 +26939,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26993,7 +26993,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27050,7 +27050,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27107,7 +27107,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27164,7 +27164,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27221,7 +27221,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27278,7 +27278,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27335,7 +27335,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27392,7 +27392,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27449,7 +27449,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27506,7 +27506,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27563,7 +27563,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27620,7 +27620,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27677,7 +27677,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27734,7 +27734,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27792,7 +27792,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27850,7 +27850,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27908,7 +27908,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -27966,7 +27966,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28024,7 +28024,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28082,7 +28082,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28140,7 +28140,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28198,7 +28198,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28256,7 +28256,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28314,7 +28314,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28372,7 +28372,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28430,7 +28430,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28488,7 +28488,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28546,7 +28546,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28604,7 +28604,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28662,7 +28662,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28720,7 +28720,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28778,7 +28778,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28836,7 +28836,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28894,7 +28894,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -28952,7 +28952,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29010,7 +29010,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29068,7 +29068,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29126,7 +29126,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29184,7 +29184,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29242,7 +29242,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29300,7 +29300,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29358,7 +29358,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29416,7 +29416,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29474,7 +29474,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29532,7 +29532,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29590,7 +29590,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29648,7 +29648,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29706,7 +29706,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29764,7 +29764,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29821,7 +29821,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29878,7 +29878,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29935,7 +29935,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -29992,7 +29992,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30049,7 +30049,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30106,7 +30106,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30163,7 +30163,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30220,7 +30220,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30277,7 +30277,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30334,7 +30334,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30391,7 +30391,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30448,7 +30448,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30506,7 +30506,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30564,7 +30564,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30622,7 +30622,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30680,7 +30680,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30738,7 +30738,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30796,7 +30796,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30854,7 +30854,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30912,7 +30912,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -30970,7 +30970,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31028,7 +31028,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31086,7 +31086,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31141,7 +31141,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31195,7 +31195,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31249,7 +31249,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31303,7 +31303,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31357,7 +31357,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31411,7 +31411,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31465,7 +31465,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31519,7 +31519,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31573,7 +31573,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31627,7 +31627,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31681,7 +31681,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31735,7 +31735,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31789,7 +31789,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31846,7 +31846,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31904,7 +31904,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -31962,7 +31962,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32020,7 +32020,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32078,7 +32078,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32136,7 +32136,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32194,7 +32194,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32252,7 +32252,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32310,7 +32310,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32368,7 +32368,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32426,7 +32426,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32484,7 +32484,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32539,7 +32539,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32593,7 +32593,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32647,7 +32647,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32702,7 +32702,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32757,7 +32757,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32812,7 +32812,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32866,7 +32866,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32921,7 +32921,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -32976,7 +32976,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33031,7 +33031,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33085,7 +33085,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33139,7 +33139,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33196,7 +33196,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33253,7 +33253,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33310,7 +33310,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33367,7 +33367,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33424,7 +33424,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33481,7 +33481,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33538,7 +33538,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33595,7 +33595,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33652,7 +33652,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33709,7 +33709,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33766,7 +33766,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33823,7 +33823,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33878,7 +33878,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33933,7 +33933,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -33987,7 +33987,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34041,7 +34041,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34095,7 +34095,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34149,7 +34149,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34203,7 +34203,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34257,7 +34257,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34311,7 +34311,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34365,7 +34365,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34419,7 +34419,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34473,7 +34473,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34527,7 +34527,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34581,7 +34581,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34635,7 +34635,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34689,7 +34689,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34743,7 +34743,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34797,7 +34797,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34854,7 +34854,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34911,7 +34911,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -34968,7 +34968,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35025,7 +35025,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35082,7 +35082,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35139,7 +35139,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35196,7 +35196,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35253,7 +35253,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35310,7 +35310,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35367,7 +35367,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35424,7 +35424,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35478,7 +35478,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35532,7 +35532,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35586,7 +35586,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35640,7 +35640,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35694,7 +35694,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35748,7 +35748,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35802,7 +35802,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35856,7 +35856,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35910,7 +35910,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -35964,7 +35964,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36018,7 +36018,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36072,7 +36072,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36126,7 +36126,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36180,7 +36180,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36234,7 +36234,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36288,7 +36288,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36342,7 +36342,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36396,7 +36396,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36450,7 +36450,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36504,7 +36504,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36558,7 +36558,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36612,7 +36612,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36666,7 +36666,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36720,7 +36720,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36774,7 +36774,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36828,7 +36828,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36882,7 +36882,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36936,7 +36936,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -36990,7 +36990,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37044,7 +37044,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37098,7 +37098,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37152,7 +37152,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37206,7 +37206,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37260,7 +37260,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37314,7 +37314,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37368,7 +37368,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37422,7 +37422,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37476,7 +37476,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37530,7 +37530,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37584,7 +37584,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37638,7 +37638,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37692,7 +37692,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37746,7 +37746,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37800,7 +37800,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37854,7 +37854,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37908,7 +37908,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -37962,7 +37962,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38016,7 +38016,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38070,7 +38070,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38124,7 +38124,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38178,7 +38178,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38232,7 +38232,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38286,7 +38286,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38340,7 +38340,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38394,7 +38394,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38448,7 +38448,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38502,7 +38502,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38556,7 +38556,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38610,7 +38610,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38664,7 +38664,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38718,7 +38718,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38772,7 +38772,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38826,7 +38826,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38880,7 +38880,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38934,7 +38934,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -38988,7 +38988,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39042,7 +39042,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39096,7 +39096,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39150,7 +39150,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39204,7 +39204,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39258,7 +39258,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39312,7 +39312,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39366,7 +39366,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39420,7 +39420,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39474,7 +39474,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39528,7 +39528,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -39582,7 +39582,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -42968,9 +42968,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -42981,8 +42981,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -43139,9 +43139,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -43152,8 +43152,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -43291,9 +43291,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -43304,8 +43304,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -44811,9 +44811,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -44824,8 +44824,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -44982,9 +44982,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -44995,8 +44995,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -45134,9 +45134,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -45147,8 +45147,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -45902,9 +45902,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -45915,8 +45915,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index bc6a377..e929b05a 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -5771,7 +5771,7 @@
             {
               "device_type": "octopus",
               "os": "ChromeOS",
-              "pool": "chrome.tests"
+              "pool": "chromium.tests"
             }
           ],
           "expiration": 21600,
@@ -5814,7 +5814,7 @@
             {
               "device_type": "octopus",
               "os": "ChromeOS",
-              "pool": "chrome.tests"
+              "pool": "chromium.tests"
             }
           ],
           "expiration": 21600,
@@ -5857,7 +5857,7 @@
             {
               "device_type": "octopus",
               "os": "ChromeOS",
-              "pool": "chrome.tests"
+              "pool": "chromium.tests"
             }
           ],
           "expiration": 21600,
@@ -5904,7 +5904,7 @@
             {
               "device_type": "octopus",
               "os": "ChromeOS",
-              "pool": "chrome.tests"
+              "pool": "chromium.tests"
             }
           ],
           "expiration": 21600,
@@ -5956,7 +5956,7 @@
             {
               "device_type": "octopus",
               "os": "ChromeOS",
-              "pool": "chrome.tests"
+              "pool": "chromium.tests"
             }
           ],
           "expiration": 21600,
@@ -6008,7 +6008,7 @@
             {
               "device_type": "octopus",
               "os": "ChromeOS",
-              "pool": "chrome.tests"
+              "pool": "chromium.tests"
             }
           ],
           "expiration": 21600,
@@ -6052,7 +6052,7 @@
             {
               "device_type": "octopus",
               "os": "ChromeOS",
-              "pool": "chrome.tests"
+              "pool": "chromium.tests"
             }
           ],
           "expiration": 21600,
@@ -6095,7 +6095,7 @@
             {
               "device_type": "octopus",
               "os": "ChromeOS",
-              "pool": "chrome.tests"
+              "pool": "chromium.tests"
             }
           ],
           "expiration": 21600,
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 1ae483d..c462c571 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -10972,7 +10972,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11026,7 +11026,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11080,7 +11080,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11134,7 +11134,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11188,7 +11188,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11242,7 +11242,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11296,7 +11296,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11350,7 +11350,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11404,7 +11404,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11458,7 +11458,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11512,7 +11512,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11566,7 +11566,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11621,7 +11621,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11676,7 +11676,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11730,7 +11730,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11784,7 +11784,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11838,7 +11838,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11893,7 +11893,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -11947,7 +11947,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12001,7 +12001,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12055,7 +12055,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12110,7 +12110,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12164,7 +12164,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12218,7 +12218,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12272,7 +12272,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12326,7 +12326,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12380,7 +12380,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12434,7 +12434,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12488,7 +12488,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12542,7 +12542,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12596,7 +12596,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12650,7 +12650,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12704,7 +12704,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12758,7 +12758,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12812,7 +12812,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12866,7 +12866,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12927,7 +12927,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -12981,7 +12981,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13035,7 +13035,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13089,7 +13089,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13143,7 +13143,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13197,7 +13197,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13251,7 +13251,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13305,7 +13305,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13359,7 +13359,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13413,7 +13413,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13467,7 +13467,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13521,7 +13521,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13575,7 +13575,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13629,7 +13629,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13683,7 +13683,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13737,7 +13737,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13791,7 +13791,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13845,7 +13845,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13900,7 +13900,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -13955,7 +13955,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14010,7 +14010,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14065,7 +14065,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14120,7 +14120,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14176,7 +14176,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14232,7 +14232,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14288,7 +14288,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14344,7 +14344,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14400,7 +14400,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14456,7 +14456,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14512,7 +14512,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14568,7 +14568,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14624,7 +14624,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14680,7 +14680,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14736,7 +14736,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14792,7 +14792,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14847,7 +14847,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14902,7 +14902,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14957,7 +14957,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15012,7 +15012,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15068,7 +15068,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15124,7 +15124,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15180,7 +15180,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15235,7 +15235,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15289,7 +15289,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15343,7 +15343,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15397,7 +15397,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15452,7 +15452,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15508,7 +15508,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15564,7 +15564,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15620,7 +15620,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15675,7 +15675,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15729,7 +15729,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15784,7 +15784,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15839,7 +15839,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15894,7 +15894,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15949,7 +15949,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16004,7 +16004,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16058,7 +16058,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16112,7 +16112,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16166,7 +16166,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16220,7 +16220,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16274,7 +16274,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16329,7 +16329,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16384,7 +16384,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16439,7 +16439,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16494,7 +16494,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16548,7 +16548,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16602,7 +16602,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16656,7 +16656,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16710,7 +16710,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16764,7 +16764,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16818,7 +16818,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16872,7 +16872,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16926,7 +16926,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16980,7 +16980,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17034,7 +17034,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17088,7 +17088,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17142,7 +17142,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17196,7 +17196,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17250,7 +17250,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17304,7 +17304,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17358,7 +17358,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17412,7 +17412,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17466,7 +17466,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17520,7 +17520,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17574,7 +17574,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17628,7 +17628,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17682,7 +17682,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17736,7 +17736,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17790,7 +17790,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17850,7 +17850,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17902,7 +17902,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17954,7 +17954,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18006,7 +18006,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18058,7 +18058,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18110,7 +18110,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18162,7 +18162,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18214,7 +18214,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18266,7 +18266,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18318,7 +18318,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18370,7 +18370,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18422,7 +18422,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18474,7 +18474,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18526,7 +18526,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18578,7 +18578,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18630,7 +18630,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18682,7 +18682,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18734,7 +18734,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18786,7 +18786,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18838,7 +18838,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18890,7 +18890,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18942,7 +18942,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18994,7 +18994,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19046,7 +19046,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19098,7 +19098,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19150,7 +19150,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19202,7 +19202,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19254,7 +19254,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19306,7 +19306,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19358,7 +19358,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19413,7 +19413,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19468,7 +19468,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19523,7 +19523,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19579,7 +19579,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19634,7 +19634,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19689,7 +19689,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19744,7 +19744,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19799,7 +19799,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19855,7 +19855,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19911,7 +19911,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -19967,7 +19967,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20023,7 +20023,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20079,7 +20079,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20135,7 +20135,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20191,7 +20191,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20247,7 +20247,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20303,7 +20303,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20360,7 +20360,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20416,7 +20416,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20472,7 +20472,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20528,7 +20528,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20584,7 +20584,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20640,7 +20640,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20696,7 +20696,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20753,7 +20753,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20809,7 +20809,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20865,7 +20865,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20921,7 +20921,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -20977,7 +20977,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21032,7 +21032,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21087,7 +21087,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21143,7 +21143,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21198,7 +21198,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21253,7 +21253,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21308,7 +21308,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21363,7 +21363,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21419,7 +21419,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21475,7 +21475,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21532,7 +21532,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21588,7 +21588,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21644,7 +21644,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21700,7 +21700,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21753,7 +21753,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21805,7 +21805,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21857,7 +21857,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21909,7 +21909,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -21961,7 +21961,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22013,7 +22013,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22065,7 +22065,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22117,7 +22117,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22172,7 +22172,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22228,7 +22228,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22284,7 +22284,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22341,7 +22341,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22397,7 +22397,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22453,7 +22453,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22509,7 +22509,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22562,7 +22562,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22615,7 +22615,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22668,7 +22668,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22720,7 +22720,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22773,7 +22773,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22828,7 +22828,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22883,7 +22883,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22938,7 +22938,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -22994,7 +22994,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23049,7 +23049,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23104,7 +23104,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23159,7 +23159,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23211,7 +23211,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23263,7 +23263,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23315,7 +23315,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23367,7 +23367,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23419,7 +23419,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23471,7 +23471,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23523,7 +23523,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23575,7 +23575,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23627,7 +23627,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23682,7 +23682,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23737,7 +23737,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23792,7 +23792,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23847,7 +23847,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23902,7 +23902,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -23957,7 +23957,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24012,7 +24012,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24064,7 +24064,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24116,7 +24116,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24168,7 +24168,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24220,7 +24220,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24272,7 +24272,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24324,7 +24324,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24376,7 +24376,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24428,7 +24428,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24480,7 +24480,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24532,7 +24532,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24584,7 +24584,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24636,7 +24636,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24688,7 +24688,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24740,7 +24740,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24792,7 +24792,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24844,7 +24844,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24896,7 +24896,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -24948,7 +24948,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25000,7 +25000,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25052,7 +25052,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25104,7 +25104,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25156,7 +25156,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25208,7 +25208,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25260,7 +25260,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25312,7 +25312,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25364,7 +25364,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25416,7 +25416,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25468,7 +25468,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25520,7 +25520,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25572,7 +25572,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25624,7 +25624,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25676,7 +25676,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25728,7 +25728,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25780,7 +25780,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25832,7 +25832,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25884,7 +25884,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25936,7 +25936,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -25988,7 +25988,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26040,7 +26040,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26092,7 +26092,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26144,7 +26144,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26196,7 +26196,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26248,7 +26248,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -26300,7 +26300,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 90320c30..ace2d1e 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -14946,7 +14946,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -14998,7 +14998,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15050,7 +15050,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15102,7 +15102,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15154,7 +15154,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15206,7 +15206,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15258,7 +15258,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15310,7 +15310,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15362,7 +15362,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15414,7 +15414,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15466,7 +15466,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15518,7 +15518,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15570,7 +15570,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15622,7 +15622,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15674,7 +15674,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15726,7 +15726,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15778,7 +15778,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15830,7 +15830,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15882,7 +15882,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15934,7 +15934,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -15986,7 +15986,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16038,7 +16038,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16090,7 +16090,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16143,7 +16143,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16196,7 +16196,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16248,7 +16248,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16300,7 +16300,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16352,7 +16352,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16404,7 +16404,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16456,7 +16456,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16508,7 +16508,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16560,7 +16560,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16612,7 +16612,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16664,7 +16664,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16716,7 +16716,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16768,7 +16768,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16820,7 +16820,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16872,7 +16872,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16924,7 +16924,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -16976,7 +16976,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17028,7 +17028,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17080,7 +17080,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17132,7 +17132,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17184,7 +17184,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17236,7 +17236,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17288,7 +17288,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17340,7 +17340,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -17392,7 +17392,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -18414,12 +18414,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -18431,8 +18431,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -18605,12 +18605,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -18622,8 +18622,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
@@ -18772,12 +18772,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 114.0.5680.0",
+        "description": "Run with ash-chrome version 114.0.5682.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -18789,8 +18789,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5680.0",
-              "revision": "version:114.0.5680.0"
+              "location": "lacros_version_skew_tests_v114.0.5682.0",
+              "revision": "version:114.0.5682.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.rust.json b/testing/buildbot/chromium.rust.json
index 012e46b..46c6de3 100644
--- a/testing/buildbot/chromium.rust.json
+++ b/testing/buildbot/chromium.rust.json
@@ -742,7 +742,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -784,7 +784,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -826,7 +826,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -869,7 +869,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -912,7 +912,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -958,7 +958,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -1002,7 +1002,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.webrtc.fyi.json b/testing/buildbot/chromium.webrtc.fyi.json
index d4f10f56..63f46f5 100644
--- a/testing/buildbot/chromium.webrtc.fyi.json
+++ b/testing/buildbot/chromium.webrtc.fyi.json
@@ -742,7 +742,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
@@ -794,7 +794,7 @@
             {
               "cipd_package": "infra/tools/mac_toolchain/${platform}",
               "location": ".",
-              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+              "revision": "git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index cbb5d1d8..1087b2f 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -999,7 +999,7 @@
         {
           "cipd_package": 'infra/tools/mac_toolchain/${platform}',
           'location': '.',
-          'revision': 'git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1',
+          'revision': 'git_revision:5468d28877d7106d8ab4f7e23b784578ffc86aff',
         },
       ],
     },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index b0243467..bf9e438 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,16 +22,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5680.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5682.0/test_ash_chrome',
     ],
-    'description': 'Run with ash-chrome version 114.0.5680.0',
+    'description': 'Run with ash-chrome version 114.0.5682.0',
     'identifier': 'Lacros version skew testing ash canary',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v114.0.5680.0',
-          'revision': 'version:114.0.5680.0',
+          'location': 'lacros_version_skew_tests_v114.0.5682.0',
+          'revision': 'version:114.0.5682.0',
         },
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 4852bb7..d5acd98d 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -4479,7 +4479,7 @@
             {
               'os': 'ChromeOS',
               'device_type': 'octopus',
-              'pool': 'chrome.tests',
+              'pool': 'chromium.tests',
             },
           ],
         },
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index a607910..d423553 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -337,7 +337,10 @@
     "skia_path_common.h",
     "skia_path_fuzzer.cc",
   ]
-  deps = [ "//skia" ]
+  deps = [
+    "//base",
+    "//skia",
+  ]
   libfuzzer_options = [ "max_len=256" ]
   if (is_debug) {
     # Disabled due to crashing on SkASSERT (crbug.com/642750, crbug.com/643275).
diff --git a/testing/merge_scripts/code_coverage/convert_to_istanbul_test.py b/testing/merge_scripts/code_coverage/convert_to_istanbul_test.py
index 31504d19..f1d66321 100755
--- a/testing/merge_scripts/code_coverage/convert_to_istanbul_test.py
+++ b/testing/merge_scripts/code_coverage/convert_to_istanbul_test.py
@@ -304,17 +304,17 @@
     def _write_transformations(
         self, source_dir, out_dir,
         original_file_name, input_file_name, output_file_name):
-      original_file = os.path.join(source_dir, original_file_name)
-      input_file = os.path.join(source_dir, input_file_name)
-      output_file = os.path.join(out_dir, output_file_name)
-      node.RunNode([
-        str(_SOURCE_MAP_PROCESSOR),
-        "--originals={}".format(" ".join([original_file])),
-        "--inputs={}".format(" ".join([input_file])),
-        "--outputs={}".format(" ".join([output_file])),
-        "--inline-sourcemaps",
-        "--sourceRoot={}".format(self.sourceRoot),
-      ])
+        original_file = os.path.join(source_dir, original_file_name)
+        input_file = os.path.join(source_dir, input_file_name)
+        output_file = os.path.join(out_dir, output_file_name)
+        node.RunNode([
+            str(_SOURCE_MAP_PROCESSOR),
+            "--originals={}".format(" ".join([original_file])),
+            "--inputs={}".format(" ".join([input_file])),
+            "--outputs={}".format(" ".join([output_file])),
+            "--inline-sourcemaps",
+            "--sourceRoot={}".format(self.sourceRoot),
+        ])
 
     def write_sources(self, *file_path_contents):
         url_to_path_map = {}
@@ -432,5 +432,28 @@
         self.assertEqual(len(istanbul_files), 0)
 
 
+    def test_multiple_coverages_in_multiple_shards(self):
+        coverage_dir_1 = os.path.join(self.coverage_dir, 'coverage1')
+        coverage_dir_2 = os.path.join(self.coverage_dir, 'coverage2')
+        os.makedirs(coverage_dir_1)
+        os.makedirs(coverage_dir_2)
+
+        self.write_sources((('//test.js', 'test.js'), self._TEST_SOURCE_B),
+                           (('//test1.js', 'test1.js'), self._TEST_SOURCE_C))
+        self._write_files(coverage_dir_1,
+                          ('test_coverage_1.cov.json', self._TEST_COVERAGE_B))
+        self._write_files(
+            coverage_dir_2,
+            ('test_coverage_2.cov.json', self._TEST_COVERAGE_DUPLICATE_DOUBLE))
+
+        merger.convert_raw_coverage_to_istanbul(
+            [coverage_dir_1, coverage_dir_2], self.out_dir,
+            self.task_output_dir)
+
+        istanbul_files = self.list_files(
+            os.path.join(self.task_output_dir, 'istanbul'))
+        self.assertEqual(len(istanbul_files), 2)
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/testing/merge_scripts/code_coverage/merge_js_lib.py b/testing/merge_scripts/code_coverage/merge_js_lib.py
index 04c8615..4c935dc1 100644
--- a/testing/merge_scripts/code_coverage/merge_js_lib.py
+++ b/testing/merge_scripts/code_coverage/merge_js_lib.py
@@ -282,7 +282,7 @@
         '--output-dir',
         task_output_dir,
         '--raw-coverage-dirs',
-        ' '.join(raw_coverage_dirs),
+        *raw_coverage_dirs,
     ])
 
 
diff --git a/testing/merge_scripts/code_coverage/merge_js_results.py b/testing/merge_scripts/code_coverage/merge_js_results.py
index 11c6086..2e9a6d8 100755
--- a/testing/merge_scripts/code_coverage/merge_js_results.py
+++ b/testing/merge_scripts/code_coverage/merge_js_results.py
@@ -83,7 +83,7 @@
         javascript_merger.generate_coverage_reports(
             output_dir, params.javascript_coverage_dir)
     except RuntimeError as e:
-        logging.warn('Failed executing istanbul tasks: %s', e)
+        logging.warning('Failed executing istanbul tasks: %s', e)
 
 
 if __name__ == '__main__':
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 3fccf89..b64273e 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2003,28 +2003,6 @@
             ]
         }
     ],
-    "CPSS-OnDeviceGeolocationPredictions": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_20221102",
-                    "params": {
-                        "holdback_chance": "0.3"
-                    },
-                    "enable_features": [
-                        "PermissionOnDeviceGeolocationPredictions"
-                    ]
-                }
-            ]
-        }
-    ],
     "CSSCustomPropertiesAblation": [
         {
             "platforms": [
@@ -2619,6 +2597,22 @@
             ]
         }
     ],
+    "ChromeOSEnableArcvmAAudioMMAP": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "CrOSLateBootArcVmAAudioMMAP"
+                    ],
+                    "min_os_version": "15376.0.0"
+                }
+            ]
+        }
+    ],
     "ChromeOSHoldingSpaceExperiments": [
         {
             "platforms": [
@@ -3454,21 +3448,6 @@
             ]
         }
     ],
-    "CrosDeviceActiveCounting28DayActiveCheckIn": [
-        {
-            "platforms": [
-                "chromeos"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "DeviceActiveClient28DayActiveCheckIn"
-                    ]
-                }
-            ]
-        }
-    ],
     "CrosHiddenNetworkMigration": [
         {
             "platforms": [
@@ -7103,31 +7082,6 @@
             ]
         }
     ],
-    "JourneysContentVisibilityFiltered": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_20230303",
-                    "params": {
-                        "content_visibility_threshold": "0.5",
-                        "supported_locales": "en-US,en,en-AU,en-CA,en-GB"
-                    },
-                    "enable_features": [
-                        "HistoryClustersOnDeviceClustering",
-                        "PageVisibilityPageContentAnnotations"
-                    ]
-                }
-            ]
-        }
-    ],
     "JourneysHide": [
         {
             "platforms": [
@@ -10985,6 +10939,28 @@
             ]
         }
     ],
+    "SafeBrowsingDailyPhishingReportsLimit": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabledv2",
+                    "params": {
+                        "kMaxReportsPerIntervalESB": "3"
+                    },
+                    "enable_features": [
+                        "SafeBrowsingDailyPhishingReportsLimit"
+                    ]
+                }
+            ]
+        }
+    ],
     "SafeBrowsingDelayedWarnings": [
         {
             "platforms": [
@@ -11042,6 +11018,25 @@
             ]
         }
     ],
+    "SafeBrowsingPhishingClassificationESBThreshold": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "SafeBrowsingPhishingClassificationESBThreshold"
+                    ]
+                }
+            ]
+        }
+    ],
     "SafeBrowsingSevenZipEvaluationEnabled": [
         {
             "platforms": [
@@ -11273,21 +11268,6 @@
             ]
         }
     ],
-    "SegmentationPlatformSegmentInfoCache": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "SegmentationPlatformSegmentInfoCache"
-                    ]
-                }
-            ]
-        }
-    ],
     "SegmentationStructuredMetrics": [
         {
             "platforms": [
@@ -12014,25 +11994,6 @@
             ]
         }
     ],
-    "SplitUserMediaQueues": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "SplitUserMediaQueues"
-                    ]
-                }
-            ]
-        }
-    ],
     "StartupProfilePickerWithoutGuest": [
         {
             "platforms": [
@@ -14856,5 +14817,20 @@
                 }
             ]
         }
+    ],
+    "ZeroCopyTabCaptureStudyWin": [
+        {
+            "platforms": [
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled_20230222",
+                    "enable_features": [
+                        "ZeroCopyTabCapture"
+                    ]
+                }
+            ]
+        }
     ]
 }
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 99375ca..7d0f066 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -160,7 +160,9 @@
 /libavif/src
 /libc++-static/libc++.a
 /libdrm/src
-/libei/src
+/libei/bin
+/libei/include
+/libei/lib64
 /libgav1/src
 /libgifcodec
 /libipp/libipp
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn
index e9e2846e..5aed432 100644
--- a/third_party/android_deps/BUILD.gn
+++ b/third_party/android_deps/BUILD.gn
@@ -1072,17 +1072,6 @@
   }
 
   # This is generated, do not edit. Update BuildConfigGenerator.groovy instead.
-  android_aar_prebuilt("google_play_services_fido_java") {
-    aar_path = "libs/com_google_android_gms_play_services_fido/play-services-fido-19.0.0-beta.aar"
-    info_path = "libs/com_google_android_gms_play_services_fido/com_google_android_gms_play_services_fido.info"
-    deps = [
-      ":google_play_services_base_java",
-      ":google_play_services_basement_java",
-      ":google_play_services_tasks_java",
-    ]
-  }
-
-  # This is generated, do not edit. Update BuildConfigGenerator.groovy instead.
   android_aar_prebuilt("google_play_services_gcm_java") {
     aar_path = "libs/com_google_android_gms_play_services_gcm/play-services-gcm-17.0.0.aar"
     info_path = "libs/com_google_android_gms_play_services_gcm/com_google_android_gms_play_services_gcm.info"
diff --git a/third_party/android_deps/additional_readme_paths.json b/third_party/android_deps/additional_readme_paths.json
index 5cc9ca7..606eef7 100644
--- a/third_party/android_deps/additional_readme_paths.json
+++ b/third_party/android_deps/additional_readme_paths.json
@@ -54,7 +54,6 @@
     "libs/com_google_android_gms_play_services_cast_framework",
     "libs/com_google_android_gms_play_services_clearcut",
     "libs/com_google_android_gms_play_services_cloud_messaging",
-    "libs/com_google_android_gms_play_services_fido",
     "libs/com_google_android_gms_play_services_flags",
     "libs/com_google_android_gms_play_services_gcm",
     "libs/com_google_android_gms_play_services_iid",
diff --git a/third_party/android_deps/build.gradle b/third_party/android_deps/build.gradle
index b92e3eeb..49c94501 100644
--- a/third_party/android_deps/build.gradle
+++ b/third_party/android_deps/build.gradle
@@ -74,7 +74,6 @@
     compile 'com.google.android.gms:play-services-location:19.0.1'
     compile 'com.google.android.gms:play-services-vision-common:19.1.3'
     compile 'com.google.android.gms:play-services-vision:20.1.3'
-    compile 'com.google.android.gms:play-services-fido:19.0.0-beta'
 
     // TODO (bjoyce): Remove after androidx migration crbug.com/896775
     // Support v4 libraries
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/3pp/3pp.pb b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/3pp/3pp.pb
deleted file mode 100644
index d743b51b..0000000
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/3pp/3pp.pb
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2021 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This is generated, do not edit. Update BuildConfigGenerator.groovy instead.
-
-create {
-  source {
-    script { name: "fetch.py" }
-  }
-}
-
-upload {
-  pkg_prefix: "chromium/third_party/android_deps/libs"
-  universal: true
-}
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/3pp/fetch.py b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/3pp/fetch.py
deleted file mode 100755
index f4e41a5..0000000
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/3pp/fetch.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This is generated, do not edit. Update BuildConfigGenerator.groovy and
-# 3ppFetch.template instead.
-
-import argparse
-import json
-import os
-import re
-import urllib.request
-
-_REPO_URL = 'https://dl.google.com/dl/android/maven2'
-_GROUP_NAME = 'com/google/android/gms'
-_MODULE_NAME = 'play-services-fido'
-_FILE_EXT = 'aar'
-_OVERRIDE_LATEST = None
-_PATCH_VERSION = 'cr1'
-
-
-def do_latest():
-    if _OVERRIDE_LATEST is not None:
-        print(_OVERRIDE_LATEST + f'.{_PATCH_VERSION}')
-        return
-    maven_metadata_url = '{}/{}/{}/maven-metadata.xml'.format(
-        _REPO_URL, _GROUP_NAME, _MODULE_NAME)
-    metadata = urllib.request.urlopen(maven_metadata_url).read().decode(
-        'utf-8')
-    # Do not parse xml with the python included parser since it is susceptible
-    # to maliciously crafted xmls. Only use regular expression parsing to be
-    # safe. RE should be enough to handle what we need to extract.
-    match = re.search('<latest>([^<]+)</latest>', metadata)
-    if match:
-        latest = match.group(1)
-    else:
-        # if no latest info was found just hope the versions are sorted and the
-        # last one is the latest (as is commonly the case).
-        latest = re.findall('<version>([^<]+)</version>', metadata)[-1]
-    print(latest + f'.{_PATCH_VERSION}')
-
-
-def get_download_url(version):
-    # Remove the patch version when getting the download url
-    version_no_patch, patch = version.rsplit('.', 1)
-    if patch.startswith('cr'):
-        version = version_no_patch
-    file_url = '{0}/{1}/{2}/{3}/{2}-{3}.{4}'.format(_REPO_URL, _GROUP_NAME,
-                                                    _MODULE_NAME, version,
-                                                    _FILE_EXT)
-    file_name = file_url.rsplit('/', 1)[-1]
-
-    partial_manifest = {
-        'url': [file_url],
-        'name': [file_name],
-        'ext': '.' + _FILE_EXT,
-    }
-    print(json.dumps(partial_manifest))
-
-
-def main():
-    ap = argparse.ArgumentParser()
-    sub = ap.add_subparsers()
-
-    latest = sub.add_parser('latest')
-    latest.set_defaults(func=lambda _opts: do_latest())
-
-    download = sub.add_parser('get_url')
-    download.set_defaults(
-        func=lambda _opts: get_download_url(os.environ['_3PP_VERSION']))
-
-    opts = ap.parse_args()
-    opts.func(opts)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/LICENSE b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/LICENSE
deleted file mode 100644
index ea19699..0000000
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/LICENSE
+++ /dev/null
@@ -1,1452 +0,0 @@
-Terms and conditions
-
-This is the Android Software Development Kit License Agreement
-
-1. Introduction
-
-1.1 The Android Software Development Kit (referred to in the License Agreement as the "SDK" and specifically including the Android system files, packaged APIs, and Google APIs add-ons) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the SDK.
-
-1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
-
-1.3 A "compatible implementation" means any Android device that (i) complies with the Android Compatibility Definition document, which can be found at the Android compatibility website (http://source.android.com/compatibility) and which may be updated from time to time; and (ii) successfully passes the Android Compatibility Test Suite (CTS).
-
-1.4 "Google" means Google LLC, a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
-
-
-2. Accepting this License Agreement
-
-2.1 In order to use the SDK, you must first agree to the License Agreement. You may not use the SDK if you do not accept the License Agreement.
-
-2.2 By clicking to accept, you hereby agree to the terms of the License Agreement.
-
-2.3 You may not use the SDK and may not accept the License Agreement if you are a person barred from receiving the SDK under the laws of the United States or other countries, including the country in which you are resident or from which you use the SDK.
-
-2.4 If you are agreeing to be bound by the License Agreement on behalf of your employer or other entity, you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the SDK on behalf of your employer or other entity.
-
-
-3. SDK License from Google
-
-3.1 Subject to the terms of the License Agreement, Google grants you a limited, worldwide, royalty-free, non-assignable, non-exclusive, and non-sublicensable license to use the SDK solely to develop applications for compatible implementations of Android.
-
-3.2 You may not use this SDK to develop applications for other platforms (including non-compatible implementations of Android) or to develop another SDK. You are of course free to develop applications for other platforms, including non-compatible implementations of Android, provided that this SDK is not used for that purpose.
-
-3.3 You agree that Google or third parties own all legal right, title and interest in and to the SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
-
-3.4 You may not use the SDK for any purpose not expressly permitted by the License Agreement.  Except to the extent required by applicable third party licenses, you may not copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the SDK or any part of the SDK.
-
-3.5 Use, reproduction and distribution of components of the SDK licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement.
-
-3.6 You agree that the form and nature of the SDK that Google provides may change without prior notice to you and that future versions of the SDK may be incompatible with applications developed on previous versions of the SDK. You agree that Google may stop (permanently or temporarily) providing the SDK (or any features within the SDK) to you or to users generally at Google's sole discretion, without prior notice to you.
-
-3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
-
-3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the SDK.
-
-
-4. Use of the SDK by You
-
-4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the SDK, including any intellectual property rights that subsist in those applications.
-
-4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a) the License Agreement and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
-
-4.3 You agree that if you use the SDK to develop applications for general public users, you will protect the privacy and legal rights of those users. If the users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If the user provides your application with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, the user has given you permission to do so.
-
-4.4 You agree that you will not engage in any activity with the SDK, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of any third party including, but not limited to, Google or any mobile communications carrier.
-
-4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
-
-4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
-
-
-5. Your Developer Credentials
-
-5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
-
-
-6. Privacy and Information
-
-6.1 In order to continually innovate and improve the SDK, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the SDK are being used and how they are being used. Before any of this information is collected, the SDK will notify you and seek your consent. If you withhold consent, the information will not be collected.
-
-6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in accordance with Google's Privacy Policy.
-
-
-7. Third Party Applications
-
-7.1 If you use the SDK to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
-
-7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
-
-7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party. In that case, the License Agreement does not affect your legal relationship with these third parties.
-
-
-8. Using Android APIs
-
-8.1 Google Data APIs
-
-8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
-
-8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
-
-
-9. Terminating this License Agreement
-
-9.1 The License Agreement will continue to apply until terminated by either you or Google as set out below.
-
-9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the SDK and any relevant developer credentials.
-
-9.3 Google may at any time, terminate the License Agreement with you if:
-(A) you have breached any provision of the License Agreement; or
-(B) Google is required to do so by law; or
-(C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated its relationship with Google or ceased to offer certain parts of the SDK to you; or
-(D) Google decides to no longer provide the SDK or certain parts of the SDK to users in the country in which you are resident or from which you use the service, or the provision of the SDK or certain SDK services to you by Google is, in Google's sole discretion, no longer commercially viable.
-
-9.4 When the License Agreement comes to an end, all of the legal rights, obligations and liabilities that you and Google have benefited from, been subject to (or which have accrued over time whilst the License Agreement has been in force) or which are expressed to continue indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall continue to apply to such rights, obligations and liabilities indefinitely.
-
-
-10. DISCLAIMER OF WARRANTIES
-
-10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
-
-10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE.
-
-10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-
-
-11. LIMITATION OF LIABILITY
-
-11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
-
-
-12. Indemnification
-
-12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes any copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you with the License Agreement.
-
-
-13. Changes to the License Agreement
-
-13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK. When these changes are made, Google will make a new version of the License Agreement available on the website where the SDK is made available.
-
-
-14. General Legal Terms
-
-14.1 The License Agreement constitutes the whole legal agreement between you and Google and governs your use of the SDK (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the SDK.
-
-14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
-
-14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.
-
-14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.
-
-14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
-
-14.6 The rights granted in the License Agreement may not be assigned or transferred by either you or Google without the prior written approval of the other party. Neither you nor Google shall be permitted to delegate their responsibilities or obligations under the License Agreement without the prior written approval of the other party.
-
-14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
-
-
-December 9, 2016
-
-
-AndroidX lifecycle common library, AndroidX lifecycle livedatacore library, AndroidX lifecycle runtime library:
-
-
-   Copyright (c) 2005-2011, The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-
-apksig:
-
-
-   Copyright (c) 2005-2008, The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-
-
-Animal Sniffer:
-
-The MIT License
-
-Copyright (c) 2008 Kohsuke Kawaguchi and codehaus.org.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-
-Checker Framework Annotations:
-
-A few parts of the Checker Framework have more permissive licenses.
-
- * The annotations are licensed under the MIT License.  (The text of this
-   license appears below.)  More specifically, all the parts of the Checker
-   Framework that you might want to include with your own program use the
-   MIT License.  This is the checker-qual.jar file and all the files that
-   appear in it:  every file in a qual/ directory, plus utility files such
-   as NullnessUtil.java, RegexUtil.java, SignednessUtil.java, etc.
-   In addition, the cleanroom implementations of third-party annotations,
-   which the Checker Framework recognizes as aliases for its own
-   annotations, are licensed under the MIT License.
-
-===========================================================================
-
-MIT License:
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-===========================================================================
-
-
-Error Prone:
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-Guava JDK5, J2ObjC, SafeParcelable library:
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-Guava JDK7:
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-   
-
-
-JsInterop Annotations:
-
-Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright 2017 Google Inc.
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-JSR 305:
-
-Copyright (c) 2007-2009, JSR305 expert group
-All rights reserved.
-
-http://www.opensource.org/licenses/bsd-license.php
-
-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 the JSR305 expert group 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.
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/OWNERS
deleted file mode 100644
index aea47a05..0000000
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/README.chromium b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/README.chromium
deleted file mode 100644
index 49ed988..0000000
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/README.chromium
+++ /dev/null
@@ -1,14 +0,0 @@
-Name: play-services-fido
-Short Name: play-services-fido
-URL: https://developers.google.com/android/guides/setup
-Version: 19.0.0-beta
-License: Android Software Development Kit License
-License File: LICENSE
-CPEPrefix: unknown
-Security Critical: yes
-
-Description:
-
-
-Local Modifications:
-No modifications.
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/cipd.yaml b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/cipd.yaml
deleted file mode 100644
index 76ca9f07..0000000
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/cipd.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2018 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# To create CIPD package run the following command.
-# cipd create --pkg-def cipd.yaml -tag version:2@19.0.0-beta.cr1
-package: chromium/third_party/android_deps/libs/com_google_android_gms_play_services_fido
-description: "play-services-fido"
-data:
-- file: play-services-fido-19.0.0-beta.aar
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/com_google_android_gms_play_services_fido.info b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/com_google_android_gms_play_services_fido.info
deleted file mode 100644
index 95177ae..0000000
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/com_google_android_gms_play_services_fido.info
+++ /dev/null
@@ -1,14 +0,0 @@
-# Generated by //build/android/gyp/aar.py
-# To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
-
-aidl = []
-assets = []
-has_classes_jar = true
-has_native_libraries = false
-has_proguard_flags = true
-has_r_text_file = false
-is_manifest_empty = true
-manifest_package = "com.google.android.gms.fido"
-resources = []
-subjar_tuples = []
-subjars = []
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index e43c664..cd0597e 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1647,7 +1647,7 @@
 
 BASE_FEATURE(kSplitUserMediaQueues,
              "SplitUserMediaQueues",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kTextCodecCJKEnabled,
              "TextCodecCJKEnabled",
diff --git a/third_party/blink/public/mojom/conversions/conversions.mojom b/third_party/blink/public/mojom/conversions/conversions.mojom
index 54c2309..787a1be 100644
--- a/third_party/blink/public/mojom/conversions/conversions.mojom
+++ b/third_party/blink/public/mojom/conversions/conversions.mojom
@@ -20,7 +20,7 @@
 
 // Sent from renderer to browser process when a resource request matching the
 // .well-known conversion registration path is intercepted.
-interface ConversionHost {
+interface AttributionHost {
   // Registers a new data host which can register a source or trigger.
   // Called when an attributionsrc attribute is registered, e.g. via an img
   // element. Information will be passed at a later point when the renderer
diff --git a/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom b/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom
index 7abefe8..6a1ef2b 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom
@@ -799,6 +799,7 @@
     kTextWrap = 746,
     kTextBoxTrim = 747,
     kOverlay = 748,
+    kWhiteSpaceCollapse = 749,
     // 1. Add new features above this line (don't change the assigned numbers of
     //    the existing items).
     // 2. Run the src/tools/metrics/histograms/update_use_counter_css.py script
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index 273206c..065de9d44 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3867,6 +3867,7 @@
   kFullscreenAllowedByWindowOpen = 4526,
   kAttributeValueContainsLtOrGt = 4527,
   kV8ImportAssertionDeprecatedSyntax = 4528,
+  kImageCaptureBackgroundBlur = 4529,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index e0901c8..808efb7 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -693,6 +693,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_leaky_relu_options.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_operand_descriptor.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_operand_descriptor.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_pad_options.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_pad_options.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_pool_2d_options.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_pool_2d_options.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_resample_2d_options.cc",
@@ -1390,6 +1392,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_model_format.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_operand_type.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_operand_type.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_padding_mode.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_padding_mode.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_power_preference.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_power_preference.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ml_rounding_type.cc",
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
index b0e34e8..7cc0dc6 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_expr.py
@@ -291,7 +291,8 @@
                 # of [TargetOfExposed] exposure. If this is actually a global,
                 # add it to GLOBAL_NAME_TO_EXECUTION_CONTEXT_CHECK.
                 return _Expr(
-                    "(::logging::NotReachedError::NotReached() << "
+                    "(::logging::NotReachedError::NotReached"
+                    "(__FILE__, __LINE__) << "
                     "\"{} exposure test is not supported at runtime\", false)".
                     format(entry.global_name))
 
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc
index 0c32ed7..78497ef 100644
--- a/third_party/blink/renderer/core/animation/animation.cc
+++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -2254,7 +2254,7 @@
 Animation::RangeBoundary* Animation::ToRangeBoundary(
     absl::optional<TimelineOffset> timeline_offset) {
   if (!timeline_offset) {
-    return MakeGarbageCollected<RangeBoundary>("auto");
+    return MakeGarbageCollected<RangeBoundary>("normal");
   }
 
   TimelineRangeOffset* timeline_range_offset =
diff --git a/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
index 660789e2..7c250f5 100644
--- a/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
@@ -71,8 +71,8 @@
     double alpha,
     double fraction,
     Color color,
-    Color::ColorInterpolationSpace color_interpolation_space) {
-  color.ConvertToColorInterpolationSpace(color_interpolation_space);
+    Color::ColorSpace color_space) {
+  color.ConvertToColorSpace(color_space);
   return std::make_tuple(
       param0 + fraction * color.Param0() * color.FloatAlpha(),
       param1 + fraction * color.Param1() * color.FloatAlpha(),
@@ -99,8 +99,7 @@
   double param1 = color.Param1();
   double param2 = color.Param2();
   double alpha = color.Alpha();
-  Color::ColorInterpolationSpace color_interpolation_space =
-      color.ColorInterpolationSpace();
+  Color::ColorSpace color_space = color.ColorSpace();
 
   if (double currentcolor_fraction = color.GetColorFraction(
           InterpolableColor::ColorKeyword::kCurrentcolor)) {
@@ -126,27 +125,27 @@
         param0, param1, param2, alpha, currentcolor_fraction,
         current_style_color.Resolve(Color(),
                                     state.StyleBuilder().UsedColorScheme()),
-        color_interpolation_space);
+        color_space);
   }
   const TextLinkColors& colors = state.GetDocument().GetTextLinkColors();
   if (double webkit_activelink_fraction = color.GetColorFraction(
           InterpolableColor::ColorKeyword::kWebkitActivelink)) {
     std::tie(param0, param1, param2, alpha) = AddPremultipliedColor(
         param0, param1, param2, alpha, webkit_activelink_fraction,
-        colors.ActiveLinkColor(), color_interpolation_space);
+        colors.ActiveLinkColor(), color_space);
   }
   if (double webkit_link_fraction = color.GetColorFraction(
           InterpolableColor::ColorKeyword::kWebkitLink)) {
     std::tie(param0, param1, param2, alpha) = AddPremultipliedColor(
         param0, param1, param2, alpha, webkit_link_fraction,
         is_visited ? colors.VisitedLinkColor() : colors.LinkColor(),
-        color_interpolation_space);
+        color_space);
   }
   if (double quirk_inherit_fraction = color.GetColorFraction(
           InterpolableColor::ColorKeyword::kQuirkInherit)) {
     std::tie(param0, param1, param2, alpha) = AddPremultipliedColor(
         param0, param1, param2, alpha, quirk_inherit_fraction,
-        colors.TextColor(), color_interpolation_space);
+        colors.TextColor(), color_space);
   }
 
   alpha = ClampTo<double>(alpha, 0, 1);
@@ -155,12 +154,10 @@
   std::tie(param0, param1, param2) =
       UnpremultiplyColor(param0, param1, param2, alpha);
 
-  switch (color_interpolation_space) {
-    case Color::ColorInterpolationSpace::kSRGB:
-      return Color::FromRGBAFloat(param0, param1, param2, alpha);
-    case Color::ColorInterpolationSpace::kOklab:
-      return Color::FromColorSpace(Color::ColorSpace::kOklab, param0, param1,
-                                   param2, alpha);
+  switch (color_space) {
+    case Color::ColorSpace::kSRGBLegacy:
+    case Color::ColorSpace::kOklab:
+      return Color::FromColorSpace(color_space, param0, param1, param2, alpha);
     default:
       // There is no way for the user to specify which color spaces should be
       // used for interpolation, so sRGB (for legacy colors) and Oklab are
diff --git a/third_party/blink/renderer/core/animation/css_color_interpolation_type_test.cc b/third_party/blink/renderer/core/animation/css_color_interpolation_type_test.cc
index 01cd9a6..909cfc6 100644
--- a/third_party/blink/renderer/core/animation/css_color_interpolation_type_test.cc
+++ b/third_party/blink/renderer/core/animation/css_color_interpolation_type_test.cc
@@ -67,21 +67,18 @@
       CSSColorInterpolationType::CreateInterpolableColor(to_color);
 
   from_color = CSSColorInterpolationType::GetColor(*from);
-  ASSERT_EQ(Color::ColorInterpolationSpace::kSRGB,
+  ASSERT_EQ(Color::ColorSpace::kSRGBLegacy,
             from_color.GetColorInterpolationSpace());
   to_color = CSSColorInterpolationType::GetColor(*to);
-  ASSERT_EQ(Color::ColorInterpolationSpace::kOklab,
-            to_color.GetColorInterpolationSpace());
+  ASSERT_EQ(Color::ColorSpace::kOklab, to_color.GetColorInterpolationSpace());
 
   // This should make both color interpolations spaces oklab
   InterpolableColor::SetupColorInterpolationSpaces(*to, *from);
 
   from_color = CSSColorInterpolationType::GetColor(*from);
-  ASSERT_EQ(Color::ColorInterpolationSpace::kOklab,
-            from_color.GetColorInterpolationSpace());
+  ASSERT_EQ(Color::ColorSpace::kOklab, from_color.GetColorInterpolationSpace());
   to_color = CSSColorInterpolationType::GetColor(*to);
-  ASSERT_EQ(Color::ColorInterpolationSpace::kOklab,
-            to_color.GetColorInterpolationSpace());
+  ASSERT_EQ(Color::ColorSpace::kOklab, to_color.GetColorInterpolationSpace());
 }
 
 TEST(CSSColorInterpolationTypeTest, Oklab) {
@@ -103,7 +100,7 @@
   ASSERT_EQ(1, result_color.Param1());
   ASSERT_EQ(1, result_color.Param2());
   ASSERT_EQ(1, result_color.FloatAlpha());
-  ASSERT_EQ(Color::ColorInterpolationSpace::kOklab,
+  ASSERT_EQ(Color::ColorSpace::kOklab,
             result_color.GetColorInterpolationSpace());
 
   from->Interpolate(*to, 0.5, *result);
@@ -113,7 +110,7 @@
   ASSERT_EQ(0.5, result_color.Param1() * result_color.FloatAlpha());
   ASSERT_EQ(0.5, result_color.Param2() * result_color.FloatAlpha());
   ASSERT_EQ(0.75, result_color.FloatAlpha());
-  ASSERT_EQ(Color::ColorInterpolationSpace::kOklab,
+  ASSERT_EQ(Color::ColorSpace::kOklab,
             result_color.GetColorInterpolationSpace());
 
   from->Interpolate(*to, 0.75, *result);
@@ -123,7 +120,7 @@
   ASSERT_EQ(0.25, result_color.Param1() * result_color.FloatAlpha());
   ASSERT_EQ(0.25, result_color.Param2() * result_color.FloatAlpha());
   ASSERT_EQ(0.625, result_color.FloatAlpha());
-  ASSERT_EQ(Color::ColorInterpolationSpace::kOklab,
+  ASSERT_EQ(Color::ColorSpace::kOklab,
             result_color.GetColorInterpolationSpace());
 
   from->Interpolate(*to, 1, *result);
@@ -132,7 +129,7 @@
   ASSERT_EQ(0, result_color.Param1());
   ASSERT_EQ(0, result_color.Param2());
   ASSERT_EQ(0.5, result_color.FloatAlpha());
-  ASSERT_EQ(Color::ColorInterpolationSpace::kOklab,
+  ASSERT_EQ(Color::ColorSpace::kOklab,
             result_color.GetColorInterpolationSpace());
 }
 
diff --git a/third_party/blink/renderer/core/animation/interpolable_color.cc b/third_party/blink/renderer/core/animation/interpolable_color.cc
index b667a003..9dff7cbd 100644
--- a/third_party/blink/renderer/core/animation/interpolable_color.cc
+++ b/third_party/blink/renderer/core/animation/interpolable_color.cc
@@ -20,10 +20,10 @@
 std::unique_ptr<InterpolableColor> InterpolableColor::Create(Color color) {
   std::unique_ptr<InterpolableColor> result =
       std::make_unique<InterpolableColor>();
-  result->color_interpolation_space_ = color.GetColorInterpolationSpace();
+  result->color_space_ = color.GetColorInterpolationSpace();
 
   // A color is not necessarily "in" it's desired interpolation space.
-  color.ConvertToColorInterpolationSpace(result->color_interpolation_space_);
+  color.ConvertToColorSpace(result->color_space_);
 
   // All params are stored pre-multiplied.
   // https://www.w3.org/TR/css-color-4/#interpolation-alpha
@@ -49,7 +49,7 @@
   // the proper fraction of the keyword color is added in.
   result->color_keyword_fractions_.Set(keyword_index, InterpolableNumber(1));
   // Keyword colors are functionally legacy colors for interpolation.
-  result->color_interpolation_space_ = Color::ColorInterpolationSpace::kSRGB;
+  result->color_space_ = Color::ColorSpace::kSRGBLegacy;
 
   return result;
 }
@@ -83,28 +83,27 @@
     InterpolableNumber param2,
     InterpolableNumber alpha,
     InterpolableNumberList color_keyword_fractions,
-    Color::ColorInterpolationSpace color_interpolation_space)
+    Color::ColorSpace color_space)
     : param0_(std::move(param0)),
       param1_(std::move(param1)),
       param2_(std::move(param2)),
       alpha_(std::move(alpha)),
       color_keyword_fractions_(std::move(color_keyword_fractions)),
-      color_interpolation_space_(color_interpolation_space) {
+      color_space_(color_space) {
   DCHECK_EQ(color_keyword_fractions_.length(), kColorKeywordCount);
 }
 
 InterpolableColor* InterpolableColor::RawClone() const {
   DCHECK_EQ(color_keyword_fractions_.length(), kColorKeywordCount);
   return new InterpolableColor(param0_, param1_, param2_, alpha_,
-                               color_keyword_fractions_.Clone(),
-                               color_interpolation_space_);
+                               color_keyword_fractions_.Clone(), color_space_);
 }
 
 InterpolableColor* InterpolableColor::RawCloneAndZero() const {
   return new InterpolableColor(InterpolableNumber(0), InterpolableNumber(0),
                                InterpolableNumber(0), InterpolableNumber(0),
                                color_keyword_fractions_.CloneAndZero(),
-                               color_interpolation_space_);
+                               color_space_);
 }
 
 Color InterpolableColor::GetColor() const {
@@ -118,16 +117,14 @@
   float param2 = param2_.Value() / alpha_.Value();
   float alpha = ClampTo<double>(alpha_.Value(), 0, 1);
 
-  switch (color_interpolation_space_) {
-    case Color::ColorInterpolationSpace::kSRGB:
-      return Color::FromRGBAFloat(param0, param1, param2, alpha);
-    case Color::ColorInterpolationSpace::kOklab:
-      return Color::FromColorSpace(Color::ColorSpace::kOklab, param0, param1,
-                                   param2, alpha);
+  switch (color_space_) {
+    // There is no way for the user to specify which color spaces should be
+    // used for interpolation, so sRGB (for legacy colors) and Oklab are the
+    // only possibilities.
+    case Color::ColorSpace::kSRGBLegacy:
+    case Color::ColorSpace::kOklab:
+      return Color::FromColorSpace(color_space_, param0, param1, param2, alpha);
     default:
-      // There is no way for the user to specify which color spaces should be
-      // used for interpolation, so sRGB (for legacy colors) and Oklab are the
-      // only possibilities.
       NOTREACHED();
       return Color();
   }
@@ -136,7 +133,7 @@
 void InterpolableColor::AssertCanInterpolateWith(
     const InterpolableValue& other) const {
   const InterpolableColor& other_color = To<InterpolableColor>(other);
-  DCHECK_EQ(color_interpolation_space_, other_color.color_interpolation_space_);
+  DCHECK_EQ(color_space_, other_color.color_space_);
   param0_.AssertCanInterpolateWith(other_color.param0_);
   param1_.AssertCanInterpolateWith(other_color.param1_);
   param2_.AssertCanInterpolateWith(other_color.param2_);
@@ -158,37 +155,36 @@
   return true;
 }
 
-void InterpolableColor::ConvertToColorInterpolationSpace(
-    Color::ColorInterpolationSpace color_interpolation_space) {
-  if (color_interpolation_space_ == color_interpolation_space)
+void InterpolableColor::ConvertToColorSpace(Color::ColorSpace color_space) {
+  if (color_space_ == color_space) {
     return;
+  }
 
   Color underlying_color = GetColor();
-  underlying_color.ConvertToColorInterpolationSpace(color_interpolation_space);
+  underlying_color.ConvertToColorSpace(color_space);
   param0_.Set(underlying_color.Param0() * underlying_color.FloatAlpha());
   param1_.Set(underlying_color.Param1() * underlying_color.FloatAlpha());
   param2_.Set(underlying_color.Param2() * underlying_color.FloatAlpha());
   alpha_.Set(underlying_color.FloatAlpha());
 
-  color_interpolation_space_ = color_interpolation_space;
+  color_space_ = color_space;
 }
 
 // static
 void InterpolableColor::SetupColorInterpolationSpaces(InterpolableColor& to,
                                                       InterpolableColor& from) {
   // In the event that the two colorspaces are the same, there's nothing to do.
-  if (to.color_interpolation_space_ == from.color_interpolation_space_)
+  if (to.color_space_ == from.color_space_) {
     return;
+  }
 
   // sRGB and Oklab are the only possible interpolation spaces, so one should be
   // in Oklab and we should convert the other.
-  DCHECK(from.color_interpolation_space_ ==
-             Color::ColorInterpolationSpace::kOklab ||
-         to.color_interpolation_space_ ==
-             Color::ColorInterpolationSpace::kOklab);
+  DCHECK(from.color_space_ == Color::ColorSpace::kOklab ||
+         to.color_space_ == Color::ColorSpace::kOklab);
 
-  to.ConvertToColorInterpolationSpace(Color::ColorInterpolationSpace::kOklab);
-  from.ConvertToColorInterpolationSpace(Color::ColorInterpolationSpace::kOklab);
+  to.ConvertToColorSpace(Color::ColorSpace::kOklab);
+  from.ConvertToColorSpace(Color::ColorSpace::kOklab);
 }
 
 void InterpolableColor::Scale(double scale) {
@@ -234,9 +230,8 @@
   const InterpolableColor& to_color = To<InterpolableColor>(to);
   InterpolableColor& result_color = To<InterpolableColor>(result);
 
-  DCHECK_EQ(to_color.color_interpolation_space_, color_interpolation_space_);
-  DCHECK_EQ(result_color.color_interpolation_space_,
-            color_interpolation_space_);
+  DCHECK_EQ(to_color.color_space_, color_space_);
+  DCHECK_EQ(result_color.color_space_, color_space_);
 
   param0_.Interpolate(to_color.param0_, progress, result_color.param0_);
   param1_.Interpolate(to_color.param1_, progress, result_color.param1_);
diff --git a/third_party/blink/renderer/core/animation/interpolable_color.h b/third_party/blink/renderer/core/animation/interpolable_color.h
index 08a535c..ace643f 100644
--- a/third_party/blink/renderer/core/animation/interpolable_color.h
+++ b/third_party/blink/renderer/core/animation/interpolable_color.h
@@ -67,9 +67,7 @@
   double Param1() const { return param1_.Value(); }
   double Param2() const { return param2_.Value(); }
   double Alpha() const { return alpha_.Value(); }
-  Color::ColorInterpolationSpace ColorInterpolationSpace() const {
-    return color_interpolation_space_;
-  }
+  Color::ColorSpace ColorSpace() const { return color_space_; }
 
   double GetColorFraction(ColorKeyword keyword) const {
     int keyword_index = static_cast<int>(keyword);
@@ -91,10 +89,9 @@
                     InterpolableNumber param2,
                     InterpolableNumber alpha,
                     InterpolableNumberList color_keyword_fractions,
-                    Color::ColorInterpolationSpace color_interpolation_space);
+                    Color::ColorSpace color_space);
 
-  void ConvertToColorInterpolationSpace(
-      Color::ColorInterpolationSpace color_interpolation_space);
+  void ConvertToColorSpace(Color::ColorSpace color_space);
   InterpolableColor* RawClone() const final;
   InterpolableColor* RawCloneAndZero() const final;
 
@@ -107,8 +104,7 @@
 
   InterpolableNumberList color_keyword_fractions_;
 
-  Color::ColorInterpolationSpace color_interpolation_space_ =
-      Color::ColorInterpolationSpace::kNone;
+  Color::ColorSpace color_space_ = Color::ColorSpace::kNone;
 };
 
 template <>
diff --git a/third_party/blink/renderer/core/animation/keyframe_animation_options.idl b/third_party/blink/renderer/core/animation/keyframe_animation_options.idl
index 6ec09cb0..a58acd1 100644
--- a/third_party/blink/renderer/core/animation/keyframe_animation_options.idl
+++ b/third_party/blink/renderer/core/animation/keyframe_animation_options.idl
@@ -24,6 +24,6 @@
 dictionary KeyframeAnimationOptions : KeyframeEffectOptions {
     DOMString id = "";
     AnimationTimeline? timeline;
-    (DOMString or TimelineRangeOffset) rangeStart = "auto";
-    (DOMString or TimelineRangeOffset) rangeEnd =  "auto";
+    (DOMString or TimelineRangeOffset) rangeStart = "normal";
+    (DOMString or TimelineRangeOffset) rangeEnd =  "normal";
 };
diff --git a/third_party/blink/renderer/core/animation/timeline_offset.cc b/third_party/blink/renderer/core/animation/timeline_offset.cc
index daa95ef..df94924 100644
--- a/third_party/blink/renderer/core/animation/timeline_offset.cc
+++ b/third_party/blink/renderer/core/animation/timeline_offset.cc
@@ -59,7 +59,7 @@
 
 String TimelineOffset::ToString() const {
   if (name == NamedRange::kNone) {
-    return "auto";
+    return "normal";
   }
 
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
@@ -89,24 +89,20 @@
   CSSParserTokenRange range(tokens);
   range.ConsumeWhitespace();
 
-  // Note that we use "auto" to represent nullopt here, unlike CSS which
-  // uses "normal".
-  if (css_parsing_utils::ConsumeIdent<CSSValueID::kAuto>(range)) {
-    if (!range.AtEnd()) {
-      ThrowExcpetionForInvalidTimelineOffset(exception_state);
-    }
-    return absl::nullopt;
-  }
-
   const CSSValue* value = css_parsing_utils::ConsumeAnimationRange(
       range, *document.ElementSheet().Contents()->ParserContext(),
       /* default_offset_percent */ default_percent);
 
-  if (!value || !value->IsValueList() || !range.AtEnd()) {
+  if (!value || !range.AtEnd()) {
     ThrowExcpetionForInvalidTimelineOffset(exception_state);
     return absl::nullopt;
   }
 
+  if (IsA<CSSIdentifierValue>(value)) {
+    DCHECK_EQ(CSSValueID::kNormal, To<CSSIdentifierValue>(*value).GetValueID());
+    return absl::nullopt;
+  }
+
   const auto& list = To<CSSValueList>(*value);
 
   // TODO(kevers): Keep track of style dependent lengths in order
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni
index 05608a9..b4dc1a33 100644
--- a/third_party/blink/renderer/core/css/build.gni
+++ b/third_party/blink/renderer/core/css/build.gni
@@ -837,4 +837,5 @@
   "threaded/filter_operation_resolver_threaded_test.cc",
   "threaded/font_object_threaded_test.cc",
   "threaded/text_renderer_threaded_test.cc",
+  "white_space_test.cc",
 ]
diff --git a/third_party/blink/renderer/core/css/css_color_mix_value.cc b/third_party/blink/renderer/core/css/css_color_mix_value.cc
index ee7a44b..394acef 100644
--- a/third_party/blink/renderer/core/css/css_color_mix_value.cc
+++ b/third_party/blink/renderer/core/css/css_color_mix_value.cc
@@ -64,8 +64,8 @@
   // Color keywords should be handled similarly.
   StringBuilder result;
   result.Append("color-mix(in ");
-  result.Append(Color::ColorInterpolationSpaceToString(
-      color_interpolation_space_, hue_interpolation_method_));
+  result.Append(Color::SerializeInterpolationSpace(color_interpolation_space_,
+                                                   hue_interpolation_method_));
   result.Append(", ");
   result.Append(color1_->CssText());
   if (percentage1_) {
diff --git a/third_party/blink/renderer/core/css/css_color_mix_value.h b/third_party/blink/renderer/core/css/css_color_mix_value.h
index ddda23a1..8b65d12 100644
--- a/third_party/blink/renderer/core/css/css_color_mix_value.h
+++ b/third_party/blink/renderer/core/css/css_color_mix_value.h
@@ -19,13 +19,12 @@
 // https://www.w3.org/TR/css-color-5/#color-mix
 class CORE_EXPORT CSSColorMixValue : public CSSValue {
  public:
-  CSSColorMixValue(
-      const CSSValue* color1,
-      const CSSValue* color2,
-      const CSSPrimitiveValue* p1,
-      const CSSPrimitiveValue* p2,
-      const Color::ColorInterpolationSpace color_interpolation_space,
-      const Color::HueInterpolationMethod hue_interpolation_method)
+  CSSColorMixValue(const CSSValue* color1,
+                   const CSSValue* color2,
+                   const CSSPrimitiveValue* p1,
+                   const CSSPrimitiveValue* p2,
+                   const Color::ColorSpace color_interpolation_space,
+                   const Color::HueInterpolationMethod hue_interpolation_method)
       : CSSValue(kColorMixClass),
         color1_(color1),
         color2_(color2),
@@ -44,7 +43,7 @@
   const CSSValue& Color2() const { return *color2_; }
   const CSSPrimitiveValue* Percentage1() const { return percentage1_; }
   const CSSPrimitiveValue* Percentage2() const { return percentage2_; }
-  Color::ColorInterpolationSpace ColorInterpolationSpace() const {
+  Color::ColorSpace ColorInterpolationSpace() const {
     return color_interpolation_space_;
   }
   Color::HueInterpolationMethod HueInterpolationMethod() const {
@@ -61,7 +60,7 @@
   Member<const CSSValue> color2_;
   Member<const CSSPrimitiveValue> percentage1_;
   Member<const CSSPrimitiveValue> percentage2_;
-  const Color::ColorInterpolationSpace color_interpolation_space_;
+  const Color::ColorSpace color_interpolation_space_;
   const Color::HueInterpolationMethod hue_interpolation_method_;
 };
 
diff --git a/third_party/blink/renderer/core/css/css_gradient_value.cc b/third_party/blink/renderer/core/css/css_gradient_value.cc
index 6ba04449..d28de862 100644
--- a/third_party/blink/renderer/core/css/css_gradient_value.cc
+++ b/third_party/blink/renderer/core/css/css_gradient_value.cc
@@ -219,7 +219,7 @@
 static void ReplaceColorHintsWithColorStops(
     Vector<GradientStop>& stops,
     const HeapVector<CSSGradientColorStop, 2>& css_gradient_stops,
-    Color::ColorInterpolationSpace color_interpolation_space,
+    Color::ColorSpace color_interpolation_space,
     Color::HueInterpolationMethod hue_interpolation_method) {
   // This algorithm will replace each color interpolation hint with 9 regular
   // color stops. The color values for the new color stops will be calculated
@@ -238,8 +238,8 @@
 
   // Support legacy gradients with color hints when no interpolation space is
   // specified.
-  if (color_interpolation_space == Color::ColorInterpolationSpace::kNone) {
-    color_interpolation_space = Color::ColorInterpolationSpace::kSRGBLegacy;
+  if (color_interpolation_space == Color::ColorSpace::kNone) {
+    color_interpolation_space = Color::ColorSpace::kSRGBLegacy;
   }
 
   int index_offset = 0;
@@ -484,12 +484,12 @@
 // value for that point.
 void ClampNegativeOffsets(
     Vector<GradientStop>& stops,
-    Color::ColorInterpolationSpace color_interpolation_space,
+    Color::ColorSpace color_interpolation_space,
     Color::HueInterpolationMethod hue_interpolation_method) {
   // Support legacy gradients with color hints when no interpolation space is
   // specified.
-  if (color_interpolation_space == Color::ColorInterpolationSpace::kNone) {
-    color_interpolation_space = Color::ColorInterpolationSpace::kSRGBLegacy;
+  if (color_interpolation_space == Color::ColorSpace::kNone) {
+    color_interpolation_space = Color::ColorSpace::kSRGBLegacy;
   }
   float last_negative_offset = 0;
 
@@ -883,7 +883,7 @@
 }
 
 bool CSSGradientValue::ShouldSerializeColorSpace() const {
-  if (color_interpolation_space_ == Color::ColorInterpolationSpace::kNone) {
+  if (color_interpolation_space_ == Color::ColorSpace::kNone) {
     return false;
   }
 
@@ -897,14 +897,14 @@
   // OKLab is the default and should not be serialized unless all colors are
   // legacy colors.
   if (!has_only_legacy_colors &&
-      color_interpolation_space_ == Color::ColorInterpolationSpace::kOklab) {
+      color_interpolation_space_ == Color::ColorSpace::kOklab) {
     return false;
   }
 
   // sRGB is the default if all colors are legacy colors and should not be
   // serialized.
   if (has_only_legacy_colors &&
-      color_interpolation_space_ == Color::ColorInterpolationSpace::kSRGB) {
+      color_interpolation_space_ == Color::ColorSpace::kSRGB) {
     return false;
   }
 
@@ -985,7 +985,7 @@
       }
       wrote_something = true;
       result.Append("in ");
-      result.Append(Color::ColorInterpolationSpaceToString(
+      result.Append(Color::SerializeInterpolationSpace(
           color_interpolation_space_, hue_interpolation_method_));
     }
 
@@ -1371,7 +1371,7 @@
 
     if (ShouldSerializeColorSpace()) {
       result.Append(" in ");
-      result.Append(Color::ColorInterpolationSpaceToString(
+      result.Append(Color::SerializeInterpolationSpace(
           color_interpolation_space_, hue_interpolation_method_));
     }
 
@@ -1421,7 +1421,7 @@
       }
       result.Append("in ");
       wrote_something = true;
-      result.Append(Color::ColorInterpolationSpaceToString(
+      result.Append(Color::SerializeInterpolationSpace(
           color_interpolation_space_, hue_interpolation_method_));
     }
 
@@ -1748,7 +1748,7 @@
     }
     result.Append("in ");
     wrote_something = true;
-    result.Append(Color::ColorInterpolationSpaceToString(
+    result.Append(Color::SerializeInterpolationSpace(
         color_interpolation_space_, hue_interpolation_method_));
   }
 
diff --git a/third_party/blink/renderer/core/css/css_gradient_value.h b/third_party/blink/renderer/core/css/css_gradient_value.h
index 82d904a..8b91a0ab 100644
--- a/third_party/blink/renderer/core/css/css_gradient_value.h
+++ b/third_party/blink/renderer/core/css/css_gradient_value.h
@@ -122,7 +122,7 @@
   void TraceAfterDispatch(blink::Visitor*) const;
 
   void SetColorInterpolationSpace(
-      Color::ColorInterpolationSpace color_interpolation_space,
+      Color::ColorSpace color_interpolation_space,
       Color::HueInterpolationMethod hue_interpolation_method) {
     color_interpolation_space_ = color_interpolation_space;
     hue_interpolation_method_ = hue_interpolation_method;
@@ -160,8 +160,7 @@
   CSSGradientType gradient_type_;
   bool repeating_ : 1;
   bool is_cacheable_ : 1;
-  Color::ColorInterpolationSpace color_interpolation_space_ =
-      Color::ColorInterpolationSpace::kNone;
+  Color::ColorSpace color_interpolation_space_ = Color::ColorSpace::kNone;
   Color::HueInterpolationMethod hue_interpolation_method_ =
       Color::HueInterpolationMethod::kShorter;
 };
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 33f1c93..4338d47 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -5894,24 +5894,51 @@
       inherited: true,
       // This property is "keyword" but use "primitive" to use `EWhiteSpace` defined manually.
       field_template: "primitive",
-      field_size: 4,  // Ensure this is in sync with `kEWhiteSpaceBits`.
+      // The values are stored in `white-space-collapse` and `text-wrap` by
+      // `computed_style_custom_functions` even when `CSSWhiteSpaceShorthand`
+      // is off, but give 1 bit to it because `field_size` can't be zero.
+      field_size: 1,
       include_paths: ["third_party/blink/renderer/core/css/white_space.h"],
       keywords: [
         "normal", "pre", "pre-wrap", "pre-line", "nowrap", "break-spaces"
       ],
-      style_builder_custom_functions: ["initial", "inherit", "value"],
+      computed_style_custom_functions: ["getter", "setter", "resetter"],
       typedom_types: ["Keyword"],
       default_value: "EWhiteSpace::kNormal",
       valid_for_cue: true,
       valid_for_marker: true,
     },
     {
+      name: "-alternative-white-space",
+      alternative_of: "white-space",
+      longhands: [
+        "white-space-collapse", "text-wrap"
+      ],
+      property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
+      runtime_flag: "CSSWhiteSpaceShorthand",
+    },
+    {
+      name: "white-space-collapse",
+      property_methods: ["CSSValueFromComputedStyleInternal"],
+      inherited: true,
+      field_template: "primitive",
+      field_size: 2,  // Ensure this is in sync with `kWhiteSpaceCollapseBits`.
+      type_name: "WhiteSpaceCollapse",
+      keywords: ["collapse", "preserve", "preserve-breaks", "break-spaces"],
+      default_value: "WhiteSpaceCollapse::kCollapse",
+      include_paths: ["third_party/blink/renderer/core/css/white_space.h"],
+      typedom_types: ["Keyword"],
+      valid_for_cue: true,
+      valid_for_marker: true,
+      runtime_flag: "CSSWhiteSpaceShorthand",
+    },
+    {
       name: "text-wrap",
       property_methods: ["CSSValueFromComputedStyleInternal"],
       inherited: true,
       field_template: "primitive",
-      field_size: 1,  // Ensure this is in sync with `kTextWrapBits`.
-      keywords: ["wrap", "balance"],
+      field_size: 2,  // Ensure this is in sync with `kTextWrapBits`.
+      keywords: ["wrap", "nowrap", "balance"],
       type_name: "TextWrap",
       default_value: "TextWrap::kWrap",
       include_paths: ["third_party/blink/renderer/core/css/white_space.h"],
diff --git a/third_party/blink/renderer/core/css/css_properties_ranking.json5 b/third_party/blink/renderer/core/css/css_properties_ranking.json5
index a057022..9e308101 100644
--- a/third_party/blink/renderer/core/css/css_properties_ranking.json5
+++ b/third_party/blink/renderer/core/css/css_properties_ranking.json5
@@ -46,6 +46,8 @@
         "padding-right",
         "transform",
         "white-space",
+        "white-space-collapse",
+        "text-wrap",
         "padding-bottom",
         "min-height",
         "background-image",
diff --git a/third_party/blink/renderer/core/css/css_property_equality.cc b/third_party/blink/renderer/core/css/css_property_equality.cc
index 9a503e9..54f05c70 100644
--- a/third_party/blink/renderer/core/css/css_property_equality.cc
+++ b/third_party/blink/renderer/core/css/css_property_equality.cc
@@ -811,6 +811,8 @@
       return a.GetTransformOrigin().Z() == b.GetTransformOrigin().Z();
     case CSSPropertyID::kWhiteSpace:
       return a.WhiteSpace() == b.WhiteSpace();
+    case CSSPropertyID::kWhiteSpaceCollapse:
+      return a.GetWhiteSpaceCollapse() == b.GetWhiteSpaceCollapse();
     case CSSPropertyID::kWidows:
       return a.Widows() == b.Widows();
     case CSSPropertyID::kWidth:
@@ -1179,6 +1181,7 @@
     case CSSPropertyID::kWebkitMaskPosition:
     case CSSPropertyID::kWebkitMaskRepeat:
     case CSSPropertyID::kWebkitTextStroke:
+    case CSSPropertyID::kAlternativeWhiteSpace:
       NOTREACHED() << property.GetCSSPropertyName().ToAtomicString().Ascii();
       return true;
 
diff --git a/third_party/blink/renderer/core/css/css_value_id_mappings.h b/third_party/blink/renderer/core/css/css_value_id_mappings.h
index 88b957e5..7d0e242e 100644
--- a/third_party/blink/renderer/core/css/css_value_id_mappings.h
+++ b/third_party/blink/renderer/core/css/css_value_id_mappings.h
@@ -409,10 +409,46 @@
 }
 
 template <>
+inline WhiteSpaceCollapse CssValueIDToPlatformEnum(CSSValueID v) {
+  switch (v) {
+    case CSSValueID::kCollapse:
+      return WhiteSpaceCollapse::kCollapse;
+    case CSSValueID::kPreserve:
+      return WhiteSpaceCollapse::kPreserve;
+    case CSSValueID::kPreserveBreaks:
+      return WhiteSpaceCollapse::kPreserveBreaks;
+    case CSSValueID::kBreakSpaces:
+      return WhiteSpaceCollapse::kBreakSpaces;
+    default:
+      NOTREACHED();
+      return WhiteSpaceCollapse::kCollapse;
+  }
+}
+
+template <>
+inline CSSValueID PlatformEnumToCSSValueID(WhiteSpaceCollapse v) {
+  switch (v) {
+    case WhiteSpaceCollapse::kCollapse:
+      return CSSValueID::kCollapse;
+    case WhiteSpaceCollapse::kPreserveBreaks:
+      return CSSValueID::kPreserveBreaks;
+    case WhiteSpaceCollapse::kPreserve:
+      return CSSValueID::kPreserve;
+    case WhiteSpaceCollapse::kBreakSpaces:
+      return CSSValueID::kBreakSpaces;
+  }
+  NOTREACHED();
+  return CSSValueID::kNone;
+}
+
+template <>
 inline TextWrap CssValueIDToPlatformEnum(CSSValueID v) {
   switch (v) {
     case CSSValueID::kWrap:
       return TextWrap::kWrap;
+    case CSSValueID::kNowrap:
+      DCHECK(RuntimeEnabledFeatures::CSSWhiteSpaceShorthandEnabled());
+      return TextWrap::kNoWrap;
     case CSSValueID::kBalance:
       return TextWrap::kBalance;
     default:
@@ -426,12 +462,20 @@
   switch (v) {
     case TextWrap::kWrap:
       return CSSValueID::kWrap;
+    case TextWrap::kNoWrap:
+      if (!RuntimeEnabledFeatures::CSSWhiteSpaceShorthandEnabled()) {
+        // Note this is not right, but a compromise until `white-space` becomes
+        // a shorthand. Simulate the behavior when it's off.
+        return CSSValueID::kWrap;
+      }
+      return CSSValueID::kNowrap;
     case TextWrap::kBalance:
       return CSSValueID::kBalance;
   }
   NOTREACHED();
   return CSSValueID::kNone;
 }
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_VALUE_ID_MAPPINGS_H_
diff --git a/third_party/blink/renderer/core/css/css_value_keywords.json5 b/third_party/blink/renderer/core/css/css_value_keywords.json5
index c7e05a28..30fbf9a 100644
--- a/third_party/blink/renderer/core/css/css_value_keywords.json5
+++ b/third_party/blink/renderer/core/css/css_value_keywords.json5
@@ -568,6 +568,12 @@
     //hidden
     "collapse",
     //
+    // white-space and its longhands (white-space-collapse and text-wrap)
+    // https://w3c.github.io/csswg-drafts/css-text-4/#white-space-property
+    //
+    "preserve",
+    "preserve-breaks",
+    //
     // Unordered rest
     //
     "a3",
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
index 39b68e7b..c1e63e7 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -1334,7 +1334,12 @@
              value_id == CSSValueID::kSquare || value_id == CSSValueID::kNone;
     case CSSPropertyID::kTextWrap:
       DCHECK(RuntimeEnabledFeatures::CSSTextWrapEnabled());
-      return value_id == CSSValueID::kWrap || value_id == CSSValueID::kBalance;
+      if (!RuntimeEnabledFeatures::CSSWhiteSpaceShorthandEnabled()) {
+        return value_id == CSSValueID::kWrap ||
+               value_id == CSSValueID::kBalance;
+      }
+      return value_id == CSSValueID::kWrap || value_id == CSSValueID::kNowrap ||
+             value_id == CSSValueID::kBalance;
     case CSSPropertyID::kTransformBox:
       return value_id == CSSValueID::kFillBox ||
              value_id == CSSValueID::kViewBox;
@@ -1367,11 +1372,18 @@
              value_id == CSSValueID::kTbRl || value_id == CSSValueID::kLr ||
              value_id == CSSValueID::kRl || value_id == CSSValueID::kTb;
     case CSSPropertyID::kWhiteSpace:
+      DCHECK(!RuntimeEnabledFeatures::CSSWhiteSpaceShorthandEnabled());
       return value_id == CSSValueID::kNormal || value_id == CSSValueID::kPre ||
              value_id == CSSValueID::kPreWrap ||
              value_id == CSSValueID::kPreLine ||
              value_id == CSSValueID::kNowrap ||
              value_id == CSSValueID::kBreakSpaces;
+    case CSSPropertyID::kWhiteSpaceCollapse:
+      DCHECK(RuntimeEnabledFeatures::CSSWhiteSpaceShorthandEnabled());
+      return value_id == CSSValueID::kCollapse ||
+             value_id == CSSValueID::kPreserve ||
+             value_id == CSSValueID::kPreserveBreaks ||
+             value_id == CSSValueID::kBreakSpaces;
     case CSSPropertyID::kWordBreak:
       return value_id == CSSValueID::kNormal ||
              value_id == CSSValueID::kBreakAll ||
@@ -1512,7 +1524,8 @@
     CSSPropertyID::kWebkitUserModify,
     CSSPropertyID::kUserSelect,
     CSSPropertyID::kWebkitWritingMode,
-    CSSPropertyID::kWhiteSpace,
+    CSSPropertyID::kWhiteSpace,  // TODO(crbug.com/1417543): Remove when done.
+    CSSPropertyID::kWhiteSpaceCollapse,
     CSSPropertyID::kWordBreak,
     CSSPropertyID::kWritingMode,
     CSSPropertyID::kScrollbarWidth,
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
index 8c94dd718..4aec10a3 100644
--- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -1984,7 +1984,7 @@
 
 static bool ConsumeColorInterpolationSpace(
     CSSParserTokenRange& args,
-    Color::ColorInterpolationSpace& color_space,
+    Color::ColorSpace& color_space,
     Color::HueInterpolationMethod& hue_interpolation) {
   if (!RuntimeEnabledFeatures::CSSColor4Enabled()) {
     return false;
@@ -1994,38 +1994,38 @@
     return false;
   }
 
-  absl::optional<Color::ColorInterpolationSpace> read_color_space;
+  absl::optional<Color::ColorSpace> read_color_space;
   if (ConsumeIdent<CSSValueID::kXyz>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kXYZD65;
+    read_color_space = Color::ColorSpace::kXYZD65;
   } else if (ConsumeIdent<CSSValueID::kXyzD50>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kXYZD50;
+    read_color_space = Color::ColorSpace::kXYZD50;
   } else if (ConsumeIdent<CSSValueID::kXyzD65>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kXYZD65;
+    read_color_space = Color::ColorSpace::kXYZD65;
   } else if (ConsumeIdent<CSSValueID::kSRGBLinear>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kSRGBLinear;
+    read_color_space = Color::ColorSpace::kSRGBLinear;
   } else if (ConsumeIdent<CSSValueID::kLab>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kLab;
+    read_color_space = Color::ColorSpace::kLab;
   } else if (ConsumeIdent<CSSValueID::kOklab>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kOklab;
+    read_color_space = Color::ColorSpace::kOklab;
   } else if (ConsumeIdent<CSSValueID::kLch>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kLch;
+    read_color_space = Color::ColorSpace::kLch;
   } else if (ConsumeIdent<CSSValueID::kOklch>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kOklch;
+    read_color_space = Color::ColorSpace::kOklch;
   } else if (ConsumeIdent<CSSValueID::kSRGB>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kSRGB;
+    read_color_space = Color::ColorSpace::kSRGB;
   } else if (ConsumeIdent<CSSValueID::kHsl>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kHSL;
+    read_color_space = Color::ColorSpace::kHSL;
   } else if (ConsumeIdent<CSSValueID::kHwb>(args)) {
-    read_color_space = Color::ColorInterpolationSpace::kHWB;
+    read_color_space = Color::ColorSpace::kHWB;
   }
 
   if (read_color_space) {
     color_space = read_color_space.value();
     absl::optional<Color::HueInterpolationMethod> read_hue;
-    if (color_space == Color::ColorInterpolationSpace::kHSL ||
-        color_space == Color::ColorInterpolationSpace::kHWB ||
-        color_space == Color::ColorInterpolationSpace::kLch ||
-        color_space == Color::ColorInterpolationSpace::kOklch) {
+    if (color_space == Color::ColorSpace::kHSL ||
+        color_space == Color::ColorSpace::kHWB ||
+        color_space == Color::ColorSpace::kLch ||
+        color_space == Color::ColorSpace::kOklch) {
       if (ConsumeIdent<CSSValueID::kShorter>(args)) {
         read_hue = Color::HueInterpolationMethod::kShorter;
       } else if (ConsumeIdent<CSSValueID::kLonger>(args)) {
@@ -2063,7 +2063,7 @@
 
   CSSParserTokenRange args = ConsumeFunction(range);
   // First argument is the colorspace
-  Color::ColorInterpolationSpace color_space;
+  Color::ColorSpace color_space;
   Color::HueInterpolationMethod hue_interpolation_method =
       Color::HueInterpolationMethod::kShorter;
   if (!ConsumeColorInterpolationSpace(args, color_space,
@@ -3054,7 +3054,7 @@
   // [ ellipse || [ <length> | <percentage> ]{2} ] |
   // [ [ circle | ellipse] || <size-keyword> ]] ]
 
-  Color::ColorInterpolationSpace color_space;
+  Color::ColorSpace color_space;
   Color::HueInterpolationMethod hue_interpolation_method =
       Color::HueInterpolationMethod::kShorter;
   bool has_color_space = ConsumeColorInterpolationSpace(
@@ -3168,7 +3168,7 @@
   // First part of grammar, the size/shape/color space clause:
   // [ in <color-space>? || [ <angle> | to <side-or-corner> ]?]
   bool expect_comma = true;
-  Color::ColorInterpolationSpace color_space;
+  Color::ColorSpace color_space;
   Color::HueInterpolationMethod hue_interpolation_method =
       Color::HueInterpolationMethod::kShorter;
   bool has_color_space = ConsumeColorInterpolationSpace(
@@ -3231,7 +3231,7 @@
 static CSSValue* ConsumeConicGradient(CSSParserTokenRange& args,
                                       const CSSParserContext& context,
                                       cssvalue::CSSGradientRepeat repeating) {
-  Color::ColorInterpolationSpace color_space;
+  Color::ColorSpace color_space;
   Color::HueInterpolationMethod hue_interpolation_method =
       Color::HueInterpolationMethod::kShorter;
   bool has_color_space = ConsumeColorInterpolationSpace(
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 8024982..98d6fa8 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -9727,44 +9727,22 @@
   return CSSIdentifierValue::Create(style.GetWritingMode());
 }
 
-void WhiteSpace::ApplyInitial(StyleResolverState& state) const {
-  ComputedStyleBuilder& builder = state.StyleBuilder();
-  builder.SetWhiteSpace(ComputedStyleInitialValues::InitialWhiteSpace());
-  // TODO(crbug.com/1417543): `white-space` will become a shorthand in the
-  // future - in order to mitigate the forward compat risk, apply to the
-  // `text-wrap` longhand as well.
-  DCHECK(GetCSSPropertyWhiteSpace().IsLonghand());
-  builder.SetTextWrap(ComputedStyleInitialValues::InitialTextWrap());
-}
-
-void WhiteSpace::ApplyInherit(StyleResolverState& state) const {
-  ComputedStyleBuilder& builder = state.StyleBuilder();
-  builder.SetWhiteSpace(state.ParentStyle()->WhiteSpace());
-  // TODO(crbug.com/1417543): See `WhiteSpace::ApplyInitial`.
-  // For now, any `white-space` values should set `text-wrap: wrap`.
-  DCHECK(GetCSSPropertyWhiteSpace().IsLonghand());
-  builder.SetTextWrap(ComputedStyleInitialValues::InitialTextWrap());
-}
-
-void WhiteSpace::ApplyValue(StyleResolverState& state,
-                            const CSSValue& value,
-                            ValueMode) const {
-  ComputedStyleBuilder& builder = state.StyleBuilder();
-  builder.SetWhiteSpace(
-      To<CSSIdentifierValue>(value).ConvertTo<blink::EWhiteSpace>());
-  // TODO(crbug.com/1417543): See `WhiteSpace::ApplyInitial`.
-  // For now, any `white-space` values should set `text-wrap: wrap`.
-  DCHECK(GetCSSPropertyWhiteSpace().IsLonghand());
-  builder.SetTextWrap(ComputedStyleInitialValues::InitialTextWrap());
-}
-
 const CSSValue* WhiteSpace::CSSValueFromComputedStyleInternal(
     const ComputedStyle& style,
     const LayoutObject*,
     bool allow_visited_style) const {
+  DCHECK(!RuntimeEnabledFeatures::CSSWhiteSpaceShorthandEnabled());
   return CSSIdentifierValue::Create(style.WhiteSpace());
 }
 
+// Longhands for `white-space`: `white-space-collapse` and `text-wrap`.
+const CSSValue* WhiteSpaceCollapse::CSSValueFromComputedStyleInternal(
+    const ComputedStyle& style,
+    const LayoutObject*,
+    bool allow_visited_style) const {
+  return CSSIdentifierValue::Create(style.GetWhiteSpaceCollapse());
+}
+
 const CSSValue* TextWrap::CSSValueFromComputedStyleInternal(
     const ComputedStyle& style,
     const LayoutObject*,
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
index dbb175a..67101d0 100644
--- a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
@@ -3764,5 +3764,73 @@
   return toggle_root;
 }
 
+bool AlternativeWhiteSpace::ParseShorthand(
+    bool important,
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    const CSSParserLocalContext&,
+    HeapVector<CSSPropertyValue, 64>& properties) const {
+  const CSSParserTokenRange original_range = range;
+
+  // Try to parse as a pre-defined keyword. The `white-space` has pre-defined
+  // keywords in addition to the multi-values shorthand, for the backward
+  // compatibility with when it was a longhand.
+  if (const CSSIdentifierValue* value = css_parsing_utils::ConsumeIdent<
+          CSSValueID::kBreakSpaces, CSSValueID::kNormal, CSSValueID::kNowrap,
+          CSSValueID::kPre, CSSValueID::kPreLine, CSSValueID::kPreWrap>(
+          range)) {
+    // Parse as a pre-defined keyword only if it is at the end. Some keywords
+    // can be both a pre-defined keyword or a longhand value.
+    if (range.AtEnd()) {
+      const EWhiteSpace whitespace =
+          CssValueIDToPlatformEnum<EWhiteSpace>(value->GetValueID());
+      DCHECK(IsValidWhiteSpace(whitespace));
+      AddProperty(
+          CSSPropertyID::kWhiteSpaceCollapse, CSSPropertyID::kWhiteSpace,
+          *CSSIdentifierValue::Create(ToWhiteSpaceCollapse(whitespace)),
+          important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
+          properties);
+      AddProperty(
+          CSSPropertyID::kTextWrap, CSSPropertyID::kWhiteSpace,
+          *CSSIdentifierValue::Create(ToTextWrap(whitespace)), important,
+          css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
+      return true;
+    }
+
+    // If `range` is not at end, the keyword is for longhands. Restore `range`.
+    range = original_range;
+  }
+
+  // Consume multi-value syntax if the first identifier is not pre-defined.
+  return css_parsing_utils::ConsumeShorthandGreedilyViaLonghands(
+      alternativeWhiteSpaceShorthand(), important, context, range, properties);
+}
+
+const CSSValue* AlternativeWhiteSpace::CSSValueFromComputedStyleInternal(
+    const ComputedStyle& style,
+    const LayoutObject* layout_object,
+    bool allow_visited_style) const {
+  const EWhiteSpace whitespace = style.WhiteSpace();
+  if (IsValidWhiteSpace(whitespace)) {
+    const CSSValueID value = PlatformEnumToCSSValueID(whitespace);
+    DCHECK_NE(value, CSSValueID::kNone);
+    return CSSIdentifierValue::Create(value);
+  }
+
+  CSSValueList* list = CSSValueList::CreateSpaceSeparated();
+  const WhiteSpaceCollapse collapse = style.GetWhiteSpaceCollapse();
+  if (collapse != ComputedStyleInitialValues::InitialWhiteSpaceCollapse()) {
+    list->Append(*CSSIdentifierValue::Create(collapse));
+  }
+  const TextWrap wrap = style.GetTextWrap();
+  if (wrap != ComputedStyleInitialValues::InitialTextWrap()) {
+    list->Append(*CSSIdentifierValue::Create(wrap));
+  }
+  // When all longhands are initial values, it should be `normal`, covered by
+  // `IsValidWhiteSpace()` above.
+  DCHECK(list->length());
+  return list;
+}
+
 }  // namespace css_shorthand
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
index abf23bdd..d636f134 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -540,16 +540,18 @@
     }
   }
 
-  // TODO(crbug.com/1417543): `white-space` will become a shorthand in the
-  // future - in order to mitigate the forward compat risk, skip the `text-wrap`
-  // longhand.
-  const CSSProperty& white_space = GetCSSPropertyWhiteSpace();
-  DCHECK(white_space.IsLonghand());
-  if (!resolver.filter_.Rejects(white_space)) {
-    if (const CascadePriority* priority =
-            map_.Find(white_space.GetCSSPropertyName())) {
-      LookupAndApply(white_space, resolver);
-      maybe_skip(GetCSSPropertyTextWrap(), *priority);
+  if (!RuntimeEnabledFeatures::CSSWhiteSpaceShorthandEnabled()) {
+    // TODO(crbug.com/1417543): `white-space` will become a shorthand in the
+    // future - in order to mitigate the forward compat risk, skip the
+    // `text-wrap` longhand.
+    const CSSProperty& white_space = GetCSSPropertyWhiteSpace();
+    DCHECK(white_space.IsLonghand());
+    if (!resolver.filter_.Rejects(white_space)) {
+      if (const CascadePriority* priority =
+              map_.Find(white_space.GetCSSPropertyName())) {
+        LookupAndApply(white_space, resolver);
+        maybe_skip(GetCSSPropertyTextWrap(), *priority);
+      }
     }
   }
 }
diff --git a/third_party/blink/renderer/core/css/selector_checker.h b/third_party/blink/renderer/core/css/selector_checker.h
index 69592ab..5d1196d 100644
--- a/third_party/blink/renderer/core/css/selector_checker.h
+++ b/third_party/blink/renderer/core/css/selector_checker.h
@@ -216,14 +216,34 @@
   };
 
   // Used for situations where we have "inner" selector matching, such as
-  // :is(...). Ensures that MatchFlags found for the inner selector are
-  //  propagated to the outer MatchResult.
+  // :is(...). Ensures that we propagate the necessary sub-result data
+  // to the outer MatchResult.
   class SubResult : public MatchResult {
     STACK_ALLOCATED();
 
    public:
     explicit SubResult(MatchResult& parent) : parent_(parent) {}
-    ~SubResult() { parent_.flags |= flags; }
+    ~SubResult() {
+      parent_.flags |= flags;
+      // Propagate proximity from nested selectors which refer to a parent
+      // rule with a kScopeActivation, e.g.:
+      //
+      //   @scope (div) {
+      //     :scope {
+      //       & { ... }
+      //     }
+      //   }
+      //
+      // The inner rule (&) has no kScopeActivation relation anywhere in the
+      // selector, because it's nested using CSSNestingType::kNesting,
+      // yet it refers to a selector which does contain a kScopeActivation.
+      // The resulting proximity value must be propagated.
+      //
+      // Note that regular :is() and similar pseudo-classes with inner selectors
+      // lists do not produce any (non-max) proximity values; it can only happen
+      // with the nesting selector (&).
+      parent_.proximity = std::min(parent_.proximity, proximity);
+    }
 
    private:
     MatchResult& parent_;
diff --git a/third_party/blink/renderer/core/css/style_color.h b/third_party/blink/renderer/core/css/style_color.h
index 57e06a1..4dabfbfb 100644
--- a/third_party/blink/renderer/core/css/style_color.h
+++ b/third_party/blink/renderer/core/css/style_color.h
@@ -80,8 +80,7 @@
     Color Resolve(const Color& current_color) const;
 
    private:
-    Color::ColorInterpolationSpace color_interpolation_space_ =
-        Color::ColorInterpolationSpace::kNone;
+    Color::ColorSpace color_interpolation_space_ = Color::ColorSpace::kNone;
     Color::HueInterpolationMethod hue_interpolation_method_ =
         Color::HueInterpolationMethod::kShorter;
     ColorOrUnresolvedColorMix color1_;
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.cc b/third_party/blink/renderer/core/css/style_property_serializer.cc
index 58845b7..74c216c6 100644
--- a/third_party/blink/renderer/core/css/style_property_serializer.cc
+++ b/third_party/blink/renderer/core/css/style_property_serializer.cc
@@ -51,6 +51,29 @@
 
 namespace blink {
 
+namespace {
+
+template <typename T>
+T ConvertIdentifierTo(const CSSValue* value, T initial_value) {
+  if (const auto* ident = DynamicTo<CSSIdentifierValue>(value)) {
+    return ident->ConvertTo<T>();
+  }
+  DCHECK(value->IsInitialValue());
+  return initial_value;
+}
+
+inline WhiteSpaceCollapse ToWhiteSpaceCollapse(const CSSValue* value) {
+  return ConvertIdentifierTo<WhiteSpaceCollapse>(
+      value, ComputedStyleInitialValues::InitialWhiteSpaceCollapse());
+}
+
+inline TextWrap ToTextWrap(const CSSValue* value) {
+  return ConvertIdentifierTo<TextWrap>(
+      value, ComputedStyleInitialValues::InitialTextWrap());
+}
+
+}  // namespace
+
 StylePropertySerializer::CSSPropertyValueSetForSerializer::
     CSSPropertyValueSetForSerializer(const CSSPropertyValueSet& properties)
     : property_set_(&properties),
@@ -379,6 +402,7 @@
     case CSSPropertyID::kTextEmphasis:
     case CSSPropertyID::kWebkitMask:
     case CSSPropertyID::kWebkitTextStroke:
+    case CSSPropertyID::kAlternativeWhiteSpace:
       return true;
     default:
       return false;
@@ -660,6 +684,8 @@
     }
     case CSSPropertyID::kViewTimeline:
       return ViewTimelineValue();
+    case CSSPropertyID::kAlternativeWhiteSpace:
+      return WhiteSpaceValue();
     case CSSPropertyID::kGridColumnGap:
     case CSSPropertyID::kGridGap:
     case CSSPropertyID::kGridRowGap:
@@ -2126,4 +2152,41 @@
   return true;
 }
 
+String StylePropertySerializer::WhiteSpaceValue() const {
+  DCHECK(RuntimeEnabledFeatures::CSSWhiteSpaceShorthandEnabled());
+
+  const CSSValue* collapse_value =
+      property_set_.GetPropertyCSSValue(GetCSSPropertyWhiteSpaceCollapse());
+  const CSSValue* wrap_value =
+      property_set_.GetPropertyCSSValue(GetCSSPropertyTextWrap());
+  if (!collapse_value || !wrap_value) {
+    // If any longhands are missing, don't serialize as a shorthand.
+    return g_empty_string;
+  }
+
+  // Check if longhands are one of pre-defined keywords of `white-space`.
+  const WhiteSpaceCollapse collapse = ToWhiteSpaceCollapse(collapse_value);
+  const TextWrap wrap = ToTextWrap(wrap_value);
+  const EWhiteSpace whitespace = ToWhiteSpace(collapse, wrap);
+  if (IsValidWhiteSpace(whitespace)) {
+    return getValueName(PlatformEnumToCSSValueID(whitespace));
+  }
+
+  // Otherwise build a multi-value list.
+  StringBuilder result;
+  if (collapse != ComputedStyleInitialValues::InitialWhiteSpaceCollapse()) {
+    result.Append(getValueName(PlatformEnumToCSSValueID(collapse)));
+  }
+  if (wrap != ComputedStyleInitialValues::InitialTextWrap()) {
+    if (!result.empty()) {
+      result.Append(kSpaceCharacter);
+    }
+    result.Append(getValueName(PlatformEnumToCSSValueID(wrap)));
+  }
+  // When all longhands are initial values, it should be `normal`, covered by
+  // `IsValidWhiteSpace()` above.
+  DCHECK(!result.empty());
+  return result.ToString();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.h b/third_party/blink/renderer/core/css/style_property_serializer.h
index 08eb4a2..0be71e1 100644
--- a/third_party/blink/renderer/core/css/style_property_serializer.h
+++ b/third_party/blink/renderer/core/css/style_property_serializer.h
@@ -78,6 +78,7 @@
   String TextDecorationValue() const;
   String BackgroundRepeatPropertyValue() const;
   String ContainIntrinsicSizeValue() const;
+  String WhiteSpaceValue() const;
   String GetPropertyText(const CSSPropertyName&,
                          const String& value,
                          bool is_important,
diff --git a/third_party/blink/renderer/core/css/white_space.h b/third_party/blink/renderer/core/css/white_space.h
index e530708..fb651de 100644
--- a/third_party/blink/renderer/core/css/white_space.h
+++ b/third_party/blink/renderer/core/css/white_space.h
@@ -9,24 +9,49 @@
 
 namespace blink {
 
-// Semantic behaviors of the `white-space` property. All values of the
-// `white-space` property can be expressed by combinations of these bits.
-enum class WhiteSpaceBehavior : uint8_t {
-  kPreserveSpacesAndTabs = 1,
+//
+// This file contains definitions of the `white-space` shorthand property and
+// its longhands.
+// https://w3c.github.io/csswg-drafts/css-text-4/#propdef-white-space
+//
+
+//
+// The `white-space-collapse` property.
+// https://w3c.github.io/csswg-drafts/css-text-4/#white-space-collapsing
+//
+enum class WhiteSpaceCollapse : uint8_t {
+  kCollapse = 0,
+  kPreserve = 1,
+  // `KPreserve` is a bit-flag, but bit 2 is shared by two different behaviors
+  // below to save memory. Use functions below instead of direct comparisons.
   kPreserveBreaks = 2,
-  kPreserveAllWhiteSpaces = kPreserveSpacesAndTabs | kPreserveBreaks,
-  kNoWrapLine = 4,
-  kBreakSpaces = 8,
-  // Ensure `kWhiteSpaceBehaviorBits` has enough bits.
+  kBreakSpaces = kPreserve | 2,
+  // Ensure `kWhiteSpaceCollapseBits` can hold all values.
 };
 
 // Ensure this is in sync with `css_properties.json5`.
-static constexpr int kWhiteSpaceBehaviorBits = 4;
+static constexpr int kWhiteSpaceCollapseBits = 2;
+static constexpr uint8_t kWhiteSpaceCollapseMask =
+    (1 << kWhiteSpaceCollapseBits) - 1;
 
-constexpr WhiteSpaceBehavior operator|(WhiteSpaceBehavior a,
-                                       WhiteSpaceBehavior b) {
-  return static_cast<WhiteSpaceBehavior>(static_cast<unsigned>(a) |
-                                         static_cast<unsigned>(b));
+inline bool IsWhiteSpaceCollapseAny(WhiteSpaceCollapse value,
+                                    WhiteSpaceCollapse flags) {
+  return static_cast<uint8_t>(value) & static_cast<uint8_t>(flags);
+}
+inline bool ShouldPreserveSpacesAndTabs(WhiteSpaceCollapse collapse) {
+  return IsWhiteSpaceCollapseAny(collapse, WhiteSpaceCollapse::kPreserve);
+}
+inline bool ShouldPreserveBreaks(WhiteSpaceCollapse collapse) {
+  return collapse != WhiteSpaceCollapse::kCollapse;
+}
+inline bool ShouldCollapseSpacesAndTabs(WhiteSpaceCollapse collapse) {
+  return !ShouldPreserveSpacesAndTabs(collapse);
+}
+inline bool ShouldCollapseBreaks(WhiteSpaceCollapse collapse) {
+  return !ShouldPreserveBreaks(collapse);
+}
+inline bool ShouldBreakSpaces(WhiteSpaceCollapse collapse) {
+  return collapse == WhiteSpaceCollapse::kBreakSpaces;
 }
 
 //
@@ -35,71 +60,73 @@
 //
 enum class TextWrap : uint8_t {
   kWrap = 0,
-  kBalance = 1,
+  kNoWrap = 1,
+  kBalance = 2,
   // Ensure `kTextWrapBits` can hold all values.
 };
 
 // Ensure this is in sync with `css_properties.json5`.
-static constexpr int kTextWrapBits = 1;
+static constexpr int kTextWrapBits = 2;
+
+inline bool IsTextWrapAny(TextWrap value, TextWrap flags) {
+  return static_cast<uint8_t>(value) & static_cast<uint8_t>(flags);
+}
+inline bool ShouldWrapLine(TextWrap wrap) {
+  return !IsTextWrapAny(wrap, TextWrap::kNoWrap);
+}
 
 //
 // The `white-space` property.
 // https://w3c.github.io/csswg-drafts/css-text-4/#propdef-white-space
 //
+// `EWhiteSpace` is represented by bit-flags of combinations of all possible
+// longhand values. Thus `ToWhiteSpace()` may return values that are not defined
+// as the `EWhiteSpace` value. `IsValidWhiteSpace()` can check if a value is one
+// of pre-defined keywords.
+//
+constexpr uint8_t ToWhiteSpaceValue(WhiteSpaceCollapse collapse,
+                                    TextWrap wrap) {
+  return static_cast<uint8_t>(collapse) |
+         (static_cast<uint8_t>(wrap) << kWhiteSpaceCollapseBits);
+}
+
 enum class EWhiteSpace : uint8_t {
-  kNormal = 0,
-  kNowrap = static_cast<uint8_t>(WhiteSpaceBehavior::kNoWrapLine),
-  kPre = static_cast<uint8_t>(WhiteSpaceBehavior::kPreserveAllWhiteSpaces |
-                              WhiteSpaceBehavior::kNoWrapLine),
-  kPreLine = static_cast<uint8_t>(WhiteSpaceBehavior::kPreserveBreaks),
-  kPreWrap = static_cast<uint8_t>(WhiteSpaceBehavior::kPreserveAllWhiteSpaces),
+  kNormal = ToWhiteSpaceValue(WhiteSpaceCollapse::kCollapse, TextWrap::kWrap),
+  kNowrap = ToWhiteSpaceValue(WhiteSpaceCollapse::kCollapse, TextWrap::kNoWrap),
+  kPre = ToWhiteSpaceValue(WhiteSpaceCollapse::kPreserve, TextWrap::kNoWrap),
+  kPreLine =
+      ToWhiteSpaceValue(WhiteSpaceCollapse::kPreserveBreaks, TextWrap::kWrap),
+  kPreWrap = ToWhiteSpaceValue(WhiteSpaceCollapse::kPreserve, TextWrap::kWrap),
   kBreakSpaces =
-      static_cast<uint8_t>(WhiteSpaceBehavior::kPreserveAllWhiteSpaces |
-                           WhiteSpaceBehavior::kBreakSpaces),
+      ToWhiteSpaceValue(WhiteSpaceCollapse::kBreakSpaces, TextWrap::kWrap),
 };
 
-// Ensure this is in sync with `css_properties.json5`.
-static constexpr int kEWhiteSpaceBits = kWhiteSpaceBehaviorBits;
+static_assert(kWhiteSpaceCollapseBits + kTextWrapBits <=
+              sizeof(EWhiteSpace) * 8);
 
-//
-// Functions for semantic behaviors.
-//
-// Note that functions in `ComputedStyle` are preferred over these functions
-// because the `white-space` property may become a shorthand in future. When
-// that happens, these functions may be removed, or less performant than
-// functions in `ComputedStyle`.
-// https://w3c.github.io/csswg-drafts/css-text-4/#propdef-white-space
-//
-inline bool IsWhiteSpaceAny(EWhiteSpace value, WhiteSpaceBehavior flags) {
-  return static_cast<uint8_t>(value) & static_cast<uint8_t>(flags);
+// Convert longhands of `white-space` to `EWhiteSpace`. The return value may not
+// be one of the defined enum values. Please see the comment above.
+inline EWhiteSpace ToWhiteSpace(WhiteSpaceCollapse collapse, TextWrap wrap) {
+  return static_cast<EWhiteSpace>(ToWhiteSpaceValue(collapse, wrap));
 }
 
-//
-// `white-space-collapse`: Collapsing/preserving white-spaces.
-// https://w3c.github.io/csswg-drafts/css-text-4/#propdef-white-space-collapse
-//
-inline bool ShouldPreserveBreaks(EWhiteSpace value) {
-  return IsWhiteSpaceAny(value, WhiteSpaceBehavior::kPreserveBreaks);
-}
-inline bool ShouldPreserveSpacesAndTabs(EWhiteSpace value) {
-  return IsWhiteSpaceAny(value, WhiteSpaceBehavior::kPreserveSpacesAndTabs);
-}
-inline bool ShouldCollapseBreaks(EWhiteSpace value) {
-  return !ShouldPreserveBreaks(value);
-}
-inline bool ShouldCollapseSpacesAndTabs(EWhiteSpace value) {
-  return !ShouldPreserveSpacesAndTabs(value);
-}
-inline bool ShouldBreakSpaces(EWhiteSpace value) {
-  return IsWhiteSpaceAny(value, WhiteSpaceBehavior::kBreakSpaces);
+inline bool IsValidWhiteSpace(EWhiteSpace whitespace) {
+  return whitespace == EWhiteSpace::kNormal ||
+         whitespace == EWhiteSpace::kNowrap ||
+         whitespace == EWhiteSpace::kPre ||
+         whitespace == EWhiteSpace::kPreLine ||
+         whitespace == EWhiteSpace::kPreWrap ||
+         whitespace == EWhiteSpace::kBreakSpaces;
 }
 
-//
-// `text-wrap`: Text Wrapping.
-// https://w3c.github.io/csswg-drafts/css-text-4/#propdef-text-wrap
-//
-inline bool ShouldWrapLine(EWhiteSpace value) {
-  return !IsWhiteSpaceAny(value, WhiteSpaceBehavior::kNoWrapLine);
+// Convert `EWhiteSpace` to longhands.
+inline WhiteSpaceCollapse ToWhiteSpaceCollapse(EWhiteSpace whitespace) {
+  return static_cast<WhiteSpaceCollapse>(static_cast<uint8_t>(whitespace) &
+                                         kWhiteSpaceCollapseMask);
+}
+inline TextWrap ToTextWrap(EWhiteSpace whitespace) {
+  return static_cast<TextWrap>(static_cast<uint8_t>(whitespace) >>
+                               kWhiteSpaceCollapseBits);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/white_space_test.cc b/third_party/blink/renderer/core/css/white_space_test.cc
new file mode 100644
index 0000000..05908e0
--- /dev/null
+++ b/third_party/blink/renderer/core/css/white_space_test.cc
@@ -0,0 +1,84 @@
+// Copyright 2023 The Chromium Authors
+// 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/core/css/white_space.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/css_identifier_value.h"
+
+namespace blink {
+
+class WhiteSpaceValuesTest : public testing::Test,
+                             public testing::WithParamInterface<EWhiteSpace> {};
+
+static const EWhiteSpace whitespace_values[] = {
+    EWhiteSpace::kNormal,  EWhiteSpace::kNowrap,  EWhiteSpace::kPre,
+    EWhiteSpace::kPreLine, EWhiteSpace::kPreWrap, EWhiteSpace::kBreakSpaces,
+};
+
+INSTANTIATE_TEST_SUITE_P(WhiteSpaceTest,
+                         WhiteSpaceValuesTest,
+                         testing::ValuesIn(whitespace_values));
+
+TEST_P(WhiteSpaceValuesTest, CSSValue) {
+  const EWhiteSpace whitespace = GetParam();
+  const CSSValueID css_value_id = PlatformEnumToCSSValueID(whitespace);
+  EXPECT_NE(css_value_id, CSSValueID::kInvalid);
+  EXPECT_NE(css_value_id, CSSValueID::kNone);
+  EXPECT_EQ(whitespace, CssValueIDToPlatformEnum<EWhiteSpace>(css_value_id));
+
+  const CSSIdentifierValue* css_value = CSSIdentifierValue::Create(whitespace);
+  EXPECT_TRUE(css_value);
+  EXPECT_EQ(whitespace, css_value->ConvertTo<EWhiteSpace>());
+}
+
+TEST(WhiteSpaceTest, Normal) {
+  const EWhiteSpace normal = EWhiteSpace::kNormal;
+  EXPECT_FALSE(ShouldPreserveSpacesAndTabs(ToWhiteSpaceCollapse(normal)));
+  EXPECT_FALSE(ShouldPreserveBreaks(ToWhiteSpaceCollapse(normal)));
+  EXPECT_FALSE(ShouldBreakSpaces(ToWhiteSpaceCollapse(normal)));
+  EXPECT_TRUE(ShouldWrapLine(ToTextWrap(normal)));
+}
+
+TEST(WhiteSpaceTest, Nowrap) {
+  const EWhiteSpace nowrap = EWhiteSpace::kNowrap;
+  EXPECT_FALSE(ShouldPreserveSpacesAndTabs(ToWhiteSpaceCollapse(nowrap)));
+  EXPECT_FALSE(ShouldPreserveBreaks(ToWhiteSpaceCollapse(nowrap)));
+  EXPECT_FALSE(ShouldBreakSpaces(ToWhiteSpaceCollapse(nowrap)));
+  EXPECT_FALSE(ShouldWrapLine(ToTextWrap(nowrap)));
+}
+
+TEST(WhiteSpaceTest, Pre) {
+  const EWhiteSpace pre = EWhiteSpace::kPre;
+  EXPECT_TRUE(ShouldPreserveSpacesAndTabs(ToWhiteSpaceCollapse(pre)));
+  EXPECT_TRUE(ShouldPreserveBreaks(ToWhiteSpaceCollapse(pre)));
+  EXPECT_FALSE(ShouldBreakSpaces(ToWhiteSpaceCollapse(pre)));
+  EXPECT_FALSE(ShouldWrapLine(ToTextWrap(pre)));
+}
+
+TEST(WhiteSpaceTest, PreLine) {
+  const EWhiteSpace pre_line = EWhiteSpace::kPreLine;
+  EXPECT_FALSE(ShouldPreserveSpacesAndTabs(ToWhiteSpaceCollapse(pre_line)));
+  EXPECT_TRUE(ShouldPreserveBreaks(ToWhiteSpaceCollapse(pre_line)));
+  EXPECT_FALSE(ShouldBreakSpaces(ToWhiteSpaceCollapse(pre_line)));
+  EXPECT_TRUE(ShouldWrapLine(ToTextWrap(pre_line)));
+}
+
+TEST(WhiteSpaceTest, PreWrap) {
+  const EWhiteSpace pre_wrap = EWhiteSpace::kPreWrap;
+  EXPECT_TRUE(ShouldPreserveSpacesAndTabs(ToWhiteSpaceCollapse(pre_wrap)));
+  EXPECT_TRUE(ShouldPreserveBreaks(ToWhiteSpaceCollapse(pre_wrap)));
+  EXPECT_FALSE(ShouldBreakSpaces(ToWhiteSpaceCollapse(pre_wrap)));
+  EXPECT_TRUE(ShouldWrapLine(ToTextWrap(pre_wrap)));
+}
+
+TEST(WhiteSpaceTest, BreakSpaces) {
+  const EWhiteSpace break_spaces = EWhiteSpace::kBreakSpaces;
+  EXPECT_TRUE(ShouldPreserveSpacesAndTabs(ToWhiteSpaceCollapse(break_spaces)));
+  EXPECT_TRUE(ShouldPreserveBreaks(ToWhiteSpaceCollapse(break_spaces)));
+  EXPECT_TRUE(ShouldBreakSpaces(ToWhiteSpaceCollapse(break_spaces)));
+  EXPECT_TRUE(ShouldWrapLine(ToTextWrap(break_spaces)));
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/build.gni b/third_party/blink/renderer/core/dom/build.gni
index e7ea9df..df4af74 100644
--- a/third_party/blink/renderer/core/dom/build.gni
+++ b/third_party/blink/renderer/core/dom/build.gni
@@ -114,9 +114,6 @@
   "dom_token_list.h",
   "element_data.cc",
   "element_data.h",
-  "element_rare_data.cc",
-  "element_rare_data.h",
-  "element_rare_data_base.h",
   "element_rare_data_field.h",
   "element_rare_data_vector.cc",
   "element_rare_data_vector.h",
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index d815499..7f8e9470 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -254,7 +254,7 @@
 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
 #include "third_party/blink/renderer/core/layout/layout_object_factory.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_view.h"
 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
 #include "third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.h"
 #include "third_party/blink/renderer/core/loader/cookie_jar.h"
@@ -2825,7 +2825,7 @@
   UpdateForcedColors();
   scoped_refptr<const ComputedStyle> style =
       GetStyleResolver().StyleForViewport();
-  layout_view_ = LayoutObjectFactory::CreateView(*this, *style);
+  layout_view_ = MakeGarbageCollected<LayoutNGView>(this);
   SetLayoutObject(layout_view_);
 
   layout_view_->SetStyle(style);
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 370dff8..6a48297 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -52,6 +52,8 @@
 #include "third_party/blink/renderer/core/accessibility/ax_context.h"
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
 #include "third_party/blink/renderer/core/animation/css/css_animations.h"
+#include "third_party/blink/renderer/core/animation/element_animations.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
 #include "third_party/blink/renderer/core/aom/computed_accessible_node.h"
 #include "third_party/blink/renderer/core/css/container_query_data.h"
 #include "third_party/blink/renderer/core/css/container_query_evaluator.h"
@@ -63,6 +65,7 @@
 #include "third_party/blink/renderer/core/css/css_selector_watch.h"
 #include "third_party/blink/renderer/core/css/css_style_sheet.h"
 #include "third_party/blink/renderer/core/css/css_value.h"
+#include "third_party/blink/renderer/core/css/cssom/inline_style_property_map.h"
 #include "third_party/blink/renderer/core/css/parser/css_parser.h"
 #include "third_party/blink/renderer/core/css/parser/css_selector_parser.h"
 #include "third_party/blink/renderer/core/css/post_style_update_scope.h"
@@ -80,11 +83,12 @@
 #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
 #include "third_party/blink/renderer/core/dom/attr.h"
 #include "third_party/blink/renderer/core/dom/container_node.h"
+#include "third_party/blink/renderer/core/dom/css_toggle.h"
+#include "third_party/blink/renderer/core/dom/css_toggle_map.h"
 #include "third_party/blink/renderer/core/dom/dataset_dom_string_map.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/dom_token_list.h"
 #include "third_party/blink/renderer/core/dom/element_data_cache.h"
-#include "third_party/blink/renderer/core/dom/element_rare_data.h"
 #include "third_party/blink/renderer/core/dom/element_rare_data_vector.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
@@ -971,7 +975,7 @@
 }
 
 NamedNodeMap* Element::attributesForBindings() const {
-  ElementRareDataBase& rare_data =
+  ElementRareDataVector& rare_data =
       const_cast<Element*>(this)->EnsureElementRareData();
   if (NamedNodeMap* attribute_map = rare_data.AttributeMap()) {
     return attribute_map;
@@ -996,13 +1000,13 @@
   return attributesVector;
 }
 
-inline ElementRareDataBase* Element::GetElementRareData() const {
+inline ElementRareDataVector* Element::GetElementRareData() const {
   DCHECK(HasRareData());
-  return static_cast<ElementRareDataBase*>(RareData());
+  return static_cast<ElementRareDataVector*>(RareData());
 }
 
-inline ElementRareDataBase& Element::EnsureElementRareData() {
-  return static_cast<ElementRareDataBase&>(EnsureRareData());
+inline ElementRareDataVector& Element::EnsureElementRareData() {
+  return static_cast<ElementRareDataVector&>(EnsureRareData());
 }
 
 void Element::RemovePopoverData() {
@@ -1042,7 +1046,7 @@
 }
 
 ElementAnimations& Element::EnsureElementAnimations() {
-  ElementRareDataBase& rare_data = EnsureElementRareData();
+  ElementRareDataVector& rare_data = EnsureElementRareData();
   if (!rare_data.GetElementAnimations()) {
     rare_data.SetElementAnimations(MakeGarbageCollected<ElementAnimations>());
   }
@@ -2231,7 +2235,7 @@
     return nullptr;
   }
 
-  ElementRareDataBase& rare_data = EnsureElementRareData();
+  ElementRareDataVector& rare_data = EnsureElementRareData();
   return rare_data.EnsureAccessibleNode(this);
 }
 
@@ -2687,7 +2691,7 @@
   }
 
   if (isConnected() && HasRareData()) {
-    ElementRareDataBase* rare_data = GetElementRareData();
+    ElementRareDataVector* rare_data = GetElementRareData();
     if (ElementIntersectionObserverData* observer_data =
             rare_data->IntersectionObserverData()) {
       observer_data->TrackWithController(
@@ -2819,7 +2823,7 @@
   ClearElementFlag(ElementFlags::kIsInCanvasSubtree);
 
   if (HasRareData()) {
-    ElementRareDataBase* data = GetElementRareData();
+    ElementRareDataVector* data = GetElementRareData();
 
     data->ClearFocusgroupFlags();
     data->ClearRestyleFlags();
@@ -2978,7 +2982,7 @@
 void Element::DetachLayoutTree(bool performing_reattach) {
   HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
   if (HasRareData()) {
-    ElementRareDataBase* data = GetElementRareData();
+    ElementRareDataVector* data = GetElementRareData();
     if (!performing_reattach) {
       data->ClearPseudoElements();
       data->ClearContainerQueryData();
@@ -3546,30 +3550,6 @@
   return false;
 }
 
-// LayoutTable[Row,Section,Cell] all amend their ComputedStyle in response
-// to StyleDidChange. Whenever we recalc the style of an element and find
-// no difference, we still need to do ApplyStyleChanges::kYes to perform the
-// amendment.
-static bool ForceApplyForLegacyLayout(const ComputedStyle& new_style,
-                                      const LayoutObject& layout_object) {
-  // See LayoutTable[Section, Row]::StyleDidChange.
-  if (layout_object.IsLegacyTableRow() ||
-      layout_object.IsLegacyTableSection()) {
-    if (new_style.HasInFlowPosition()) {
-      return true;
-    }
-  }
-  // See LayoutTableCell::StyleDidChange.
-  if (layout_object.IsTableCellLegacy()) {
-    if (layout_object.Parent() &&
-        new_style.GetWritingMode() !=
-            layout_object.Parent()->StyleRef().GetWritingMode()) {
-      return true;
-    }
-  }
-  return false;
-}
-
 // This function performs two important tasks:
 //
 //  1. It computes the correct style for the element itself.
@@ -3744,7 +3724,7 @@
   }
 
   if (!new_style && HasRareData()) {
-    ElementRareDataBase* rare_data = GetElementRareData();
+    ElementRareDataVector* rare_data = GetElementRareData();
     if (ElementAnimations* element_animations =
             rare_data->GetElementAnimations()) {
       element_animations->CssAnimations().Cancel();
@@ -3891,9 +3871,6 @@
         apply_changes = LayoutObject::ApplyStyleChanges::kYes;
       }
     }
-    if (ForceApplyForLegacyLayout(*layout_style, *layout_object)) {
-      apply_changes = LayoutObject::ApplyStyleChanges::kYes;
-    }
     layout_object->SetStyle(layout_style.get(), apply_changes);
   }
   return child_change;
@@ -4382,7 +4359,7 @@
 
 void Element::SetRegionCaptureCropId(
     std::unique_ptr<RegionCaptureCropId> crop_id) {
-  ElementRareDataBase& rare_data = EnsureElementRareData();
+  ElementRareDataVector& rare_data = EnsureElementRareData();
 
   CHECK(!rare_data.GetRegionCaptureCropId());
 
@@ -7124,7 +7101,7 @@
 }
 
 DOMTokenList& Element::classList() {
-  ElementRareDataBase& rare_data = EnsureElementRareData();
+  ElementRareDataVector& rare_data = EnsureElementRareData();
   if (!rare_data.GetClassList()) {
     auto* class_list =
         MakeGarbageCollected<DOMTokenList>(*this, html_names::kClassAttr);
@@ -7136,7 +7113,7 @@
 }
 
 DOMStringMap& Element::dataset() {
-  ElementRareDataBase& rare_data = EnsureElementRareData();
+  ElementRareDataVector& rare_data = EnsureElementRareData();
   if (!rare_data.Dataset()) {
     rare_data.SetDataset(MakeGarbageCollected<DatasetDOMStringMap>(this));
   }
@@ -8319,7 +8296,7 @@
 }
 
 DOMTokenList& Element::part() {
-  ElementRareDataBase& rare_data = EnsureElementRareData();
+  ElementRareDataVector& rare_data = EnsureElementRareData();
   DOMTokenList* part = rare_data.GetPart();
   if (!part) {
     part = MakeGarbageCollected<DOMTokenList>(*this, html_names::kPartAttr);
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index fc0044d..d89abec 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -90,7 +90,7 @@
 class ElementAnimations;
 class ElementInternals;
 class ElementIntersectionObserverData;
-class ElementRareDataBase;
+class ElementRareDataVector;
 class ExceptionState;
 class FocusOptions;
 class GetInnerHTMLOptions;
@@ -1545,8 +1545,8 @@
                             bool include_shadow_roots,
                             ExceptionState&);
 
-  ElementRareDataBase* GetElementRareData() const;
-  ElementRareDataBase& EnsureElementRareData();
+  ElementRareDataVector* GetElementRareData() const;
+  ElementRareDataVector& EnsureElementRareData();
 
   void RemoveAttrNodeList();
   void DetachAllAttrNodesFromElement();
diff --git a/third_party/blink/renderer/core/dom/element_rare_data.cc b/third_party/blink/renderer/core/dom/element_rare_data.cc
deleted file mode 100644
index 469da517..0000000
--- a/third_party/blink/renderer/core/dom/element_rare_data.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * 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.
- */
-
-#include "third_party/blink/renderer/core/dom/element_rare_data.h"
-
-#include <memory>
-#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
-#include "third_party/blink/renderer/core/css/container_query_data.h"
-#include "third_party/blink/renderer/core/css/cssom/inline_style_property_map.h"
-#include "third_party/blink/renderer/core/editing/ime/edit_context.h"
-#include "third_party/blink/renderer/core/html/anchor_element_observer.h"
-#include "third_party/blink/renderer/core/html/custom/element_internals.h"
-#include "third_party/blink/renderer/core/layout/anchor_scroll_data.h"
-#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
-#include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
-#include "third_party/blink/renderer/core/style/computed_style.h"
-#include "third_party/blink/renderer/platform/wtf/size_assertions.h"
-
-namespace blink {
-
-struct SameSizeAsElementRareData : ElementRareDataBase {
-  void* pointers_or_strings[4];
-  Member<void*> members[22];
-  absl::optional<LayoutUnit> last_remembered_block_size;
-  absl::optional<LayoutUnit> last_remembered_inline_size;
-  gfx::Vector2dF scroll_offset;
-  wtf_size_t implicitly_anchored_element_count;
-};
-
-ElementRareData::ElementRareData(NodeData* node_layout_data)
-    : ElementRareDataBase(node_layout_data), class_list_(nullptr) {}
-
-ElementRareData::~ElementRareData() {
-  DCHECK(!pseudo_element_data_);
-}
-
-CSSStyleDeclaration& ElementRareData::EnsureInlineCSSStyleDeclaration(
-    Element* owner_element) {
-  if (!cssom_wrapper_) {
-    cssom_wrapper_ =
-        MakeGarbageCollected<InlineCSSStyleDeclaration>(owner_element);
-  }
-  return *cssom_wrapper_;
-}
-
-InlineStylePropertyMap& ElementRareData::EnsureInlineStylePropertyMap(
-    Element* owner_element) {
-  if (!cssom_map_wrapper_) {
-    cssom_map_wrapper_ =
-        MakeGarbageCollected<InlineStylePropertyMap>(owner_element);
-  }
-  return *cssom_map_wrapper_;
-}
-
-AttrNodeList& ElementRareData::EnsureAttrNodeList() {
-  if (!attr_node_list_)
-    attr_node_list_ = MakeGarbageCollected<AttrNodeList>();
-  return *attr_node_list_;
-}
-
-ElementRareData::ResizeObserverDataMap&
-ElementRareData::EnsureResizeObserverData() {
-  if (!resize_observer_data_) {
-    resize_observer_data_ = MakeGarbageCollected<
-        HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>>();
-  }
-  return *resize_observer_data_;
-}
-
-PopoverData& ElementRareData::EnsurePopoverData() {
-  if (!popover_data_)
-    popover_data_ = MakeGarbageCollected<PopoverData>();
-  return *popover_data_;
-}
-void ElementRareData::RemovePopoverData() {
-  popover_data_.Clear();
-}
-
-CSSToggleMap& ElementRareData::EnsureToggleMap(Element* owner_element) {
-  DCHECK(!toggle_map_ || toggle_map_->OwnerElement() == owner_element);
-  if (!toggle_map_)
-    toggle_map_ = MakeGarbageCollected<CSSToggleMap>(owner_element);
-  return *toggle_map_;
-}
-
-ElementInternals& ElementRareData::EnsureElementInternals(HTMLElement& target) {
-  if (element_internals_)
-    return *element_internals_;
-  element_internals_ = MakeGarbageCollected<ElementInternals>(target);
-  return *element_internals_;
-}
-
-AnchorScrollData& ElementRareData::EnsureAnchorScrollData(
-    Element* owner_element) {
-  DCHECK(!anchor_scroll_data_ ||
-         anchor_scroll_data_->OwnerElement() == owner_element);
-  if (!anchor_scroll_data_)
-    anchor_scroll_data_ = MakeGarbageCollected<AnchorScrollData>(owner_element);
-  return *anchor_scroll_data_;
-}
-
-AnchorElementObserver& ElementRareData::EnsureAnchorElementObserver(
-    HTMLElement* element) {
-  DCHECK(!anchor_element_observer_ ||
-         anchor_element_observer_->GetElement() == element);
-  if (!anchor_element_observer_) {
-    anchor_element_observer_ =
-        MakeGarbageCollected<AnchorElementObserver>(element);
-  }
-  return *anchor_element_observer_;
-}
-
-void ElementRareData::Trace(blink::Visitor* visitor) const {
-  visitor->Trace(dataset_);
-  visitor->Trace(shadow_root_);
-  visitor->Trace(class_list_);
-  visitor->Trace(attribute_map_);
-  visitor->Trace(attr_node_list_);
-  visitor->Trace(cssom_wrapper_);
-  visitor->Trace(element_animations_);
-  visitor->Trace(intersection_observer_data_);
-  visitor->Trace(pseudo_element_data_);
-  visitor->Trace(edit_context_);
-  visitor->Trace(part_);
-  visitor->Trace(cssom_map_wrapper_);
-  visitor->Trace(element_internals_);
-  visitor->Trace(accessible_node_);
-  visitor->Trace(display_lock_context_);
-  visitor->Trace(container_query_data_);
-  visitor->Trace(resize_observer_data_);
-  visitor->Trace(custom_element_definition_);
-  visitor->Trace(popover_data_);
-  visitor->Trace(toggle_map_);
-  visitor->Trace(anchor_scroll_data_);
-  visitor->Trace(anchor_element_observer_);
-  NodeRareData::Trace(visitor);
-}
-
-ASSERT_SIZE(ElementRareData, SameSizeAsElementRareData);
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/element_rare_data.h b/third_party/blink/renderer/core/dom/element_rare_data.h
deleted file mode 100644
index 86613a80..0000000
--- a/third_party/blink/renderer/core/dom/element_rare_data.h
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2008 David Smith <catfish.man@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_RARE_DATA_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_RARE_DATA_H_
-
-#include <memory>
-
-#include "base/token.h"
-#include "third_party/blink/renderer/core/animation/element_animations.h"
-#include "third_party/blink/renderer/core/aom/accessible_node.h"
-#include "third_party/blink/renderer/core/css/container_query_data.h"
-#include "third_party/blink/renderer/core/css/cssom/inline_style_property_map.h"
-#include "third_party/blink/renderer/core/css/inline_css_style_declaration.h"
-#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
-#include "third_party/blink/renderer/core/dom/attr.h"
-#include "third_party/blink/renderer/core/dom/css_toggle_map.h"
-#include "third_party/blink/renderer/core/dom/dataset_dom_string_map.h"
-#include "third_party/blink/renderer/core/dom/dom_token_list.h"
-#include "third_party/blink/renderer/core/dom/element_rare_data_base.h"
-#include "third_party/blink/renderer/core/dom/focusgroup_flags.h"
-#include "third_party/blink/renderer/core/dom/has_invalidation_flags.h"
-#include "third_party/blink/renderer/core/dom/named_node_map.h"
-#include "third_party/blink/renderer/core/dom/names_map.h"
-#include "third_party/blink/renderer/core/dom/node_rare_data.h"
-#include "third_party/blink/renderer/core/dom/popover_data.h"
-#include "third_party/blink/renderer/core/dom/pseudo_element.h"
-#include "third_party/blink/renderer/core/dom/pseudo_element_data.h"
-#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/dom/space_split_string.h"
-#include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
-#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/region_capture_crop_id.h"
-
-namespace blink {
-
-class AnchorElementObserver;
-class AnchorScrollData;
-class ContainerQueryData;
-class Element;
-class HTMLElement;
-class ResizeObservation;
-class ResizeObserver;
-
-class ElementRareData final : public ElementRareDataBase {
- public:
-  explicit ElementRareData(NodeData*);
-  ~ElementRareData() override;
-
-  void SetPseudoElement(
-      PseudoId,
-      PseudoElement*,
-      const AtomicString& view_transition_name = g_null_atom) override;
-  PseudoElement* GetPseudoElement(
-      PseudoId,
-      const AtomicString& view_transition_name = g_null_atom) const override;
-  PseudoElementData::PseudoElementVector GetPseudoElements() const override;
-
-  CSSStyleDeclaration& EnsureInlineCSSStyleDeclaration(
-      Element* owner_element) override;
-
-  ShadowRoot* GetShadowRoot() const override { return shadow_root_.Get(); }
-  void SetShadowRoot(ShadowRoot& shadow_root) override {
-    DCHECK(!shadow_root_);
-    shadow_root_ = &shadow_root;
-  }
-
-  NamedNodeMap* AttributeMap() const override { return attribute_map_.Get(); }
-  void SetAttributeMap(NamedNodeMap* attribute_map) override {
-    attribute_map_ = attribute_map;
-  }
-
-  DOMTokenList* GetClassList() const override { return class_list_.Get(); }
-  void SetClassList(DOMTokenList* class_list) override {
-    class_list_ = class_list;
-  }
-
-  DatasetDOMStringMap* Dataset() const override { return dataset_.Get(); }
-  void SetDataset(DatasetDOMStringMap* dataset) override { dataset_ = dataset; }
-
-  ScrollOffset SavedLayerScrollOffset() const override {
-    return saved_layer_scroll_offset_;
-  }
-  void SetSavedLayerScrollOffset(ScrollOffset offset) override {
-    saved_layer_scroll_offset_ = offset;
-  }
-
-  ElementAnimations* GetElementAnimations() override {
-    return element_animations_.Get();
-  }
-  void SetElementAnimations(ElementAnimations* element_animations) override {
-    element_animations_ = element_animations;
-  }
-
-  bool HasPseudoElements() const override;
-  void ClearPseudoElements() override;
-
-  AttrNodeList& EnsureAttrNodeList() override;
-  AttrNodeList* GetAttrNodeList() override { return attr_node_list_.Get(); }
-  void RemoveAttrNodeList() override { attr_node_list_.Clear(); }
-  void AddAttr(Attr* attr) override { EnsureAttrNodeList().push_back(attr); }
-
-  ElementIntersectionObserverData* IntersectionObserverData() const override {
-    return intersection_observer_data_.Get();
-  }
-  ElementIntersectionObserverData& EnsureIntersectionObserverData() override {
-    if (!intersection_observer_data_) {
-      intersection_observer_data_ =
-          MakeGarbageCollected<ElementIntersectionObserverData>();
-    }
-    return *intersection_observer_data_;
-  }
-
-  ContainerQueryEvaluator* GetContainerQueryEvaluator() const override {
-    ContainerQueryData* container_query_data = GetContainerQueryData();
-    if (!container_query_data)
-      return nullptr;
-    return container_query_data->GetContainerQueryEvaluator();
-  }
-  void SetContainerQueryEvaluator(ContainerQueryEvaluator* evaluator) override {
-    ContainerQueryData* container_query_data = GetContainerQueryData();
-    if (container_query_data)
-      container_query_data->SetContainerQueryEvaluator(evaluator);
-    else if (evaluator)
-      EnsureContainerQueryData().SetContainerQueryEvaluator(evaluator);
-  }
-
-  const AtomicString& GetNonce() const override { return nonce_; }
-  void SetNonce(const AtomicString& nonce) override { nonce_ = nonce; }
-
-  EditContext* GetEditContext() const override { return edit_context_.Get(); }
-  void SetEditContext(EditContext* edit_context) override {
-    edit_context_ = edit_context;
-  }
-
-  void SetPart(DOMTokenList* part) override { part_ = part; }
-  DOMTokenList* GetPart() const override { return part_.Get(); }
-
-  void SetPartNamesMap(const AtomicString part_names) override {
-    if (!part_names_map_) {
-      part_names_map_ = std::make_unique<NamesMap>();
-    }
-    part_names_map_->Set(part_names);
-  }
-  const NamesMap* PartNamesMap() const override {
-    return part_names_map_.get();
-  }
-
-  InlineStylePropertyMap& EnsureInlineStylePropertyMap(
-      Element* owner_element) override;
-  InlineStylePropertyMap* GetInlineStylePropertyMap() override {
-    return cssom_map_wrapper_.Get();
-  }
-
-  ElementInternals& EnsureElementInternals(HTMLElement& target) override;
-  const ElementInternals* GetElementInternals() const override {
-    return element_internals_;
-  }
-
-  AccessibleNode* GetAccessibleNode() const override {
-    return accessible_node_.Get();
-  }
-  AccessibleNode* EnsureAccessibleNode(Element* owner_element) override {
-    if (!accessible_node_) {
-      accessible_node_ = MakeGarbageCollected<AccessibleNode>(owner_element);
-    }
-    return accessible_node_;
-  }
-  void ClearAccessibleNode() override { accessible_node_.Clear(); }
-
-  DisplayLockContext* EnsureDisplayLockContext(Element* element) override {
-    if (!display_lock_context_) {
-      display_lock_context_ = MakeGarbageCollected<DisplayLockContext>(element);
-    }
-    return display_lock_context_.Get();
-  }
-  DisplayLockContext* GetDisplayLockContext() const override {
-    return display_lock_context_;
-  }
-
-  ContainerQueryData& EnsureContainerQueryData() override {
-    if (!container_query_data_)
-      container_query_data_ = MakeGarbageCollected<ContainerQueryData>();
-    return *container_query_data_;
-  }
-  ContainerQueryData* GetContainerQueryData() const override {
-    return container_query_data_;
-  }
-  void ClearContainerQueryData() override { container_query_data_ = nullptr; }
-
-  // Returns the crop-ID if one was set, or nullptr otherwise.
-  const RegionCaptureCropId* GetRegionCaptureCropId() const override {
-    return region_capture_crop_id_.get();
-  }
-
-  // Sets a crop-ID on the item. Must be called at most once. Cannot be used
-  // to unset a previously set crop-ID.
-  void SetRegionCaptureCropId(
-      std::unique_ptr<RegionCaptureCropId> crop_id) override {
-    DCHECK(!GetRegionCaptureCropId());
-    DCHECK(crop_id);
-    DCHECK(!crop_id->value().is_zero());
-    region_capture_crop_id_ = std::move(crop_id);
-  }
-
-  using ResizeObserverDataMap =
-      HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>;
-
-  ResizeObserverDataMap* ResizeObserverData() const override {
-    return resize_observer_data_;
-  }
-  ResizeObserverDataMap& EnsureResizeObserverData() override;
-
-  void SetCustomElementDefinition(
-      CustomElementDefinition* definition) override {
-    custom_element_definition_ = definition;
-  }
-  CustomElementDefinition* GetCustomElementDefinition() const override {
-    return custom_element_definition_.Get();
-  }
-
-  void SetIsValue(const AtomicString& is_value) override {
-    is_value_ = is_value;
-  }
-  const AtomicString& IsValue() const override { return is_value_; }
-
-  void SetLastRememberedBlockSize(absl::optional<LayoutUnit> size) override {
-    last_intrinsic_block_size_ = size;
-  }
-  void SetLastRememberedInlineSize(absl::optional<LayoutUnit> size) override {
-    last_intrinsic_inline_size_ = size;
-  }
-  absl::optional<LayoutUnit> LastRememberedBlockSize() const override {
-    return last_intrinsic_block_size_;
-  }
-  absl::optional<LayoutUnit> LastRememberedInlineSize() const override {
-    return last_intrinsic_inline_size_;
-  }
-
-  PopoverData* GetPopoverData() const override { return popover_data_; }
-  PopoverData& EnsurePopoverData() override;
-  void RemovePopoverData() override;
-
-  CSSToggleMap* GetToggleMap() const override { return toggle_map_.Get(); }
-  CSSToggleMap& EnsureToggleMap(Element* owner_element) override;
-
-  AnchorScrollData* GetAnchorScrollData() const override {
-    return anchor_scroll_data_;
-  }
-  void RemoveAnchorScrollData() override { anchor_scroll_data_ = nullptr; }
-  AnchorScrollData& EnsureAnchorScrollData(Element*) override;
-
-  bool HasElementFlag(ElementFlags mask) const override {
-    return element_flags_ & static_cast<uint16_t>(mask);
-  }
-  void SetElementFlag(ElementFlags mask, bool value) override {
-    element_flags_ =
-        (element_flags_ & ~static_cast<uint16_t>(mask)) |
-        (-static_cast<uint16_t>(value) & static_cast<uint16_t>(mask));
-  }
-  void ClearElementFlag(ElementFlags mask) override {
-    element_flags_ &= ~static_cast<uint16_t>(mask);
-  }
-
-  bool HasRestyleFlags() const override {
-    return bit_field_.get<RestyleFlags>();
-  }
-  void ClearRestyleFlags() override { bit_field_.set<RestyleFlags>(0); }
-
-  void SetTabIndexExplicitly() override {
-    SetElementFlag(ElementFlags::kTabIndexWasSetExplicitly, true);
-  }
-  void ClearTabIndexExplicitly() override {
-    ClearElementFlag(ElementFlags::kTabIndexWasSetExplicitly);
-  }
-
-  AnchorElementObserver* GetAnchorElementObserver() const override {
-    return anchor_element_observer_;
-  }
-  AnchorElementObserver& EnsureAnchorElementObserver(HTMLElement*) override;
-
-  void IncrementImplicitlyAnchoredElementCount() override {
-    ++implicitly_anchored_element_count_;
-  }
-  void DecrementImplicitlyAnchoredElementCount() override {
-    DCHECK(implicitly_anchored_element_count_);
-    --implicitly_anchored_element_count_;
-  }
-  bool HasImplicitlyAnchoredElement() const override {
-    return implicitly_anchored_element_count_;
-  }
-
-  void Trace(blink::Visitor*) const override;
-
- private:
-  AtomicString nonce_;
-  AtomicString is_value_;
-
-  std::unique_ptr<NamesMap> part_names_map_;
-  std::unique_ptr<RegionCaptureCropId> region_capture_crop_id_;
-
-  Member<DatasetDOMStringMap> dataset_;
-  Member<ShadowRoot> shadow_root_;
-  Member<DOMTokenList> class_list_;
-  Member<NamedNodeMap> attribute_map_;
-  Member<AttrNodeList> attr_node_list_;
-  Member<InlineCSSStyleDeclaration> cssom_wrapper_;
-  Member<ElementAnimations> element_animations_;
-  Member<ElementIntersectionObserverData> intersection_observer_data_;
-  Member<PseudoElementData> pseudo_element_data_;
-  Member<EditContext> edit_context_;
-  Member<DOMTokenList> part_;
-  Member<InlineStylePropertyMap> cssom_map_wrapper_;
-  Member<ElementInternals> element_internals_;
-  Member<AccessibleNode> accessible_node_;
-  Member<DisplayLockContext> display_lock_context_;
-  Member<ContainerQueryData> container_query_data_;
-  Member<ResizeObserverDataMap> resize_observer_data_;
-  Member<CustomElementDefinition> custom_element_definition_;
-  Member<PopoverData> popover_data_;
-  Member<CSSToggleMap> toggle_map_;
-  Member<AnchorScrollData> anchor_scroll_data_;
-  Member<AnchorElementObserver> anchor_element_observer_;
-
-  ScrollOffset saved_layer_scroll_offset_;
-  wtf_size_t implicitly_anchored_element_count_ = 0;
-  absl::optional<LayoutUnit> last_intrinsic_block_size_;
-  absl::optional<LayoutUnit> last_intrinsic_inline_size_;
-};
-
-inline LayoutSize DefaultMinimumSizeForResizing() {
-  return LayoutSize(LayoutUnit::Max(), LayoutUnit::Max());
-}
-
-inline bool ElementRareData::HasPseudoElements() const {
-  return (pseudo_element_data_ && pseudo_element_data_->HasPseudoElements());
-}
-
-inline void ElementRareData::ClearPseudoElements() {
-  if (pseudo_element_data_) {
-    pseudo_element_data_->ClearPseudoElements();
-    pseudo_element_data_.Clear();
-  }
-}
-
-inline void ElementRareData::SetPseudoElement(
-    PseudoId pseudo_id,
-    PseudoElement* element,
-    const AtomicString& view_transition_name) {
-  if (!pseudo_element_data_) {
-    if (!element)
-      return;
-    pseudo_element_data_ = MakeGarbageCollected<PseudoElementData>();
-  }
-  pseudo_element_data_->SetPseudoElement(pseudo_id, element,
-                                         view_transition_name);
-}
-
-inline PseudoElement* ElementRareData::GetPseudoElement(
-    PseudoId pseudo_id,
-    const AtomicString& view_transition_name) const {
-  if (!pseudo_element_data_)
-    return nullptr;
-  return pseudo_element_data_->GetPseudoElement(pseudo_id,
-                                                view_transition_name);
-}
-
-inline PseudoElementData::PseudoElementVector
-ElementRareData::GetPseudoElements() const {
-  if (!pseudo_element_data_)
-    return {};
-  return pseudo_element_data_->GetPseudoElements();
-}
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_RARE_DATA_H_
diff --git a/third_party/blink/renderer/core/dom/element_rare_data_base.h b/third_party/blink/renderer/core/dom/element_rare_data_base.h
deleted file mode 100644
index a51ce41..0000000
--- a/third_party/blink/renderer/core/dom/element_rare_data_base.h
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright 2022 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_CORE_DOM_ELEMENT_RARE_DATA_BASE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_RARE_DATA_BASE_H_
-
-#include "third_party/blink/renderer/core/dom/focusgroup_flags.h"
-#include "third_party/blink/renderer/core/dom/node_rare_data.h"
-#include "third_party/blink/renderer/core/dom/pseudo_element.h"
-#include "third_party/blink/renderer/core/dom/pseudo_element_data.h"
-#include "third_party/blink/renderer/platform/region_capture_crop_id.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-
-namespace blink {
-
-class CSSStyleDeclaration;
-class ShadowRoot;
-class NamedNodeMap;
-class DOMTokenList;
-class DatasetDOMStringMap;
-class ElementAnimations;
-class Attr;
-typedef HeapVector<Member<Attr>> AttrNodeList;
-class ElementIntersectionObserverData;
-class ContainerQueryEvaluator;
-class EditContext;
-class AnchorElementObserver;
-class InlineStylePropertyMap;
-class ElementInternals;
-class AccessibleNode;
-class DisplayLockContext;
-class ContainerQueryData;
-class ResizeObserver;
-class ResizeObservation;
-class CustomElementDefinition;
-class PopoverData;
-class CSSToggleMap;
-class HTMLElement;
-
-enum class ElementFlags;
-
-class ElementRareDataBase : public NodeRareData {
- public:
-  explicit ElementRareDataBase(NodeData* node_layout_data)
-      : NodeRareData(ClassType::kElementRareData,
-                     std::move(*node_layout_data)) {}
-
-  virtual void SetPseudoElement(
-      PseudoId,
-      PseudoElement*,
-      const AtomicString& document_transition_tag = g_null_atom) = 0;
-  virtual PseudoElement* GetPseudoElement(
-      PseudoId,
-      const AtomicString& document_transition_tag = g_null_atom) const = 0;
-  virtual PseudoElementData::PseudoElementVector GetPseudoElements() const = 0;
-
-  virtual CSSStyleDeclaration& EnsureInlineCSSStyleDeclaration(
-      Element* owner_element) = 0;
-
-  virtual ShadowRoot* GetShadowRoot() const = 0;
-  virtual void SetShadowRoot(ShadowRoot& shadow_root) = 0;
-
-  virtual NamedNodeMap* AttributeMap() const = 0;
-  virtual void SetAttributeMap(NamedNodeMap* attribute_map) = 0;
-
-  virtual DOMTokenList* GetClassList() const = 0;
-  virtual void SetClassList(DOMTokenList* class_list) = 0;
-
-  virtual DatasetDOMStringMap* Dataset() const = 0;
-  virtual void SetDataset(DatasetDOMStringMap* dataset) = 0;
-
-  virtual ScrollOffset SavedLayerScrollOffset() const = 0;
-  virtual void SetSavedLayerScrollOffset(ScrollOffset offset) = 0;
-
-  virtual ElementAnimations* GetElementAnimations() = 0;
-  virtual void SetElementAnimations(ElementAnimations* element_animations) = 0;
-
-  virtual bool HasPseudoElements() const = 0;
-  virtual void ClearPseudoElements() = 0;
-
-  virtual AttrNodeList& EnsureAttrNodeList() = 0;
-  virtual AttrNodeList* GetAttrNodeList() = 0;
-  virtual void RemoveAttrNodeList() = 0;
-  virtual void AddAttr(Attr* attr) = 0;
-
-  virtual ElementIntersectionObserverData* IntersectionObserverData() const = 0;
-  virtual ElementIntersectionObserverData& EnsureIntersectionObserverData() = 0;
-
-  virtual ContainerQueryEvaluator* GetContainerQueryEvaluator() const = 0;
-  virtual void SetContainerQueryEvaluator(
-      ContainerQueryEvaluator* evaluator) = 0;
-
-  virtual const AtomicString& GetNonce() const = 0;
-  virtual void SetNonce(const AtomicString& nonce) = 0;
-
-  virtual EditContext* GetEditContext() const = 0;
-  virtual void SetEditContext(EditContext* edit_context) = 0;
-
-  virtual void SetPart(DOMTokenList* part) = 0;
-  virtual DOMTokenList* GetPart() const = 0;
-
-  virtual void SetPartNamesMap(const AtomicString part_names) = 0;
-  virtual const NamesMap* PartNamesMap() const = 0;
-
-  virtual InlineStylePropertyMap& EnsureInlineStylePropertyMap(
-      Element* owner_element) = 0;
-  virtual InlineStylePropertyMap* GetInlineStylePropertyMap() = 0;
-
-  virtual ElementInternals& EnsureElementInternals(HTMLElement& target) = 0;
-  virtual const ElementInternals* GetElementInternals() const = 0;
-
-  virtual AccessibleNode* GetAccessibleNode() const = 0;
-  virtual AccessibleNode* EnsureAccessibleNode(Element* owner_element) = 0;
-  virtual void ClearAccessibleNode() = 0;
-
-  virtual DisplayLockContext* EnsureDisplayLockContext(Element* element) = 0;
-  virtual DisplayLockContext* GetDisplayLockContext() const = 0;
-
-  virtual ContainerQueryData& EnsureContainerQueryData() = 0;
-  virtual ContainerQueryData* GetContainerQueryData() const = 0;
-  virtual void ClearContainerQueryData() = 0;
-
-  // Returns the crop-ID if one was set, or nullptr otherwise.
-  virtual const RegionCaptureCropId* GetRegionCaptureCropId() const = 0;
-
-  // Sets a crop-ID on the item. Must be called at most once. Cannot be used
-  // to unset a previously set crop-ID.
-  virtual void SetRegionCaptureCropId(
-      std::unique_ptr<RegionCaptureCropId> crop_id) = 0;
-
-  using ResizeObserverDataMap =
-      HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>;
-
-  virtual ResizeObserverDataMap* ResizeObserverData() const = 0;
-  virtual ResizeObserverDataMap& EnsureResizeObserverData() = 0;
-
-  virtual void SetCustomElementDefinition(
-      CustomElementDefinition* definition) = 0;
-  virtual CustomElementDefinition* GetCustomElementDefinition() const = 0;
-
-  virtual void SetIsValue(const AtomicString& is_value) = 0;
-  virtual const AtomicString& IsValue() const = 0;
-
-  virtual void SetLastRememberedBlockSize(absl::optional<LayoutUnit> size) = 0;
-  virtual void SetLastRememberedInlineSize(absl::optional<LayoutUnit> size) = 0;
-  virtual absl::optional<LayoutUnit> LastRememberedBlockSize() const = 0;
-  virtual absl::optional<LayoutUnit> LastRememberedInlineSize() const = 0;
-
-  virtual PopoverData* GetPopoverData() const = 0;
-  virtual PopoverData& EnsurePopoverData() = 0;
-  virtual void RemovePopoverData() = 0;
-
-  virtual CSSToggleMap* GetToggleMap() const = 0;
-  virtual CSSToggleMap& EnsureToggleMap(Element* owner_element) = 0;
-
-  FocusgroupFlags GetFocusgroupFlags() const { return focusgroup_flags_; }
-  void SetFocusgroupFlags(FocusgroupFlags flags) { focusgroup_flags_ = flags; }
-  void ClearFocusgroupFlags() { focusgroup_flags_ = FocusgroupFlags::kNone; }
-
-  bool AffectedBySubjectHas() const {
-    return has_invalidation_flags_.affected_by_subject_has;
-  }
-  void SetAffectedBySubjectHas() {
-    has_invalidation_flags_.affected_by_subject_has = true;
-  }
-  bool AffectedByNonSubjectHas() const {
-    return has_invalidation_flags_.affected_by_non_subject_has;
-  }
-  void SetAffectedByNonSubjectHas() {
-    has_invalidation_flags_.affected_by_non_subject_has = true;
-  }
-  bool AncestorsOrAncestorSiblingsAffectedByHas() const {
-    return has_invalidation_flags_
-        .ancestors_or_ancestor_siblings_affected_by_has;
-  }
-  void SetAncestorsOrAncestorSiblingsAffectedByHas() {
-    has_invalidation_flags_.ancestors_or_ancestor_siblings_affected_by_has =
-        true;
-  }
-  unsigned GetSiblingsAffectedByHasFlags() const {
-    return has_invalidation_flags_.siblings_affected_by_has;
-  }
-  bool HasSiblingsAffectedByHasFlags(unsigned flags) const {
-    return has_invalidation_flags_.siblings_affected_by_has & flags;
-  }
-  void SetSiblingsAffectedByHasFlags(unsigned flags) {
-    has_invalidation_flags_.siblings_affected_by_has |= flags;
-  }
-  bool AffectedByPseudoInHas() const {
-    return has_invalidation_flags_.affected_by_pseudos_in_has;
-  }
-  void SetAffectedByPseudoInHas() {
-    has_invalidation_flags_.affected_by_pseudos_in_has = true;
-  }
-  bool AncestorsOrSiblingsAffectedByHoverInHas() const {
-    return has_invalidation_flags_
-        .ancestors_or_siblings_affected_by_hover_in_has;
-  }
-  void SetAncestorsOrSiblingsAffectedByHoverInHas() {
-    has_invalidation_flags_.ancestors_or_siblings_affected_by_hover_in_has =
-        true;
-  }
-  bool AncestorsOrSiblingsAffectedByActiveInHas() const {
-    return has_invalidation_flags_
-        .ancestors_or_siblings_affected_by_active_in_has;
-  }
-  void SetAncestorsOrSiblingsAffectedByActiveInHas() {
-    has_invalidation_flags_.ancestors_or_siblings_affected_by_active_in_has =
-        true;
-  }
-  bool AncestorsOrSiblingsAffectedByFocusInHas() const {
-    return has_invalidation_flags_
-        .ancestors_or_siblings_affected_by_focus_in_has;
-  }
-  void SetAncestorsOrSiblingsAffectedByFocusInHas() {
-    has_invalidation_flags_.ancestors_or_siblings_affected_by_focus_in_has =
-        true;
-  }
-  bool AncestorsOrSiblingsAffectedByFocusVisibleInHas() const {
-    return has_invalidation_flags_
-        .ancestors_or_siblings_affected_by_focus_visible_in_has;
-  }
-  void SetAncestorsOrSiblingsAffectedByFocusVisibleInHas() {
-    has_invalidation_flags_
-        .ancestors_or_siblings_affected_by_focus_visible_in_has = true;
-  }
-  bool AffectedByLogicalCombinationsInHas() const {
-    return has_invalidation_flags_.affected_by_logical_combinations_in_has;
-  }
-  void SetAffectedByLogicalCombinationsInHas() {
-    has_invalidation_flags_.affected_by_logical_combinations_in_has = true;
-  }
-  bool AffectedByMultipleHas() const {
-    return has_invalidation_flags_.affected_by_multiple_has;
-  }
-  void SetAffectedByMultipleHas() {
-    has_invalidation_flags_.affected_by_multiple_has = true;
-  }
-
-  virtual void SetTabIndexExplicitly() = 0;
-  virtual void ClearTabIndexExplicitly() = 0;
-
-  virtual AnchorScrollData* GetAnchorScrollData() const = 0;
-  virtual void RemoveAnchorScrollData() = 0;
-  virtual AnchorScrollData& EnsureAnchorScrollData(Element*) = 0;
-
-  virtual AnchorElementObserver* GetAnchorElementObserver() const = 0;
-  virtual AnchorElementObserver& EnsureAnchorElementObserver(HTMLElement*) = 0;
-
-  virtual void IncrementImplicitlyAnchoredElementCount() = 0;
-  virtual void DecrementImplicitlyAnchoredElementCount() = 0;
-  virtual bool HasImplicitlyAnchoredElement() const = 0;
-
-  // from NodeRareData
-  virtual bool HasElementFlag(ElementFlags mask) const = 0;
-  virtual void SetElementFlag(ElementFlags mask, bool value) = 0;
-  virtual void ClearElementFlag(ElementFlags mask) = 0;
-  virtual bool HasRestyleFlags() const = 0;
-  virtual void ClearRestyleFlags() = 0;
-
-  void SetDidAttachInternals() { did_attach_internals_ = true; }
-  bool DidAttachInternals() const { return did_attach_internals_; }
-  void SetStyleShouldForceLegacyLayout(bool force) {
-    style_should_force_legacy_layout_ = force;
-  }
-  bool StyleShouldForceLegacyLayout() const {
-    return style_should_force_legacy_layout_;
-  }
-  void SetShouldForceLegacyLayoutForChild(bool force) {
-    should_force_legacy_layout_for_child_ = force;
-  }
-  bool ShouldForceLegacyLayoutForChild() const {
-    return should_force_legacy_layout_for_child_;
-  }
-  bool HasUndoStack() const { return has_undo_stack_; }
-  void SetHasUndoStack(bool value) { has_undo_stack_ = value; }
-  bool ScrollbarPseudoElementStylesDependOnFontMetrics() const {
-    return scrollbar_pseudo_element_styles_depend_on_font_metrics_;
-  }
-  void SetScrollbarPseudoElementStylesDependOnFontMetrics(bool value) {
-    scrollbar_pseudo_element_styles_depend_on_font_metrics_ = value;
-  }
-
- private:
-  unsigned did_attach_internals_ : 1;
-  unsigned should_force_legacy_layout_for_child_ : 1;
-  unsigned style_should_force_legacy_layout_ : 1;
-  unsigned has_undo_stack_ : 1;
-  unsigned scrollbar_pseudo_element_styles_depend_on_font_metrics_ : 1;
-  HasInvalidationFlags has_invalidation_flags_;
-  FocusgroupFlags focusgroup_flags_ = FocusgroupFlags::kNone;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_RARE_DATA_BASE_H_
diff --git a/third_party/blink/renderer/core/dom/element_rare_data_vector.cc b/third_party/blink/renderer/core/dom/element_rare_data_vector.cc
index 0b55856..f52ffb4 100644
--- a/third_party/blink/renderer/core/dom/element_rare_data_vector.cc
+++ b/third_party/blink/renderer/core/dom/element_rare_data_vector.cc
@@ -14,7 +14,6 @@
 #include "third_party/blink/renderer/core/dom/css_toggle_map.h"
 #include "third_party/blink/renderer/core/dom/dataset_dom_string_map.h"
 #include "third_party/blink/renderer/core/dom/dom_token_list.h"
-#include "third_party/blink/renderer/core/dom/element_rare_data_base.h"
 #include "third_party/blink/renderer/core/dom/has_invalidation_flags.h"
 #include "third_party/blink/renderer/core/dom/named_node_map.h"
 #include "third_party/blink/renderer/core/dom/names_map.h"
@@ -37,7 +36,7 @@
 namespace blink {
 
 ElementRareDataVector::ElementRareDataVector(NodeData* node_layout_data)
-    : ElementRareDataBase(node_layout_data) {}
+    : NodeRareData(ClassType::kElementRareData, std::move(*node_layout_data)) {}
 
 ElementRareDataVector::~ElementRareDataVector() {
   DCHECK(!GetField(FieldId::kPseudoElementData));
@@ -421,7 +420,6 @@
 void ElementRareDataVector::Trace(blink::Visitor* visitor) const {
   visitor->Trace(fields_);
   NodeRareData::Trace(visitor);
-  ElementRareDataBase::Trace(visitor);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/element_rare_data_vector.h b/third_party/blink/renderer/core/dom/element_rare_data_vector.h
index 7d6f31ae..bcb783d 100644
--- a/third_party/blink/renderer/core/dom/element_rare_data_vector.h
+++ b/third_party/blink/renderer/core/dom/element_rare_data_vector.h
@@ -5,12 +5,44 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_RARE_DATA_VECTOR_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_RARE_DATA_VECTOR_H_
 
-#include "third_party/blink/renderer/core/dom/element_rare_data_base.h"
+#include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/element_rare_data_field.h"
+#include "third_party/blink/renderer/core/dom/focusgroup_flags.h"
+#include "third_party/blink/renderer/core/dom/node_rare_data.h"
+#include "third_party/blink/renderer/core/dom/pseudo_element.h"
+#include "third_party/blink/renderer/core/dom/pseudo_element_data.h"
 #include "third_party/blink/renderer/platform/heap/trace_traits.h"
+#include "third_party/blink/renderer/platform/region_capture_crop_id.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
 namespace blink {
 
+class CSSStyleDeclaration;
+class ShadowRoot;
+class NamedNodeMap;
+class DOMTokenList;
+class DatasetDOMStringMap;
+class ElementAnimations;
+class Attr;
+typedef HeapVector<Member<Attr>> AttrNodeList;
+class ElementIntersectionObserverData;
+class ContainerQueryEvaluator;
+class EditContext;
+class AnchorElementObserver;
+class InlineStylePropertyMap;
+class ElementInternals;
+class AccessibleNode;
+class DisplayLockContext;
+class ContainerQueryData;
+class ResizeObserver;
+class ResizeObservation;
+class CustomElementDefinition;
+class PopoverData;
+class CSSToggleMap;
+class HTMLElement;
+
+enum class ElementFlags;
+
 // This class stores lazily-initialized state associated with Elements, each of
 // which is identified in the FieldId enum. Since storing pointers to all of
 // these classes would take up too much memory, we use a Vector and only include
@@ -28,7 +60,7 @@
 //   0: Member<ShadowRoot>
 //   1: Member<EditContext>
 // Bitfield: 0b00000000000000000000001000000010
-class CORE_EXPORT ElementRareDataVector final : public ElementRareDataBase {
+class CORE_EXPORT ElementRareDataVector final : public NodeRareData {
  private:
   friend class ElementRareDataVectorTest;
   enum class FieldId : unsigned {
@@ -146,141 +178,254 @@
   void SetPseudoElement(
       PseudoId,
       PseudoElement*,
-      const AtomicString& document_transition_tag = g_null_atom) override;
+      const AtomicString& document_transition_tag = g_null_atom);
   PseudoElement* GetPseudoElement(
       PseudoId,
-      const AtomicString& document_transition_tag = g_null_atom) const override;
-  PseudoElementData::PseudoElementVector GetPseudoElements() const override;
+      const AtomicString& document_transition_tag = g_null_atom) const;
+  PseudoElementData::PseudoElementVector GetPseudoElements() const;
 
-  CSSStyleDeclaration& EnsureInlineCSSStyleDeclaration(
-      Element* owner_element) override;
+  CSSStyleDeclaration& EnsureInlineCSSStyleDeclaration(Element* owner_element);
 
-  ShadowRoot* GetShadowRoot() const override;
-  void SetShadowRoot(ShadowRoot& shadow_root) override;
+  ShadowRoot* GetShadowRoot() const;
+  void SetShadowRoot(ShadowRoot& shadow_root);
 
-  NamedNodeMap* AttributeMap() const override;
-  void SetAttributeMap(NamedNodeMap* attribute_map) override;
+  NamedNodeMap* AttributeMap() const;
+  void SetAttributeMap(NamedNodeMap* attribute_map);
 
-  DOMTokenList* GetClassList() const override;
-  void SetClassList(DOMTokenList* class_list) override;
+  DOMTokenList* GetClassList() const;
+  void SetClassList(DOMTokenList* class_list);
 
-  DatasetDOMStringMap* Dataset() const override;
-  void SetDataset(DatasetDOMStringMap* dataset) override;
+  DatasetDOMStringMap* Dataset() const;
+  void SetDataset(DatasetDOMStringMap* dataset);
 
-  ScrollOffset SavedLayerScrollOffset() const override;
-  void SetSavedLayerScrollOffset(ScrollOffset offset) override;
+  ScrollOffset SavedLayerScrollOffset() const;
+  void SetSavedLayerScrollOffset(ScrollOffset offset);
 
-  ElementAnimations* GetElementAnimations() override;
-  void SetElementAnimations(ElementAnimations* element_animations) override;
+  ElementAnimations* GetElementAnimations();
+  void SetElementAnimations(ElementAnimations* element_animations);
 
-  bool HasPseudoElements() const override;
-  void ClearPseudoElements() override;
+  bool HasPseudoElements() const;
+  void ClearPseudoElements();
 
-  AttrNodeList& EnsureAttrNodeList() override;
-  AttrNodeList* GetAttrNodeList() override;
-  void RemoveAttrNodeList() override;
-  void AddAttr(Attr* attr) override;
+  AttrNodeList& EnsureAttrNodeList();
+  AttrNodeList* GetAttrNodeList();
+  void RemoveAttrNodeList();
+  void AddAttr(Attr* attr);
 
-  ElementIntersectionObserverData* IntersectionObserverData() const override;
-  ElementIntersectionObserverData& EnsureIntersectionObserverData() override;
+  ElementIntersectionObserverData* IntersectionObserverData() const;
+  ElementIntersectionObserverData& EnsureIntersectionObserverData();
 
-  ContainerQueryEvaluator* GetContainerQueryEvaluator() const override;
-  void SetContainerQueryEvaluator(ContainerQueryEvaluator* evaluator) override;
+  ContainerQueryEvaluator* GetContainerQueryEvaluator() const;
+  void SetContainerQueryEvaluator(ContainerQueryEvaluator* evaluator);
 
-  const AtomicString& GetNonce() const override;
-  void SetNonce(const AtomicString& nonce) override;
+  const AtomicString& GetNonce() const;
+  void SetNonce(const AtomicString& nonce);
 
-  const AtomicString& IsValue() const override;
-  void SetIsValue(const AtomicString& is_value) override;
+  const AtomicString& IsValue() const;
+  void SetIsValue(const AtomicString& is_value);
 
-  EditContext* GetEditContext() const override;
-  void SetEditContext(EditContext* edit_context) override;
+  EditContext* GetEditContext() const;
+  void SetEditContext(EditContext* edit_context);
 
-  void SetPart(DOMTokenList* part) override;
-  DOMTokenList* GetPart() const override;
+  void SetPart(DOMTokenList* part);
+  DOMTokenList* GetPart() const;
 
-  void SetPartNamesMap(const AtomicString part_names) override;
-  const NamesMap* PartNamesMap() const override;
+  void SetPartNamesMap(const AtomicString part_names);
+  const NamesMap* PartNamesMap() const;
 
-  InlineStylePropertyMap& EnsureInlineStylePropertyMap(
-      Element* owner_element) override;
-  InlineStylePropertyMap* GetInlineStylePropertyMap() override;
+  InlineStylePropertyMap& EnsureInlineStylePropertyMap(Element* owner_element);
+  InlineStylePropertyMap* GetInlineStylePropertyMap();
 
-  const ElementInternals* GetElementInternals() const override;
-  ElementInternals& EnsureElementInternals(HTMLElement& target) override;
+  const ElementInternals* GetElementInternals() const;
+  ElementInternals& EnsureElementInternals(HTMLElement& target);
 
-  AccessibleNode* GetAccessibleNode() const override;
-  AccessibleNode* EnsureAccessibleNode(Element* owner_element) override;
-  void ClearAccessibleNode() override;
+  AccessibleNode* GetAccessibleNode() const;
+  AccessibleNode* EnsureAccessibleNode(Element* owner_element);
+  void ClearAccessibleNode();
 
-  DisplayLockContext* EnsureDisplayLockContext(Element* element) override;
-  DisplayLockContext* GetDisplayLockContext() const override;
+  DisplayLockContext* EnsureDisplayLockContext(Element* element);
+  DisplayLockContext* GetDisplayLockContext() const;
 
-  ContainerQueryData& EnsureContainerQueryData() override;
-  ContainerQueryData* GetContainerQueryData() const override;
-  void ClearContainerQueryData() override;
+  ContainerQueryData& EnsureContainerQueryData();
+  ContainerQueryData* GetContainerQueryData() const;
+  void ClearContainerQueryData();
 
   // Returns the crop-ID if one was set, or nullptr otherwise.
-  const RegionCaptureCropId* GetRegionCaptureCropId() const override;
+  const RegionCaptureCropId* GetRegionCaptureCropId() const;
   // Sets a crop-ID on the item. Must be called at most once. Cannot be used
   // to unset a previously set crop-ID.
-  void SetRegionCaptureCropId(
-      std::unique_ptr<RegionCaptureCropId> crop_id) override;
+  void SetRegionCaptureCropId(std::unique_ptr<RegionCaptureCropId> crop_id);
 
-  ResizeObserverDataMap* ResizeObserverData() const override;
-  ResizeObserverDataMap& EnsureResizeObserverData() override;
+  using ResizeObserverDataMap =
+      HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>;
+  ResizeObserverDataMap* ResizeObserverData() const;
+  ResizeObserverDataMap& EnsureResizeObserverData();
 
-  void SetCustomElementDefinition(CustomElementDefinition* definition) override;
-  CustomElementDefinition* GetCustomElementDefinition() const override;
+  void SetCustomElementDefinition(CustomElementDefinition* definition);
+  CustomElementDefinition* GetCustomElementDefinition() const;
 
-  void SetLastRememberedBlockSize(absl::optional<LayoutUnit> size) override;
-  void SetLastRememberedInlineSize(absl::optional<LayoutUnit> size) override;
-  absl::optional<LayoutUnit> LastRememberedBlockSize() const override;
-  absl::optional<LayoutUnit> LastRememberedInlineSize() const override;
+  void SetLastRememberedBlockSize(absl::optional<LayoutUnit> size);
+  void SetLastRememberedInlineSize(absl::optional<LayoutUnit> size);
+  absl::optional<LayoutUnit> LastRememberedBlockSize() const;
+  absl::optional<LayoutUnit> LastRememberedInlineSize() const;
 
-  PopoverData* GetPopoverData() const override;
-  PopoverData& EnsurePopoverData() override;
-  void RemovePopoverData() override;
+  PopoverData* GetPopoverData() const;
+  PopoverData& EnsurePopoverData();
+  void RemovePopoverData();
 
-  CSSToggleMap* GetToggleMap() const override;
-  CSSToggleMap& EnsureToggleMap(Element* owner_element) override;
+  CSSToggleMap* GetToggleMap() const;
+  CSSToggleMap& EnsureToggleMap(Element* owner_element);
 
-  bool HasElementFlag(ElementFlags mask) const override {
+  bool HasElementFlag(ElementFlags mask) const {
     return element_flags_ & static_cast<uint16_t>(mask);
   }
-  void SetElementFlag(ElementFlags mask, bool value) override {
+  void SetElementFlag(ElementFlags mask, bool value) {
     element_flags_ =
         (element_flags_ & ~static_cast<uint16_t>(mask)) |
         (-static_cast<uint16_t>(value) & static_cast<uint16_t>(mask));
   }
-  void ClearElementFlag(ElementFlags mask) override {
+  void ClearElementFlag(ElementFlags mask) {
     element_flags_ &= ~static_cast<uint16_t>(mask);
   }
 
-  bool HasRestyleFlags() const override {
-    return bit_field_.get<RestyleFlags>();
-  }
-  void ClearRestyleFlags() override { bit_field_.set<RestyleFlags>(0); }
+  bool HasRestyleFlags() const { return bit_field_.get<RestyleFlags>(); }
+  void ClearRestyleFlags() { bit_field_.set<RestyleFlags>(0); }
 
-  void SetTabIndexExplicitly() override {
+  void SetTabIndexExplicitly() {
     SetElementFlag(ElementFlags::kTabIndexWasSetExplicitly, true);
   }
-  void ClearTabIndexExplicitly() override {
+  void ClearTabIndexExplicitly() {
     ClearElementFlag(ElementFlags::kTabIndexWasSetExplicitly);
   }
 
-  AnchorScrollData* GetAnchorScrollData() const override;
-  void RemoveAnchorScrollData() override;
-  AnchorScrollData& EnsureAnchorScrollData(Element*) override;
+  AnchorScrollData* GetAnchorScrollData() const;
+  void RemoveAnchorScrollData();
+  AnchorScrollData& EnsureAnchorScrollData(Element*);
 
-  AnchorElementObserver& EnsureAnchorElementObserver(HTMLElement*) override;
-  AnchorElementObserver* GetAnchorElementObserver() const override;
+  AnchorElementObserver& EnsureAnchorElementObserver(HTMLElement*);
+  AnchorElementObserver* GetAnchorElementObserver() const;
 
-  void IncrementImplicitlyAnchoredElementCount() override;
-  void DecrementImplicitlyAnchoredElementCount() override;
-  bool HasImplicitlyAnchoredElement() const override;
+  void IncrementImplicitlyAnchoredElementCount();
+  void DecrementImplicitlyAnchoredElementCount();
+  bool HasImplicitlyAnchoredElement() const;
+
+  void SetDidAttachInternals() { did_attach_internals_ = true; }
+  bool DidAttachInternals() const { return did_attach_internals_; }
+  void SetStyleShouldForceLegacyLayout(bool force) {
+    style_should_force_legacy_layout_ = force;
+  }
+  bool StyleShouldForceLegacyLayout() const {
+    return style_should_force_legacy_layout_;
+  }
+  void SetShouldForceLegacyLayoutForChild(bool force) {
+    should_force_legacy_layout_for_child_ = force;
+  }
+  bool ShouldForceLegacyLayoutForChild() const {
+    return should_force_legacy_layout_for_child_;
+  }
+  bool HasUndoStack() const { return has_undo_stack_; }
+  void SetHasUndoStack(bool value) { has_undo_stack_ = value; }
+  bool ScrollbarPseudoElementStylesDependOnFontMetrics() const {
+    return scrollbar_pseudo_element_styles_depend_on_font_metrics_;
+  }
+  void SetScrollbarPseudoElementStylesDependOnFontMetrics(bool value) {
+    scrollbar_pseudo_element_styles_depend_on_font_metrics_ = value;
+  }
+
+  FocusgroupFlags GetFocusgroupFlags() const { return focusgroup_flags_; }
+  void SetFocusgroupFlags(FocusgroupFlags flags) { focusgroup_flags_ = flags; }
+  void ClearFocusgroupFlags() { focusgroup_flags_ = FocusgroupFlags::kNone; }
+
+  bool AffectedBySubjectHas() const {
+    return has_invalidation_flags_.affected_by_subject_has;
+  }
+  void SetAffectedBySubjectHas() {
+    has_invalidation_flags_.affected_by_subject_has = true;
+  }
+  bool AffectedByNonSubjectHas() const {
+    return has_invalidation_flags_.affected_by_non_subject_has;
+  }
+  void SetAffectedByNonSubjectHas() {
+    has_invalidation_flags_.affected_by_non_subject_has = true;
+  }
+  bool AncestorsOrAncestorSiblingsAffectedByHas() const {
+    return has_invalidation_flags_
+        .ancestors_or_ancestor_siblings_affected_by_has;
+  }
+  void SetAncestorsOrAncestorSiblingsAffectedByHas() {
+    has_invalidation_flags_.ancestors_or_ancestor_siblings_affected_by_has =
+        true;
+  }
+  unsigned GetSiblingsAffectedByHasFlags() const {
+    return has_invalidation_flags_.siblings_affected_by_has;
+  }
+  bool HasSiblingsAffectedByHasFlags(unsigned flags) const {
+    return has_invalidation_flags_.siblings_affected_by_has & flags;
+  }
+  void SetSiblingsAffectedByHasFlags(unsigned flags) {
+    has_invalidation_flags_.siblings_affected_by_has |= flags;
+  }
+  bool AffectedByPseudoInHas() const {
+    return has_invalidation_flags_.affected_by_pseudos_in_has;
+  }
+  void SetAffectedByPseudoInHas() {
+    has_invalidation_flags_.affected_by_pseudos_in_has = true;
+  }
+  bool AncestorsOrSiblingsAffectedByHoverInHas() const {
+    return has_invalidation_flags_
+        .ancestors_or_siblings_affected_by_hover_in_has;
+  }
+  void SetAncestorsOrSiblingsAffectedByHoverInHas() {
+    has_invalidation_flags_.ancestors_or_siblings_affected_by_hover_in_has =
+        true;
+  }
+  bool AncestorsOrSiblingsAffectedByActiveInHas() const {
+    return has_invalidation_flags_
+        .ancestors_or_siblings_affected_by_active_in_has;
+  }
+  void SetAncestorsOrSiblingsAffectedByActiveInHas() {
+    has_invalidation_flags_.ancestors_or_siblings_affected_by_active_in_has =
+        true;
+  }
+  bool AncestorsOrSiblingsAffectedByFocusInHas() const {
+    return has_invalidation_flags_
+        .ancestors_or_siblings_affected_by_focus_in_has;
+  }
+  void SetAncestorsOrSiblingsAffectedByFocusInHas() {
+    has_invalidation_flags_.ancestors_or_siblings_affected_by_focus_in_has =
+        true;
+  }
+  bool AncestorsOrSiblingsAffectedByFocusVisibleInHas() const {
+    return has_invalidation_flags_
+        .ancestors_or_siblings_affected_by_focus_visible_in_has;
+  }
+  void SetAncestorsOrSiblingsAffectedByFocusVisibleInHas() {
+    has_invalidation_flags_
+        .ancestors_or_siblings_affected_by_focus_visible_in_has = true;
+  }
+  bool AffectedByLogicalCombinationsInHas() const {
+    return has_invalidation_flags_.affected_by_logical_combinations_in_has;
+  }
+  void SetAffectedByLogicalCombinationsInHas() {
+    has_invalidation_flags_.affected_by_logical_combinations_in_has = true;
+  }
+  bool AffectedByMultipleHas() const {
+    return has_invalidation_flags_.affected_by_multiple_has;
+  }
+  void SetAffectedByMultipleHas() {
+    has_invalidation_flags_.affected_by_multiple_has = true;
+  }
 
   void Trace(blink::Visitor*) const override;
+
+ private:
+  unsigned did_attach_internals_ : 1;
+  unsigned should_force_legacy_layout_for_child_ : 1;
+  unsigned style_should_force_legacy_layout_ : 1;
+  unsigned has_undo_stack_ : 1;
+  unsigned scrollbar_pseudo_element_styles_depend_on_font_metrics_ : 1;
+  HasInvalidationFlags has_invalidation_flags_;
+  FocusgroupFlags focusgroup_flags_ = FocusgroupFlags::kNone;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc
index 6074b36c..edd1b9aef 100644
--- a/third_party/blink/renderer/core/dom/node.cc
+++ b/third_party/blink/renderer/core/dom/node.cc
@@ -49,7 +49,6 @@
 #include "third_party/blink/renderer/core/dom/document_type.h"
 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
 #include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/element_rare_data.h"
 #include "third_party/blink/renderer/core/dom/element_rare_data_vector.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h"
@@ -339,11 +338,7 @@
 
 NodeRareData& Node::CreateRareData() {
   if (IsElementNode()) {
-    if (RuntimeEnabledFeatures::ElementSuperRareDataEnabled()) {
-      data_ = MakeGarbageCollected<ElementRareDataVector>(data_);
-    } else {
-      data_ = MakeGarbageCollected<ElementRareData>(data_);
-    }
+    data_ = MakeGarbageCollected<ElementRareDataVector>(data_);
   } else {
     data_ = MakeGarbageCollected<NodeRareData>(std::move(*data_));
   }
diff --git a/third_party/blink/renderer/core/dom/node_rare_data.cc b/third_party/blink/renderer/core/dom/node_rare_data.cc
index aa089c6..bba4a72 100644
--- a/third_party/blink/renderer/core/dom/node_rare_data.cc
+++ b/third_party/blink/renderer/core/dom/node_rare_data.cc
@@ -33,7 +33,6 @@
 #include "third_party/blink/renderer/core/animation/scroll_timeline.h"
 #include "third_party/blink/renderer/core/dom/container_node.h"
 #include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/element_rare_data.h"
 #include "third_party/blink/renderer/core/dom/flat_tree_node_data.h"
 #include "third_party/blink/renderer/core/dom/mutation_observer_registration.h"
 #include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
diff --git a/third_party/blink/renderer/core/dom/pseudo_element.cc b/third_party/blink/renderer/core/dom/pseudo_element.cc
index e428cc8..03bf240 100644
--- a/third_party/blink/renderer/core/dom/pseudo_element.cc
+++ b/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -29,7 +29,7 @@
 #include <utility>
 
 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
-#include "third_party/blink/renderer/core/dom/element_rare_data.h"
+#include "third_party/blink/renderer/core/dom/element_rare_data_vector.h"
 #include "third_party/blink/renderer/core/dom/first_letter_pseudo_element.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
diff --git a/third_party/blink/renderer/core/dom/text.cc b/third_party/blink/renderer/core/dom/text.cc
index 0e31009..3a32385 100644
--- a/third_party/blink/renderer/core/dom/text.cc
+++ b/third_party/blink/renderer/core/dom/text.cc
@@ -262,7 +262,7 @@
   }
 
   if (parent.IsTable() || parent.IsTableRow() || parent.IsTableSection() ||
-      parent.IsLayoutTableCol() || parent.IsFrameSetIncludingNG() ||
+      parent.IsLayoutTableCol() || parent.IsFrameSet() ||
       parent.IsFlexibleBoxIncludingNG() || parent.IsLayoutNGGrid() ||
       parent.IsSVGRoot() || parent.IsSVGContainer() || parent.IsSVGImage() ||
       parent.IsSVGShape()) {
diff --git a/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc b/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
index b64a5ae..7f89aa2 100644
--- a/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
@@ -47,7 +47,8 @@
 #include "third_party/blink/renderer/core/html/html_style_element.h"
 #include "third_party/blink/renderer/core/html/html_table_row_element.h"
 #include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/layout_text.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.cc b/third_party/blink/renderer/core/editing/editing_utilities.cc
index bb664a67..0ad492d 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.cc
+++ b/third_party/blink/renderer/core/editing/editing_utilities.cc
@@ -73,7 +73,6 @@
 #include "third_party/blink/renderer/core/input_type_names.h"
 #include "third_party/blink/renderer/core/layout/layout_image.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/svg/svg_image_element.h"
 #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
diff --git a/third_party/blink/renderer/core/editing/element_inner_text.cc b/third_party/blink/renderer/core/editing/element_inner_text.cc
index 83d923a..1cd20ac 100644
--- a/third_party/blink/renderer/core/editing/element_inner_text.cc
+++ b/third_party/blink/renderer/core/editing/element_inner_text.cc
@@ -17,14 +17,14 @@
 #include "third_party/blink/renderer/core/html/forms/html_select_element.h"
 #include "third_party/blink/renderer/core/html/html_br_element.h"
 #include "third_party/blink/renderer/core/html/html_paragraph_element.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
 #include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
 #include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/text/character_names.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -152,7 +152,7 @@
   if (!layout_object)
     return false;
   if (layout_object->IsTableSection()) {
-    // Note: |LayoutTableSection::IsInline()| returns false, but it is not
+    // Note: |LayoutNGTableSection::IsInline()| returns false, but it is not
     // block-level.
     return false;
   }
@@ -190,8 +190,8 @@
       table_row.SectionInterface();
   if (!table_section)
     return false;
-  // See |LayoutTable::SectionAbove()| and |SectionBelow()| for traversing
-  // |LayoutTableSection|.
+  // See |LayoutNGTable::NextSectionInterface()| and
+  // |PreviousSectionInterface()| for traversing |LayoutNGTableSection|.
   for (const LayoutObject* runner =
            table_section->ToLayoutObject()->NextSibling();
        runner; runner = runner->NextSibling()) {
diff --git a/third_party/blink/renderer/core/editing/iterators/text_iterator.cc b/third_party/blink/renderer/core/editing/iterators/text_iterator.cc
index 327c807..44370ce3 100644
--- a/third_party/blink/renderer/core/editing/iterators/text_iterator.cc
+++ b/third_party/blink/renderer/core/editing/iterators/text_iterator.cc
@@ -46,8 +46,9 @@
 #include "third_party/blink/renderer/core/html/html_image_element.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/input_type_names.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
 #include "third_party/blink/renderer/platform/fonts/font.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
diff --git a/third_party/blink/renderer/core/frame/attribution_src_loader.cc b/third_party/blink/renderer/core/frame/attribution_src_loader.cc
index f1b26f5..305803d 100644
--- a/third_party/blink/renderer/core/frame/attribution_src_loader.cc
+++ b/third_party/blink/renderer/core/frame/attribution_src_loader.cc
@@ -182,30 +182,27 @@
     : public GarbageCollected<AttributionSrcLoader::ResourceClient>,
       public RawResourceClient {
  public:
-  // `associated_with_navigation` indicates whether the attribution data
+  // `attribution_src_token` has a value if the attribution data
   // produced by this client will need to be associated with a navigation.
   ResourceClient(AttributionSrcLoader* loader,
                  RegistrationType type,
-                 bool associated_with_navigation)
+                 absl::optional<AttributionSrcToken> attribution_src_token)
       : loader_(loader), type_(type) {
     DCHECK(loader_);
     DCHECK(loader_->local_frame_);
     DCHECK(loader_->local_frame_->IsAttached());
 
-    mojo::AssociatedRemote<mojom::blink::ConversionHost> conversion_host;
+    mojo::AssociatedRemote<mojom::blink::AttributionHost> attribution_host;
     loader_->local_frame_->GetRemoteNavigationAssociatedInterfaces()
-        ->GetInterface(&conversion_host);
+        ->GetInterface(&attribution_host);
 
-    if (associated_with_navigation) {
-      // Create a new token which will be used to identify `data_host_` in the
-      // browser process.
-      attribution_src_token_ = AttributionSrcToken();
-      conversion_host->RegisterNavigationDataHost(
-          data_host_.BindNewPipeAndPassReceiver(), *attribution_src_token_);
+    if (attribution_src_token.has_value()) {
+      attribution_host->RegisterNavigationDataHost(
+          data_host_.BindNewPipeAndPassReceiver(), *attribution_src_token);
     } else {
       // Send the data host normally.
-      conversion_host->RegisterDataHost(data_host_.BindNewPipeAndPassReceiver(),
-                                        type);
+      attribution_host->RegisterDataHost(
+          data_host_.BindNewPipeAndPassReceiver(), type);
     }
   }
 
@@ -222,10 +219,6 @@
     RawResourceClient::Trace(visitor);
   }
 
-  const absl::optional<AttributionSrcToken>& attribution_src_token() const {
-    return attribution_src_token_;
-  }
-
   void HandleResponseHeaders(
       attribution_reporting::SuitableOrigin reporting_origin,
       const AttributionHeaders&,
@@ -265,11 +258,6 @@
   // request can only register one type of event across redirects.
   RegistrationType type_;
 
-  // Token used to identify an attributionsrc request in the browser process.
-  // Only generated for attributionsrc requests that are associated with a
-  // navigation.
-  absl::optional<AttributionSrcToken> attribution_src_token_;
-
   // Remote used for registering responses with the browser-process.
   GC_PLUGIN_IGNORE("https://crbug.com/1381979")
   mojo::Remote<mojom::blink::AttributionDataHost> data_host_;
@@ -290,7 +278,7 @@
 
 void AttributionSrcLoader::Register(const KURL& src_url, HTMLElement* element) {
   CreateAndSendRequest(src_url, element, RegistrationType::kSourceOrTrigger,
-                       /*associated_with_navigation=*/false);
+                       /*attribution_src_token=*/absl::nullopt);
 }
 
 absl::optional<Impression> AttributionSrcLoader::RegisterNavigation(
@@ -299,23 +287,23 @@
     HTMLElement* element) {
   // TODO(apaseltiner): Add tests to ensure that this method can't be used to
   // register triggers.
-  ResourceClient* client =
-      CreateAndSendRequest(src_url, element, RegistrationType::kSource,
-                           /*associated_with_navigation=*/true);
+
+  const AttributionSrcToken attribution_src_token;
+  ResourceClient* client = CreateAndSendRequest(
+      src_url, element, RegistrationType::kSource, attribution_src_token);
   if (!client)
     return absl::nullopt;
 
-  DCHECK(client->attribution_src_token());
-  return blink::Impression{
-      .attribution_src_token = *client->attribution_src_token(),
-      .nav_type = nav_type};
+  return blink::Impression{.attribution_src_token = attribution_src_token,
+                           .nav_type = nav_type};
 }
 
 AttributionSrcLoader::ResourceClient*
-AttributionSrcLoader::CreateAndSendRequest(const KURL& src_url,
-                                           HTMLElement* element,
-                                           RegistrationType src_type,
-                                           bool associated_with_navigation) {
+AttributionSrcLoader::CreateAndSendRequest(
+    const KURL& src_url,
+    HTMLElement* element,
+    RegistrationType src_type,
+    absl::optional<AttributionSrcToken> attribution_src_token) {
   // Detached frames cannot/should not register new attributionsrcs.
   if (!local_frame_->IsAttached())
     return nullptr;
@@ -339,17 +327,17 @@
     document->AddPostPrerenderingActivationStep(
         WTF::BindOnce(base::IgnoreResult(&AttributionSrcLoader::DoRegistration),
                       WrapPersistentIfNeeded(this), src_url, src_type,
-                      associated_with_navigation));
+                      attribution_src_token));
     return nullptr;
   }
 
-  return DoRegistration(src_url, src_type, associated_with_navigation);
+  return DoRegistration(src_url, src_type, attribution_src_token);
 }
 
 AttributionSrcLoader::ResourceClient* AttributionSrcLoader::DoRegistration(
     const KURL& src_url,
-    RegistrationType src_type,
-    bool associated_with_navigation) {
+    const RegistrationType src_type,
+    const absl::optional<AttributionSrcToken> attribution_src_token) {
   if (!local_frame_->IsAttached())
     return nullptr;
 
@@ -361,17 +349,16 @@
   request.SetKeepalive(true);
   request.SetRequestContext(mojom::blink::RequestContextType::ATTRIBUTION_SRC);
 
-  const char* eligible = [src_type,
-                          associated_with_navigation]() -> const char* {
+  const char* eligible = [&]() -> const char* {
     switch (src_type) {
       case RegistrationType::kSource:
-        return associated_with_navigation ? "navigation-source"
-                                          : "event-source";
+        return attribution_src_token.has_value() ? "navigation-source"
+                                                 : "event-source";
       case RegistrationType::kTrigger:
         NOTREACHED();
         return nullptr;
       case RegistrationType::kSourceOrTrigger:
-        DCHECK(!associated_with_navigation);
+        DCHECK(!attribution_src_token.has_value());
         return kAttributionEligibleEventSourceAndTrigger;
     }
   }();
@@ -385,8 +372,8 @@
   params.MutableOptions().initiator_info.name =
       fetch_initiator_type_names::kAttributionsrc;
 
-  auto* client = MakeGarbageCollected<ResourceClient>(
-      this, src_type, associated_with_navigation);
+  auto* client = MakeGarbageCollected<ResourceClient>(this, src_type,
+                                                      attribution_src_token);
   ++num_resource_clients_;
 
   // TODO(https://crbug.com/1374121): If this registration is
@@ -568,7 +555,7 @@
   // TODO(johnidel): Consider refactoring this such that we can share clients
   // for redirect chain, or not create the client at all.
   auto* client = MakeGarbageCollected<ResourceClient>(
-      this, src_type, /*associated_with_navigation=*/false);
+      this, src_type, /*attribution_src_token=*/absl::nullopt);
   client->HandleResponseHeaders(std::move(reporting_origin), headers,
                                 trigger_attestation);
   client->Finish();
diff --git a/third_party/blink/renderer/core/frame/attribution_src_loader.h b/third_party/blink/renderer/core/frame/attribution_src_loader.h
index e493e39a..d1d9272 100644
--- a/third_party/blink/renderer/core/frame/attribution_src_loader.h
+++ b/third_party/blink/renderer/core/frame/attribution_src_loader.h
@@ -10,6 +10,7 @@
 
 #include "components/attribution_reporting/registration_type.mojom-blink-forward.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/public/mojom/conversions/attribution_reporting.mojom-blink-forward.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/forward.h"
@@ -95,7 +96,7 @@
   ResourceClient* DoRegistration(
       const KURL& src_url,
       attribution_reporting::mojom::blink::RegistrationType,
-      bool associated_with_navigation);
+      absl::optional<AttributionSrcToken>);
 
   // Returns the reporting origin corresponding to `url` if its protocol is in
   // the HTTP family, its origin is potentially trustworthy, and attribution is
@@ -111,7 +112,7 @@
       const KURL& src_url,
       HTMLElement* element,
       attribution_reporting::mojom::blink::RegistrationType,
-      bool associated_with_navigation);
+      absl::optional<AttributionSrcToken>);
 
   // Returns whether OS-level attribution is supported.
   bool HasOsSupport() const;
diff --git a/third_party/blink/renderer/core/frame/attribution_src_loader_test.cc b/third_party/blink/renderer/core/frame/attribution_src_loader_test.cc
index 69da8e90..d792ed5 100644
--- a/third_party/blink/renderer/core/frame/attribution_src_loader_test.cc
+++ b/third_party/blink/renderer/core/frame/attribution_src_loader_test.cc
@@ -156,11 +156,11 @@
   mojo::Receiver<mojom::blink::AttributionDataHost> receiver_{this};
 };
 
-class MockAttributionHost : public mojom::blink::ConversionHost {
+class MockAttributionHost : public mojom::blink::AttributionHost {
  public:
   explicit MockAttributionHost(blink::AssociatedInterfaceProvider* provider) {
     provider->OverrideBinderForTesting(
-        mojom::blink::ConversionHost::Name_,
+        mojom::blink::AttributionHost::Name_,
         WTF::BindRepeating(&MockAttributionHost::BindReceiver,
                            WTF::Unretained(this)));
   }
@@ -181,7 +181,7 @@
  private:
   void BindReceiver(mojo::ScopedInterfaceEndpointHandle handle) {
     receiver_.Bind(
-        mojo::PendingAssociatedReceiver<mojom::blink::ConversionHost>(
+        mojo::PendingAssociatedReceiver<mojom::blink::AttributionHost>(
             std::move(handle)));
     if (quit_)
       std::move(quit_).Run();
@@ -197,7 +197,7 @@
       mojo::PendingReceiver<mojom::blink::AttributionDataHost> data_host,
       const blink::AttributionSrcToken& attribution_src_token) override {}
 
-  mojo::AssociatedReceiver<mojom::blink::ConversionHost> receiver_{this};
+  mojo::AssociatedReceiver<mojom::blink::AttributionHost> receiver_{this};
   base::OnceClosure quit_;
 
   std::unique_ptr<MockDataHost> mock_data_host_;
@@ -227,7 +227,7 @@
     GetFrame()
         .GetRemoteNavigationAssociatedInterfaces()
         ->OverrideBinderForTesting(
-            mojom::blink::ConversionHost::Name_,
+            mojom::blink::AttributionHost::Name_,
             WTF::BindRepeating([](mojo::ScopedInterfaceEndpointHandle) {}));
     url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
     PageTestBase::TearDown();
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index 2cb2130..4bfae3a 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -27,6 +27,7 @@
 
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_stringtreatnullasemptystring_trustedscript.h"
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
 #include "third_party/blink/renderer/core/css/css_color.h"
@@ -40,7 +41,7 @@
 #include "third_party/blink/renderer/core/css_value_keywords.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/document_fragment.h"
-#include "third_party/blink/renderer/core/dom/element_rare_data.h"
+#include "third_party/blink/renderer/core/dom/element_rare_data_vector.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/events/event_listener.h"
 #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
diff --git a/third_party/blink/renderer/core/html/html_frame_set_element.cc b/third_party/blink/renderer/core/html/html_frame_set_element.cc
index a14c4d45..4448c61 100644
--- a/third_party/blink/renderer/core/html/html_frame_set_element.cc
+++ b/third_party/blink/renderer/core/html/html_frame_set_element.cc
@@ -37,8 +37,6 @@
 #include "third_party/blink/renderer/core/html/html_frame_element.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/layout/layout_frame_set.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
 #include "third_party/blink/renderer/core/layout/ng/frame_set_layout_data.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
@@ -51,8 +49,6 @@
 constexpr int kDefaultBorderThicknessPx = 6;
 
 const Vector<LayoutUnit>& ColumnSizes(const LayoutBox& box) {
-  if (const auto* legacy = DynamicTo<LayoutFrameSet>(box))
-    return legacy->Columns().sizes_;
   DCHECK(IsA<LayoutNGFrameSet>(box));
   // |object| should have only 1 physical fragment because <frameset> is
   // monolithic.
@@ -62,8 +58,6 @@
 }
 
 const Vector<LayoutUnit>& RowSizes(const LayoutBox& box) {
-  if (const auto* legacy = DynamicTo<LayoutFrameSet>(box))
-    return legacy->Rows().sizes_;
   DCHECK(IsA<LayoutNGFrameSet>(box));
   // |object| should have only 1 physical fragment because <frameset> is
   // monolithic.
@@ -417,7 +411,7 @@
     const ComputedStyle& style,
     LegacyLayout legacy) {
   if (style.ContentBehavesAsNormal())
-    return LayoutObjectFactory::CreateFrameSet(*this, style, legacy);
+    return MakeGarbageCollected<LayoutNGFrameSet>(this);
   return LayoutObject::CreateObject(this, style, legacy);
 }
 
@@ -430,7 +424,7 @@
 void HTMLFrameSetElement::DefaultEventHandler(Event& evt) {
   auto* mouse_event = DynamicTo<MouseEvent>(evt);
   if (mouse_event && !NoResize() && GetLayoutObject() &&
-      GetLayoutObject()->IsFrameSetIncludingNG()) {
+      GetLayoutObject()->IsFrameSet()) {
     if (UserResize(*mouse_event)) {
       evt.SetDefaultHandled();
       return;
diff --git a/third_party/blink/renderer/core/html/html_image_fallback_helper.cc b/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
index 5b31dee0..d0b6ab7 100644
--- a/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
+++ b/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
@@ -5,7 +5,7 @@
 #include "third_party/blink/renderer/core/html/html_image_fallback_helper.h"
 
 #include "third_party/blink/renderer/core/css/style_engine.h"
-#include "third_party/blink/renderer/core/dom/element_rare_data.h"
+#include "third_party/blink/renderer/core/dom/element_rare_data_vector.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/dom/text.h"
 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
diff --git a/third_party/blink/renderer/core/html/html_rt_element.cc b/third_party/blink/renderer/core/html/html_rt_element.cc
index be1401e..7c4eba0 100644
--- a/third_party/blink/renderer/core/html/html_rt_element.cc
+++ b/third_party/blink/renderer/core/html/html_rt_element.cc
@@ -6,7 +6,7 @@
 
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 
 namespace blink {
@@ -17,7 +17,7 @@
 LayoutObject* HTMLRTElement::CreateLayoutObject(const ComputedStyle& style,
                                                 LegacyLayout legacy) {
   if (style.Display() == EDisplay::kBlock)
-    return LayoutObjectFactory::CreateRubyText(this, style, legacy);
+    return MakeGarbageCollected<LayoutNGRubyText>(this);
   return LayoutObject::CreateObject(this, style, legacy);
 }
 
diff --git a/third_party/blink/renderer/core/html/html_ruby_element.cc b/third_party/blink/renderer/core/html/html_ruby_element.cc
index eacb2ac..d6f0779 100644
--- a/third_party/blink/renderer/core/html/html_ruby_element.cc
+++ b/third_party/blink/renderer/core/html/html_ruby_element.cc
@@ -6,8 +6,8 @@
 
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
 #include "third_party/blink/renderer/core/layout/layout_ruby.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h"
 
 namespace blink {
 
@@ -20,7 +20,7 @@
     return MakeGarbageCollected<LayoutRubyAsInline>(this);
   if (style.Display() == EDisplay::kBlock) {
     UseCounter::Count(GetDocument(), WebFeature::kRubyElementWithDisplayBlock);
-    return LayoutObjectFactory::CreateRubyAsBlock(this, style, legacy);
+    return MakeGarbageCollected<LayoutNGRubyAsBlock>(this);
   }
   return LayoutObject::CreateObject(this, style, legacy);
 }
diff --git a/third_party/blink/renderer/core/html/html_table_cell_element.cc b/third_party/blink/renderer/core/html/html_table_cell_element.cc
index 4071fe9..8241427 100644
--- a/third_party/blink/renderer/core/html/html_table_cell_element.cc
+++ b/third_party/blink/renderer/core/html/html_table_cell_element.cc
@@ -33,7 +33,7 @@
 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
 #include "third_party/blink/renderer/core/html/table_constants.h"
 #include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/html/html_table_col_element.cc b/third_party/blink/renderer/core/html/html_table_col_element.cc
index bc80e6b..5993400 100644
--- a/third_party/blink/renderer/core/html/html_table_col_element.cc
+++ b/third_party/blink/renderer/core/html/html_table_col_element.cc
@@ -31,7 +31,7 @@
 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
 #include "third_party/blink/renderer/core/html/table_constants.h"
 #include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
index a4f7377..00258c1 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
@@ -27,8 +27,8 @@
 
 #include "third_party/blink/renderer/core/css/style_change_reason.h"
 #include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
 #include "third_party/blink/renderer/core/layout/layout_ruby.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
 namespace blink {
@@ -150,7 +150,7 @@
     case kVTTNodeTypeRuby:
       return MakeGarbageCollected<LayoutRubyAsInline>(this);
     case kVTTNodeTypeRubyText:
-      return LayoutObjectFactory::CreateRubyText(this, style, legacy);
+      return MakeGarbageCollected<LayoutNGRubyText>(this);
   }
   return LayoutObject::CreateObject(this, style, legacy);
 }
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
index cfc46069..5b9510e 100644
--- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
+++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
@@ -4,8 +4,9 @@
 
 #include "third_party/blink/renderer/core/intersection_observer/intersection_observation.h"
 
-#include "third_party/blink/renderer/core/dom/element_rare_data.h"
+#include "third_party/blink/renderer/core/dom/element_rare_data_vector.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
 #include "third_party/blink/renderer/core/intersection_observer/intersection_geometry.h"
 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h"
diff --git a/third_party/blink/renderer/core/layout/api/line_layout_ruby_base.h b/third_party/blink/renderer/core/layout/api/line_layout_ruby_base.h
deleted file mode 100644
index 363d210..0000000
--- a/third_party/blink/renderer/core/layout/api/line_layout_ruby_base.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2016 The Chromium Authors
-// 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_CORE_LAYOUT_API_LINE_LAYOUT_RUBY_BASE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_RUBY_BASE_H_
-
-#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
-
-namespace blink {
-
-class LineLayoutRubyBase : public LineLayoutBlockFlow {
- public:
-  explicit LineLayoutRubyBase(LayoutRubyBase* layout_ruby_base)
-      : LineLayoutBlockFlow(layout_ruby_base) {}
-
-  explicit LineLayoutRubyBase(const LineLayoutItem& item)
-      : LineLayoutBlockFlow(item) {
-    SECURITY_DCHECK(!item || item.IsRubyBase());
-  }
-
-  explicit LineLayoutRubyBase(std::nullptr_t) : LineLayoutBlockFlow(nullptr) {}
-
-  LineLayoutRubyBase() = default;
-
- private:
-  LayoutRubyBase* ToRubyBase() { return To<LayoutRubyBase>(GetLayoutObject()); }
-
-  const LayoutRubyBase* ToRubyBase() const {
-    return To<LayoutRubyBase>(GetLayoutObject());
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_RUBY_BASE_H_
diff --git a/third_party/blink/renderer/core/layout/api/line_layout_ruby_run.h b/third_party/blink/renderer/core/layout/api/line_layout_ruby_run.h
deleted file mode 100644
index 1403c71..0000000
--- a/third_party/blink/renderer/core/layout/api/line_layout_ruby_run.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// 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_CORE_LAYOUT_API_LINE_LAYOUT_RUBY_RUN_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_RUBY_RUN_H_
-
-#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
-#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_base.h"
-#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_text.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
-
-namespace blink {
-
-class LineLayoutRubyRun : public LineLayoutBlockFlow {
- public:
-  explicit LineLayoutRubyRun(LayoutRubyRun* layout_ruby_run)
-      : LineLayoutBlockFlow(layout_ruby_run) {}
-
-  explicit LineLayoutRubyRun(const LineLayoutItem& item)
-      : LineLayoutBlockFlow(item) {
-    SECURITY_DCHECK(!item || item.IsRubyRun());
-  }
-
-  explicit LineLayoutRubyRun(std::nullptr_t) : LineLayoutBlockFlow(nullptr) {}
-
-  LineLayoutRubyRun() = default;
-
-  void GetOverhang(bool first_line,
-                   LineLayoutItem start_layout_item,
-                   LineLayoutItem end_layout_item,
-                   int& start_overhang,
-                   int& end_overhang) const {
-    ToRubyRun()->GetOverhang(first_line, start_layout_item.GetLayoutObject(),
-                             end_layout_item.GetLayoutObject(), start_overhang,
-                             end_overhang);
-  }
-
-  LineLayoutRubyText RubyText() const {
-    return LineLayoutRubyText(ToRubyRun()->RubyText());
-  }
-
-  LineLayoutRubyBase RubyBase() const {
-    return LineLayoutRubyBase(ToRubyRun()->RubyBase());
-  }
-
-  bool CanBreakBefore(const LazyLineBreakIterator& iterator) const {
-    return ToRubyRun()->CanBreakBefore(iterator);
-  }
-
- private:
-  LayoutRubyRun* ToRubyRun() { return To<LayoutRubyRun>(GetLayoutObject()); }
-
-  const LayoutRubyRun* ToRubyRun() const {
-    return To<LayoutRubyRun>(GetLayoutObject());
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_RUBY_RUN_H_
diff --git a/third_party/blink/renderer/core/layout/api/line_layout_ruby_text.h b/third_party/blink/renderer/core/layout/api/line_layout_ruby_text.h
deleted file mode 100644
index 3290bad3..0000000
--- a/third_party/blink/renderer/core/layout/api/line_layout_ruby_text.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2016 The Chromium Authors
-// 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_CORE_LAYOUT_API_LINE_LAYOUT_RUBY_TEXT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_RUBY_TEXT_H_
-
-#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
-
-namespace blink {
-
-class LineLayoutRubyText : public LineLayoutBlockFlow {
- public:
-  explicit LineLayoutRubyText(LayoutRubyText* layout_ruby_text)
-      : LineLayoutBlockFlow(layout_ruby_text) {}
-
-  explicit LineLayoutRubyText(const LineLayoutItem& item)
-      : LineLayoutBlockFlow(item) {
-    SECURITY_DCHECK(!item || item.IsRubyText());
-  }
-
-  explicit LineLayoutRubyText(std::nullptr_t) : LineLayoutBlockFlow(nullptr) {}
-
-  LineLayoutRubyText() = default;
-
- private:
-  LayoutRubyText* ToRubyText() { return To<LayoutRubyText>(GetLayoutObject()); }
-
-  const LayoutRubyText* ToRubyText() const {
-    return To<LayoutRubyText>(GetLayoutObject());
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_RUBY_TEXT_H_
diff --git a/third_party/blink/renderer/core/layout/build.gni b/third_party/blink/renderer/core/layout/build.gni
index e8f502e1..c1ad286 100644
--- a/third_party/blink/renderer/core/layout/build.gni
+++ b/third_party/blink/renderer/core/layout/build.gni
@@ -38,9 +38,6 @@
   "api/line_layout_item.h",
   "api/line_layout_item.cc",
   "api/line_layout_list_marker.h",
-  "api/line_layout_ruby_base.h",
-  "api/line_layout_ruby_run.h",
-  "api/line_layout_ruby_text.h",
   "api/line_layout_svg_inline.h",
   "api/line_layout_svg_text_path.h",
   "api/line_layout_text.cc",
@@ -129,8 +126,6 @@
   "layout_flow_thread.h",
   "layout_frame.cc",
   "layout_frame.h",
-  "layout_frame_set.cc",
-  "layout_frame_set.h",
   "layout_html_canvas.cc",
   "layout_html_canvas.h",
   "layout_iframe.cc",
@@ -176,32 +171,12 @@
   "layout_replaced.h",
   "layout_ruby.cc",
   "layout_ruby.h",
-  "layout_ruby_base.cc",
-  "layout_ruby_base.h",
-  "layout_ruby_run.cc",
-  "layout_ruby_run.h",
-  "layout_ruby_text.cc",
-  "layout_ruby_text.h",
   "layout_shift_region.cc",
   "layout_shift_region.h",
   "layout_shift_tracker.cc",
   "layout_shift_tracker.h",
   "layout_state.cc",
   "layout_state.h",
-  "layout_table.cc",
-  "layout_table.h",
-  "layout_table_box_component.cc",
-  "layout_table_box_component.h",
-  "layout_table_caption.cc",
-  "layout_table_caption.h",
-  "layout_table_cell.cc",
-  "layout_table_cell.h",
-  "layout_table_col.cc",
-  "layout_table_col.h",
-  "layout_table_row.cc",
-  "layout_table_row.h",
-  "layout_table_section.cc",
-  "layout_table_section.h",
   "layout_text.cc",
   "layout_text.h",
   "layout_text_combine.cc",
@@ -731,13 +706,6 @@
   "svg/transform_helper.h",
   "svg/transformed_hit_test_location.cc",
   "svg/transformed_hit_test_location.h",
-  "table_grid_cell.cc",
-  "table_grid_cell.h",
-  "table_layout_algorithm.h",
-  "table_layout_algorithm_auto.cc",
-  "table_layout_algorithm_auto.h",
-  "table_layout_algorithm_fixed.cc",
-  "table_layout_algorithm_fixed.h",
   "text_decoration_offset.cc",
   "text_decoration_offset.h",
   "text_decoration_offset_base.cc",
@@ -812,7 +780,6 @@
   "layout_box_test.cc",
   "layout_embedded_content_test.cc",
   "layout_flexible_box_test.cc",
-  "layout_frame_set_test.cc",
   "layout_image_test.cc",
   "layout_image_resource_test.cc",
   "layout_inline_test.cc",
@@ -827,7 +794,6 @@
   "layout_shift_region_test.cc",
   "layout_shift_tracker_test.cc",
   "layout_table_col_test.cc",
-  "layout_table_row_test.cc",
   "layout_table_section_test.cc",
   "layout_table_test.cc",
   "layout_text_control_test.cc",
@@ -866,6 +832,7 @@
   "ng/inline/ng_paragraph_line_breaker_test.cc",
   "ng/inline/ng_physical_line_box_fragment_test.cc",
   "ng/layout_ng_fieldset_test.cc",
+  "ng/layout_ng_frame_set_test.cc",
   "ng/layout_ng_text_control_single_line_test.cc",
   "ng/list/layout_ng_list_item_test.cc",
   "ng/ng_absolute_utils_test.cc",
diff --git a/third_party/blink/renderer/core/layout/column_balancer.cc b/third_party/blink/renderer/core/layout/column_balancer.cc
index 7211f621..9d0b3955 100644
--- a/third_party/blink/renderer/core/layout/column_balancer.cc
+++ b/third_party/blink/renderer/core/layout/column_balancer.cc
@@ -106,16 +106,11 @@
     if (child_box.IsOutOfFlowPositioned() || child_box.IsColumnSpanAll())
       continue;
 
-    // Tables are wicked. Both table rows and table cells are relative to their
-    // table section.
-    LayoutUnit offset_for_this_child =
-        child_box.IsLegacyTableRow() ? LayoutUnit() : logical_top;
-
     // Include this child's offset in the flow thread offset. Note that rather
     // than subtracting the offset again when done, we set it back to the old
     // value. This matters in saturated arithmetic situations.
     auto old_flow_thread_offset = flow_thread_offset_;
-    flow_thread_offset_ += offset_for_this_child;
+    flow_thread_offset_ += logical_top;
 
     ExamineBoxAfterEntering(child_box, logical_height,
                             previous_break_after_value);
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index 4971ee5..7a24e363 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -55,12 +55,12 @@
 #include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
 #include "third_party/blink/renderer/core/layout/layout_object_factory.h"
 #include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/layout/layout_theme.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
 #include "third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h"
 #include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
@@ -1553,16 +1553,6 @@
   if (UNLIKELY(IsListBox(this) && StyleRef().LogicalWidth().IsPercentOrCalc()))
     child_sizes.min_size = LayoutUnit();
 
-  if (IsTableCellLegacy()) {
-    Length table_cell_width =
-        To<LayoutTableCell>(this)->StyleOrColLogicalWidth();
-    if (table_cell_width.IsFixed() && table_cell_width.Value() > 0) {
-      child_sizes.max_size = std::max(
-          child_sizes.min_size, AdjustContentBoxLogicalWidthForBoxSizing(
-                                    LayoutUnit(table_cell_width.Value())));
-    }
-  }
-
   sizes += child_sizes;
   return sizes;
 }
@@ -2248,8 +2238,8 @@
   } else if (new_display == EDisplay::kGrid) {
     layout_block = MakeGarbageCollected<LayoutNGGrid>(/* element */ nullptr);
   } else if (new_display == EDisplay::kBlockMath) {
-    layout_block = LayoutObjectFactory::CreateMath(parent->GetDocument(),
-                                                   *new_style, legacy);
+    layout_block =
+        MakeGarbageCollected<LayoutNGMathMLBlock>(/* element */ nullptr);
   } else {
     DCHECK(new_display == EDisplay::kBlock ||
            new_display == EDisplay::kFlowRoot);
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.h b/third_party/blink/renderer/core/layout/layout_block_flow.h
index 3aee5d9..eea89ec3 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.h
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -56,7 +56,6 @@
 class LineWidth;
 class LayoutMultiColumnFlowThread;
 class LayoutMultiColumnSpannerPlaceholder;
-class LayoutRubyRun;
 class MarginInfo;
 class NGOffsetMapping;
 class NGPhysicalFragment;
@@ -1024,9 +1023,9 @@
   friend class MarginInfo;
   friend class LineWidth;  // needs to know FloatingObject
 
-  // LayoutRubyBase objects need to be able to split and merge, moving their
-  // children around (calling makeChildrenNonInline).
-  friend class LayoutRubyBase;
+  // LayoutNGRubyBase objects need to be able to split and merge, moving their
+  // children around (calling MakeChildrenNonInline).
+  friend class LayoutNGRubyBase;
 
   // FIXME-BLOCKFLOW: These methods have implementations in
   // LayoutBlockFlowLine. They should be moved to the proper header once the
@@ -1036,10 +1035,6 @@
   InlineFlowBox* CreateLineBoxes(LineLayoutItem,
                                  const LineInfo&,
                                  InlineBox* child_box);
-  void SetMarginsForRubyRun(BidiRun*,
-                            LayoutRubyRun*,
-                            LayoutObject*,
-                            const LineInfo&);
   void ComputeInlineDirectionPositionsForLine(RootInlineBox*,
                                               const LineInfo&,
                                               BidiRun* first_run,
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
index 4681056..bc1dc817 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
@@ -30,7 +30,6 @@
 #include "third_party/blink/renderer/core/layout/layout_list_item.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h"
 #include "third_party/blink/renderer/core/layout/line/glyph_overflow.h"
@@ -470,33 +469,6 @@
                               trailing_space_width;
 }
 
-void LayoutBlockFlow::SetMarginsForRubyRun(BidiRun* run,
-                                           LayoutRubyRun* layout_ruby_run,
-                                           LayoutObject* previous_object,
-                                           const LineInfo& line_info) {
-  NOT_DESTROYED();
-  int start_overhang;
-  int end_overhang;
-  LayoutObject* next_object = nullptr;
-  for (BidiRun* run_with_next_object = run->Next(); run_with_next_object;
-       run_with_next_object = run_with_next_object->Next()) {
-    if (!run_with_next_object->line_layout_item_.IsOutOfFlowPositioned() &&
-        !run_with_next_object->box_->IsLineBreak()) {
-      next_object = run_with_next_object->line_layout_item_.GetLayoutObject();
-      break;
-    }
-  }
-  layout_ruby_run->GetOverhang(
-      line_info.IsFirstLine(),
-      layout_ruby_run->StyleRef().IsLeftToRightDirection() ? previous_object
-                                                           : next_object,
-      layout_ruby_run->StyleRef().IsLeftToRightDirection() ? next_object
-                                                           : previous_object,
-      start_overhang, end_overhang);
-  SetMarginStartForChild(*layout_ruby_run, LayoutUnit(-start_overhang));
-  SetMarginEndForChild(*layout_ruby_run, LayoutUnit(-end_overhang));
-}
-
 static inline wtf_size_t FindWordMeasurement(
     LineLayoutText layout_text,
     int offset,
@@ -810,7 +782,6 @@
   LayoutUnit total_logical_width = line_box->GetFlowSpacingLogicalWidth();
   bool is_after_expansion = true;
   ExpansionOpportunities expansions;
-  LayoutObject* previous_object = nullptr;
   ETextAlign text_align = line_info.GetTextAlign();
 
   BidiRun* r = first_run;
@@ -849,10 +820,6 @@
       if (!r->line_layout_item_.IsLayoutInline()) {
         auto* layout_box =
             To<LayoutBox>(r->line_layout_item_.GetLayoutObject());
-        if (layout_box->IsRubyRun()) {
-          SetMarginsForRubyRun(r, To<LayoutRubyRun>(layout_box),
-                               previous_object, line_info);
-        }
         r->box_->SetLogicalWidth(LogicalWidthForChild(*layout_box));
         total_logical_width +=
             MarginStartForChild(*layout_box) + MarginEndForChild(*layout_box);
@@ -861,7 +828,6 @@
     }
 
     total_logical_width += r->box_->LogicalWidth();
-    previous_object = r->line_layout_item_.GetLayoutObject();
   }
 
   if (is_after_expansion)
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index abba4b1..90c0cce3 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -70,7 +70,6 @@
 #include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
 #include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/layout/layout_text_control.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/ng/custom/custom_layout_child.h"
@@ -89,6 +88,7 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
 #include "third_party/blink/renderer/core/layout/shapes/shape_outside_info.h"
 #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
@@ -1002,7 +1002,6 @@
       IsSVGChild() ? style_to_use.HasTransformRelatedPropertyForSVG()
                    : style_to_use.HasTransformRelatedProperty());
   SetHasReflection(style_to_use.BoxReflect());
-  // LayoutTable and LayoutTableCell will overwrite this flag if needed.
   SetHasNonCollapsedBorderDecoration(style_to_use.HasBorderDecoration());
 
   bool should_clip_overflow = (!StyleRef().IsOverflowVisibleAlongBothAxes() ||
@@ -3292,8 +3291,9 @@
     // set the "layout" result.
     if (measure_result_)
       InvalidateItems(*measure_result_);
-    if (IsTableCell() && !IsTableCellLegacy())
+    if (IsTableCell()) {
       To<LayoutNGTableCell>(this)->InvalidateLayoutResultCacheAfterMeasure();
+    }
     measure_result_ = result;
   } else {
     // We have a "layout" result, and we may need to clear the old "measure"
@@ -3839,29 +3839,12 @@
 
   AncestorSkipInfo skip_info(ancestor, true);
   LayoutObject* container = Container(&skip_info);
-  LayoutBox* table_row_container = nullptr;
-  // Skip table row because cells and rows are in the same coordinate space (see
-  // below, however for more comments about when |ancestor| is the table row).
-  if ((IsTableCell() && !IsLayoutNGObject()) || IsTableCellLegacy()) {
-    DCHECK(container->IsTableRow());
-    DCHECK_EQ(ParentBox(), container);
-    if (container != ancestor)
-      container = container->Parent();
-    else
-      table_row_container = To<LayoutBox>(container);
-  }
   if (!container)
     return true;
 
   PhysicalOffset container_offset;
   if (auto* box = DynamicTo<LayoutBox>(container)) {
     container_offset += PhysicalLocation(box);
-
-    // If the row is the ancestor, however, add its offset back in. In effect,
-    // this passes from the joint <td> / <tr> coordinate space to the parent
-    // space, then back to <tr> / <td>.
-    if (table_row_container)
-      container_offset -= table_row_container->PhysicalLocation(box);
   } else {
     container_offset += PhysicalLocation();
   }
@@ -5516,8 +5499,6 @@
     LayoutBox& layout_box,
     LayoutUnit inline_position,
     LayoutUnit& block_position) {
-  if (layout_box.IsLegacyTableRow())
-    return LayoutUnit();
   block_position += layout_box.LogicalTop();
   if (!layout_box.IsLayoutFlowThread())
     return LayoutUnit();
@@ -6055,8 +6036,9 @@
   LayoutUnit static_logical_top = child->Layer()->StaticBlockPosition();
   for (LayoutObject* curr = child->Parent(); curr && curr != container_block;
        curr = curr->Container()) {
-    if (!curr->IsBox() || curr->IsLegacyTableRow())
+    if (!curr->IsBox()) {
       continue;
+    }
     const auto& box = *To<LayoutBox>(curr);
     static_logical_top +=
         (fragment_builder &&
@@ -7355,9 +7337,10 @@
       (Parent() && IsWritingModeRoot()) ||
       (IsFixedPositioned() && GetDocument().Printing() &&
        IsA<LayoutView>(Container())) ||
-      ShouldApplySizeContainment() || IsFrameSetIncludingNG() ||
-      StyleRef().HasLineClamp())
+      ShouldApplySizeContainment() || IsFrameSet() ||
+      StyleRef().HasLineClamp()) {
     return kForbidBreaks;
+  }
 
   if (engine != kUnknownFragmentationEngine) {
     // If the object isn't using the same engine as the fragmentation context,
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
index 33d427c4..fe2e8e85 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -1053,8 +1053,9 @@
         // FIXME: What are we supposed to do inside SVG content?
         reference_point += PhysicalOffsetToBeNoop(
             current->ColumnOffset(reference_point.ToLayoutPoint()));
-        if (current->IsBox() && !current->IsLegacyTableRow())
+        if (current->IsBox()) {
           reference_point += To<LayoutBox>(current)->PhysicalLocation();
+        }
       }
 
       if (offset_parent_object->IsBox() && offset_parent_object->IsBody() &&
@@ -1317,7 +1318,7 @@
       auto* parent_box = To<LayoutBoxModelObject>(box_to_split->Parent());
       // We need to invalidate the |parentBox| before inserting the new node
       // so that the table paint invalidation logic knows the structure is
-      // dirty. See for example LayoutTableCell:localVisualRect().
+      // dirty.
       MarkBoxForRelayoutAfterSplit(parent_box);
       parent_box->VirtualChildren()->InsertChildNode(
           parent_box, post_box, box_to_split->NextSibling());
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.h b/third_party/blink/renderer/core/layout/layout_box_model_object.h
index 15e9009..3f2a67a 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.h
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.h
@@ -246,8 +246,6 @@
   }
 
   // These functions are used during layout.
-  // - Table cells override them to include the intrinsic padding (see
-  //   explanations in LayoutTableCell).
   // - Table override them to exclude padding with collapsing borders.
   virtual LayoutUnit PaddingTop() const {
     NOT_DESTROYED();
diff --git a/third_party/blink/renderer/core/layout/layout_frame.h b/third_party/blink/renderer/core/layout/layout_frame.h
index 1787bb95..8b82096e 100644
--- a/third_party/blink/renderer/core/layout/layout_frame.h
+++ b/third_party/blink/renderer/core/layout/layout_frame.h
@@ -24,7 +24,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FRAME_H_
 
 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
-#include "third_party/blink/renderer/core/layout/layout_frame_set.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/layout/layout_frame_set.cc b/third_party/blink/renderer/core/layout/layout_frame_set.cc
deleted file mode 100644
index 84fa8e2..0000000
--- a/third_party/blink/renderer/core/layout/layout_frame_set.cc
+++ /dev/null
@@ -1,416 +0,0 @@
-/**
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 2000 Simon Hausmann <hausmann@kde.org>
- *           (C) 2000 Stefan Schimanski (1Stein@gmx.de)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "third_party/blink/renderer/core/layout/layout_frame_set.h"
-
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/events/mouse_event.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/html/frame_edge_info.h"
-#include "third_party/blink/renderer/core/html/html_dimension.h"
-#include "third_party/blink/renderer/core/html/html_frame_element.h"
-#include "third_party/blink/renderer/core/html/html_frame_set_element.h"
-#include "third_party/blink/renderer/core/layout/layout_frame.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/paint/frame_set_painter.h"
-#include "third_party/blink/renderer/platform/cursors.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "ui/base/cursor/cursor.h"
-
-namespace blink {
-
-// Adjusts proportionally the size with remaining size.
-static int AdjustSizeToRemainingSize(int current,
-                                     int remaining,
-                                     int64_t total) {
-  // Performs the math operations step by step to avoid the overflow.
-  base::CheckedNumeric<int64_t> temp_product = current;
-  temp_product *= remaining;
-  temp_product /= total;
-  return base::checked_cast<int>(temp_product.ValueOrDie());
-}
-
-LayoutFrameSet::LayoutFrameSet(Element* element) : LayoutBox(element) {
-  DCHECK(IsA<HTMLFrameSetElement>(element));
-  SetInline(false);
-}
-
-LayoutFrameSet::~LayoutFrameSet() = default;
-
-void LayoutFrameSet::Trace(Visitor* visitor) const {
-  visitor->Trace(children_);
-  LayoutBox::Trace(visitor);
-}
-
-HTMLFrameSetElement* LayoutFrameSet::FrameSet() const {
-  NOT_DESTROYED();
-  return To<HTMLFrameSetElement>(GetNode());
-}
-
-void LayoutFrameSet::Paint(const PaintInfo& paint_info) const {
-  NOT_DESTROYED();
-  FrameSetPainter(*this).Paint(paint_info);
-}
-
-void LayoutFrameSet::GridAxis::Resize(int size) {
-  sizes_.resize(size);
-}
-
-void LayoutFrameSet::LayOutAxis(GridAxis& axis,
-                                const Vector<HTMLDimension>& grid,
-                                const Vector<int>& deltas,
-                                int available_len) {
-  NOT_DESTROYED();
-  DCHECK_EQ(axis.sizes_.size(), deltas.size());
-
-  available_len = max(available_len, 0);
-
-  DCHECK_EQ(axis.sizes_.size(), deltas.size());
-
-  if (grid.empty()) {
-    axis.sizes_[0] = LayoutUnit(available_len);
-    return;
-  }
-
-  Vector<int> grid_layout(axis.sizes_.size());
-  int grid_len = axis.sizes_.size();
-  DCHECK(grid_len);
-
-  int64_t total_relative = 0;
-  int64_t total_fixed = 0;
-  int64_t total_percent = 0;
-  int count_relative = 0;
-  int count_fixed = 0;
-  int count_percent = 0;
-
-  float effective_zoom = StyleRef().EffectiveZoom();
-
-  // First we need to investigate how many columns of each type we have and
-  // how much space these columns are going to require.
-  for (int i = 0; i < grid_len; ++i) {
-    // Count the total length of all of the fixed columns/rows -> totalFixed.
-    // Count the number of columns/rows which are fixed -> countFixed.
-    if (grid[i].IsAbsolute()) {
-      grid_layout[i] = ClampTo<int>(max(grid[i].Value() * effective_zoom, 0.0));
-      total_fixed += grid_layout[i];
-      count_fixed++;
-    }
-
-    // Count the total percentage of all of the percentage columns/rows ->
-    // totalPercent. Count the number of columns/rows which are percentages ->
-    // countPercent.
-    if (grid[i].IsPercentage()) {
-      grid_layout[i] =
-          ClampTo<int>(max(grid[i].Value() * available_len / 100., 0.0));
-      total_percent += grid_layout[i];
-      count_percent++;
-    }
-
-    // Count the total relative of all the relative columns/rows ->
-    // totalRelative. Count the number of columns/rows which are relative ->
-    // countRelative.
-    if (grid[i].IsRelative()) {
-      total_relative += ClampTo<int>(max(grid[i].Value(), 1.0));
-      count_relative++;
-    }
-  }
-
-  int remaining_len = available_len;
-
-  // Fixed columns/rows are our first priority. If there is not enough space to
-  // fit all fixed columns/rows we need to proportionally adjust their size.
-  if (total_fixed > remaining_len) {
-    int remaining_fixed = remaining_len;
-
-    for (int i = 0; i < grid_len; ++i) {
-      if (grid[i].IsAbsolute()) {
-        grid_layout[i] = AdjustSizeToRemainingSize(
-            grid_layout[i], remaining_fixed, total_fixed);
-        remaining_len -= grid_layout[i];
-      }
-    }
-  } else {
-    remaining_len -= total_fixed;
-  }
-
-  // Percentage columns/rows are our second priority. Divide the remaining space
-  // proportionally over all percentage columns/rows.
-  // NOTE: the size of each column/row is not relative to 100%, but to the total
-  // percentage. For example, if there are three columns, each of 75%, and the
-  // available space is 300px, each column will become 100px in width.
-  if (total_percent > remaining_len) {
-    int remaining_percent = remaining_len;
-
-    for (int i = 0; i < grid_len; ++i) {
-      if (grid[i].IsPercentage()) {
-        grid_layout[i] = AdjustSizeToRemainingSize(
-            grid_layout[i], remaining_percent, total_percent);
-        remaining_len -= grid_layout[i];
-      }
-    }
-  } else {
-    remaining_len -= total_percent;
-  }
-
-  // Relative columns/rows are our last priority. Divide the remaining space
-  // proportionally over all relative columns/rows.
-  // NOTE: the relative value of 0* is treated as 1*.
-  if (count_relative) {
-    int last_relative = 0;
-    int64_t remaining_relative = remaining_len;
-
-    for (int i = 0; i < grid_len; ++i) {
-      if (grid[i].IsRelative()) {
-        grid_layout[i] = ClampTo<int>(
-            (ClampTo<int>(max(grid[i].Value(), 1.)) * remaining_relative) /
-            total_relative);
-        remaining_len -= grid_layout[i];
-        DCHECK_GE(remaining_len, 0);
-        last_relative = i;
-      }
-    }
-
-    // If we could not evenly distribute the available space of all of the
-    // relative columns/rows, the remainder will be added to the last column/
-    // row. For example: if we have a space of 100px and three columns (*,*,*),
-    // the remainder will be 1px and will be added to the last column: 33px,
-    // 33px, 34px.
-    if (remaining_len) {
-      grid_layout[last_relative] += remaining_len;
-      remaining_len = 0;
-    }
-  }
-
-  // If we still have some left over space we need to divide it over the already
-  // existing columns/rows
-  if (remaining_len) {
-    // Our first priority is to spread if over the percentage columns. The
-    // remaining space is spread evenly, for example: if we have a space of
-    // 100px, the columns definition of 25%,25% used to result in two columns of
-    // 25px. After this the columns will each be 50px in width.
-    if (count_percent && total_percent) {
-      int remaining_percent = remaining_len;
-      int change_percent = 0;
-
-      for (int i = 0; i < grid_len; ++i) {
-        if (grid[i].IsPercentage()) {
-          change_percent = AdjustSizeToRemainingSize(
-              grid_layout[i], remaining_percent, total_percent);
-          grid_layout[i] += change_percent;
-          remaining_len -= change_percent;
-        }
-      }
-    } else if (total_fixed) {
-      // Our last priority is to spread the remaining space over the fixed
-      // columns. For example if we have 100px of space and two column of each
-      // 40px, both columns will become exactly 50px.
-      int remaining_fixed = remaining_len;
-      int change_fixed = 0;
-
-      for (int i = 0; i < grid_len; ++i) {
-        if (grid[i].IsAbsolute()) {
-          change_fixed = AdjustSizeToRemainingSize(
-              grid_layout[i], remaining_fixed, total_fixed);
-          grid_layout[i] += change_fixed;
-          remaining_len -= change_fixed;
-        }
-      }
-    }
-  }
-
-  // If we still have some left over space we probably ended up with a remainder
-  // of a division. We cannot spread it evenly anymore. If we have any
-  // percentage columns/rows simply spread the remainder equally over all
-  // available percentage columns, regardless of their size.
-  if (remaining_len && count_percent) {
-    int remaining_percent = remaining_len;
-    int change_percent = 0;
-
-    for (int i = 0; i < grid_len; ++i) {
-      if (grid[i].IsPercentage()) {
-        change_percent = remaining_percent / count_percent;
-        grid_layout[i] += change_percent;
-        remaining_len -= change_percent;
-      }
-    }
-  } else if (remaining_len && count_fixed) {
-    // If we don't have any percentage columns/rows we only have fixed columns.
-    // Spread the remainder equally over all fixed columns/rows.
-    int remaining_fixed = remaining_len;
-    int change_fixed = 0;
-
-    for (int i = 0; i < grid_len; ++i) {
-      if (grid[i].IsAbsolute()) {
-        change_fixed = remaining_fixed / count_fixed;
-        grid_layout[i] += change_fixed;
-        remaining_len -= change_fixed;
-      }
-    }
-  }
-
-  // Still some left over. Add it to the last column, because it is impossible
-  // spread it evenly or equally.
-  if (remaining_len)
-    grid_layout[grid_len - 1] += remaining_len;
-
-  // now we have the final layout, distribute the delta over it
-  bool worked = true;
-  for (int i = 0; i < grid_len; ++i) {
-    if (grid_layout[i] && grid_layout[i] + deltas[i] <= 0)
-      worked = false;
-    grid_layout[i] += deltas[i];
-  }
-  // if the deltas broke something, undo them
-  if (!worked) {
-    for (int i = 0; i < grid_len; ++i)
-      grid_layout[i] -= deltas[i];
-  }
-
-  for (int i = 0; i < grid_len; ++i)
-    axis.sizes_[i] = LayoutUnit(grid_layout[i]);
-}
-
-void LayoutFrameSet::UpdateLayout() {
-  NOT_DESTROYED();
-  DCHECK(NeedsLayout());
-
-  if (!Parent()->IsFrameSet()) {
-    SetWidth(LayoutUnit(View()->ViewWidth()));
-    SetHeight(LayoutUnit(View()->ViewHeight()));
-  }
-
-  unsigned cols = FrameSet()->TotalCols();
-  unsigned rows = FrameSet()->TotalRows();
-  const Vector<int>& rows_deltas = FrameSet()->RowDeltas();
-  const Vector<int>& cols_deltas = FrameSet()->ColDeltas();
-
-  if (rows_.sizes_.size() != rows || cols_.sizes_.size() != cols) {
-    rows_.Resize(rows);
-    cols_.Resize(cols);
-  }
-
-  LayoutUnit border_thickness(FrameSet()->Border(StyleRef()));
-  LayOutAxis(rows_, FrameSet()->RowLengths(), rows_deltas,
-             (Size().Height() - (rows - 1) * border_thickness).ToInt());
-  LayOutAxis(cols_, FrameSet()->ColLengths(), cols_deltas,
-             (Size().Width() - (cols - 1) * border_thickness).ToInt());
-
-  PositionFrames();
-
-  LayoutBox::UpdateLayout();
-
-  cols_.allow_border_ = FrameSet()->AllowBorderColumns();
-  rows_.allow_border_ = FrameSet()->AllowBorderRows();
-
-  UpdateAfterLayout();
-
-  ClearNeedsLayout();
-}
-
-static void ClearNeedsLayoutOnHiddenFrames(LayoutBox* frame) {
-  for (; frame; frame = frame->NextSiblingBox()) {
-    frame->SetWidth(LayoutUnit());
-    frame->SetHeight(LayoutUnit());
-    frame->ClearNeedsLayout();
-    ClearNeedsLayoutOnHiddenFrames(frame->FirstChildBox());
-  }
-}
-
-void LayoutFrameSet::PositionFrames() {
-  NOT_DESTROYED();
-  LayoutBox* child = FirstChildBox();
-  if (!child)
-    return;
-
-  int rows = FrameSet()->TotalRows();
-  int cols = FrameSet()->TotalCols();
-
-  int border_thickness = FrameSet()->Border(StyleRef());
-  LayoutSize size;
-  LayoutPoint position;
-  for (int r = 0; r < rows; r++) {
-    position.SetX(LayoutUnit());
-    size.SetHeight(LayoutUnit(rows_.sizes_[r]));
-    for (int c = 0; c < cols; c++) {
-      child->SetLocation(position);
-      size.SetWidth(LayoutUnit(cols_.sizes_[c]));
-
-      // If we have a new size, we need to resize and layout the child. If the
-      // size is 0x0 we also need to lay out, since this may mean that we're
-      // dealing with a child frameset that wasn't previously initialized
-      // properly, because it was previously hidden, but no longer is, because
-      // rows * cols may have increased.
-      if (size != child->Size() || size.IsEmpty()) {
-        child->SetSize(size);
-        child->SetNeedsLayoutAndFullPaintInvalidation(
-            layout_invalidation_reason::kSizeChanged);
-        child->UpdateLayout();
-      }
-
-      position.SetX(position.X() + size.Width() + border_thickness);
-
-      child = child->NextSiblingBox();
-      if (!child)
-        return;
-    }
-    position.SetY(position.Y() + size.Height() + border_thickness);
-  }
-
-  // All the remaining frames are hidden to avoid ugly spurious unflowed frames.
-  ClearNeedsLayoutOnHiddenFrames(child);
-}
-
-bool LayoutFrameSet::IsChildAllowed(LayoutObject* child,
-                                    const ComputedStyle&) const {
-  NOT_DESTROYED();
-  return child->IsFrame() || child->IsFrameSet();
-}
-
-void LayoutFrameSet::AddChild(LayoutObject* new_child,
-                              LayoutObject* before_child) {
-  LayoutBox::AddChild(new_child, before_child);
-  FrameSet()->DirtyEdgeInfoAndFullPaintInvalidation();
-}
-
-void LayoutFrameSet::RemoveChild(LayoutObject* child) {
-  LayoutBox::RemoveChild(child);
-  if (!DocumentBeingDestroyed())
-    FrameSet()->DirtyEdgeInfoAndFullPaintInvalidation();
-}
-
-CursorDirective LayoutFrameSet::GetCursor(const PhysicalOffset& point,
-                                          ui::Cursor& cursor) const {
-  NOT_DESTROYED();
-  gfx::Point rounded_point = ToRoundedPoint(point);
-  if (FrameSet()->CanResizeRow(rounded_point)) {
-    cursor = RowResizeCursor();
-    return kSetCursor;
-  }
-  if (FrameSet()->CanResizeColumn(rounded_point)) {
-    cursor = ColumnResizeCursor();
-    return kSetCursor;
-  }
-  return LayoutBox::GetCursor(point, cursor);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_frame_set.h b/third_party/blink/renderer/core/layout/layout_frame_set.h
deleted file mode 100644
index 4f08ed81..0000000
--- a/third_party/blink/renderer/core/layout/layout_frame_set.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 2000 Simon Hausmann <hausmann@kde.org>
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FRAME_SET_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FRAME_SET_H_
-
-#include "base/check_op.h"
-#include "third_party/blink/renderer/core/layout/layout_box.h"
-
-namespace blink {
-
-class HTMLDimension;
-class HTMLFrameSetElement;
-
-class LayoutFrameSet final : public LayoutBox {
- public:
-  explicit LayoutFrameSet(Element*);
-  ~LayoutFrameSet() override;
-  void Trace(Visitor*) const override;
-
-  LayoutObject* FirstChild() const {
-    NOT_DESTROYED();
-    DCHECK_EQ(Children(), VirtualChildren());
-    return Children()->FirstChild();
-  }
-  LayoutObject* LastChild() const {
-    NOT_DESTROYED();
-    DCHECK_EQ(Children(), VirtualChildren());
-    return Children()->LastChild();
-  }
-
-  // If you have a LayoutFrameSet, use firstChild or lastChild instead.
-  void SlowFirstChild() const = delete;
-  void SlowLastChild() const = delete;
-
-  const LayoutObjectChildList* Children() const {
-    NOT_DESTROYED();
-    return &children_;
-  }
-  LayoutObjectChildList* Children() {
-    NOT_DESTROYED();
-    return &children_;
-  }
-
-  HTMLFrameSetElement* FrameSet() const;
-
-  class GridAxis {
-    DISALLOW_NEW();
-
-   public:
-    GridAxis() = default;
-    GridAxis(const GridAxis&) = delete;
-    GridAxis& operator=(const GridAxis&) = delete;
-
-    void Resize(int);
-
-    Vector<LayoutUnit> sizes_;
-    // A copy of HTMLFrameSetElement::allow_border_*.  It's helpful
-    // because this information is used at the paint stage.
-    Vector<bool> allow_border_;
-  };
-
-  const GridAxis& Rows() const {
-    NOT_DESTROYED();
-    return rows_;
-  }
-  const GridAxis& Columns() const {
-    NOT_DESTROYED();
-    return cols_;
-  }
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutFrameSet";
-  }
-
- private:
-  LayoutObjectChildList* VirtualChildren() override {
-    NOT_DESTROYED();
-    return Children();
-  }
-  const LayoutObjectChildList* VirtualChildren() const override {
-    NOT_DESTROYED();
-    return Children();
-  }
-
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectFrameSet || LayoutBox::IsOfType(type);
-  }
-
-  void UpdateLayout() override;
-  void Paint(const PaintInfo&) const override;
-
-  MinMaxSizes PreferredLogicalWidths() const override {
-    NOT_DESTROYED();
-    return MinMaxSizes();
-  }
-  MinMaxSizes ComputeIntrinsicLogicalWidths() const final {
-    NOT_DESTROYED();
-    MinMaxSizes sizes;
-    LayoutUnit scrollbar_thickness = ComputeLogicalScrollbars().InlineSum();
-    sizes += BorderAndPaddingLogicalWidth() + scrollbar_thickness;
-    return sizes;
-  }
-
-  bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
-  void AddChild(LayoutObject* new_child, LayoutObject* before_child) override;
-  void RemoveChild(LayoutObject* child) override;
-  CursorDirective GetCursor(const PhysicalOffset&, ui::Cursor&) const override;
-
-  void LayOutAxis(GridAxis&,
-                  const Vector<HTMLDimension>&,
-                  const Vector<int>& deltas,
-                  int available_space);
-  void PositionFrames();
-
-  LayoutObjectChildList children_;
-
-  GridAxis rows_;
-  GridAxis cols_;
-};
-
-template <>
-struct DowncastTraits<LayoutFrameSet> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsFrameSet();
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FRAME_SET_H_
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index c3cbad6f..adf1730 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -85,23 +85,28 @@
 #include "third_party/blink/renderer/core/layout/layout_object_factory.h"
 #include "third_party/blink/renderer/core/layout/layout_object_inl.h"
 #include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
 #include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
 #include "third_party/blink/renderer/core/layout/layout_theme.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/custom/layout_ng_custom.h"
 #include "third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_outline_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 #include "third_party/blink/renderer/core/page/autoscroll_controller.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/paint/fragment_data_iterator.h"
@@ -175,9 +180,6 @@
   // The NG paint system currently doesn't support replaced content.
   if (obj.IsLayoutReplaced())
     return false;
-  // The NG paint system currently doesn't support table-cells.
-  if (obj.IsTableCellLegacy())
-    return false;
   // Text controls have some logic in the layout objects that will be missed if
   // we traverse the fragment tree when hit-testing.
   if (obj.IsTextControl()) {
@@ -373,20 +375,20 @@
       return LayoutObjectFactory::CreateBlockFlow(*element, style, legacy);
     case EDisplay::kTable:
     case EDisplay::kInlineTable:
-      return LayoutObjectFactory::CreateTable(*element, style, legacy);
+      return MakeGarbageCollected<LayoutNGTable>(element);
     case EDisplay::kTableRowGroup:
     case EDisplay::kTableHeaderGroup:
     case EDisplay::kTableFooterGroup:
-      return LayoutObjectFactory::CreateTableSection(*element, style, legacy);
+      return MakeGarbageCollected<LayoutNGTableSection>(element);
     case EDisplay::kTableRow:
-      return LayoutObjectFactory::CreateTableRow(*element, style, legacy);
+      return MakeGarbageCollected<LayoutNGTableRow>(element);
     case EDisplay::kTableColumnGroup:
     case EDisplay::kTableColumn:
-      return LayoutObjectFactory::CreateTableColumn(*element, style, legacy);
+      return MakeGarbageCollected<LayoutNGTableColumn>(element);
     case EDisplay::kTableCell:
-      return LayoutObjectFactory::CreateTableCell(*element, style, legacy);
+      return MakeGarbageCollected<LayoutNGTableCell>(element);
     case EDisplay::kTableCaption:
-      return LayoutObjectFactory::CreateTableCaption(*element, style, legacy);
+      return MakeGarbageCollected<LayoutNGTableCaption>(element);
     case EDisplay::kWebkitBox:
     case EDisplay::kWebkitInlineBox:
       if (style.IsDeprecatedWebkitBoxWithVerticalLineClamp()) {
@@ -405,10 +407,10 @@
       return MakeGarbageCollected<LayoutNGGrid>(element);
     case EDisplay::kMath:
     case EDisplay::kBlockMath:
-      return LayoutObjectFactory::CreateMath(*element, style, legacy);
+      return MakeGarbageCollected<LayoutNGMathMLBlock>(element);
     case EDisplay::kLayoutCustom:
     case EDisplay::kInlineLayoutCustom:
-      return LayoutObjectFactory::CreateCustom(*element, style, legacy);
+      return MakeGarbageCollected<LayoutNGCustom>(element);
   }
 
   NOTREACHED();
@@ -580,8 +582,9 @@
 
   // Make an exception for <frameset> children, which don't produce fragments
   // if the number of children is larger than <rows count> * <cols count>.
-  if (Parent() && Parent()->IsFrameSetIncludingNG())
+  if (Parent() && Parent()->IsFrameSet()) {
     return;
+  }
 
   // Sometimes we just have a Layout(NG)View with no children, and the view is
   // not marked for layout, even if it has never been laid out. It seems that we
@@ -625,8 +628,7 @@
         !after_child->IsBeforeContent()) {
       table = after_child;
     } else {
-      table = LayoutObjectFactory::CreateAnonymousTableWithParent(
-          *this, !new_child->IsLayoutNGObject());
+      table = LayoutNGTable::CreateAnonymousWithParent(*this);
       children->InsertChildNode(this, table, before_child);
     }
     table->AddChild(new_child);
@@ -1641,10 +1643,7 @@
     // rather than from their parents (sections or rows). Skip these when
     // invalidating.
     if (current->IsTableCell()) {
-      if (current->IsTableCellLegacy())
-        return current->ContainingBlock();
-      else
-        return To<LayoutNGTableCell>(current)->Table();
+      return To<LayoutNGTableCell>(current)->Table();
     }
     return current->Container();
   };
@@ -3956,7 +3955,8 @@
     }
     // RubyBase should be kept if RubyText exists
     if (destroy_root_parent->IsRubyBase()) {
-      auto* ruby_run = DynamicTo<LayoutRubyRun>(destroy_root_parent->Parent());
+      auto* ruby_run =
+          DynamicTo<LayoutNGRubyRun>(destroy_root_parent->Parent());
       if (ruby_run && ruby_run->HasRubyText())
         break;
     }
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 66ef99e..3ac7f63 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -194,7 +194,7 @@
 // Some LayoutObjects don't have an associated Node and are called "anonymous"
 // (see the constructor below). Anonymous LayoutObjects exist for several
 // purposes but are usually required by CSS. A good example is anonymous table
-// parts (see LayoutTable for the expected structure). Anonymous LayoutObjects
+// parts (see LayoutNGTable for the expected structure). Anonymous LayoutObjects
 // are generated when a new child is added to the tree in addChild(). See the
 // function for some important information on this.
 //
@@ -583,7 +583,7 @@
   // from a structure of a flat tree if Shadow DOM is used.
   // See LayoutTreeBuilderTraversal and FlatTreeTraversal.
   //
-  // See LayoutTable::addChild and LayoutBlock::addChild.
+  // See LayoutNGTable::AddChild and LayoutBlockFlow::AddChild.
   // TODO(jchaffraix): |newChild| cannot be nullptr and should be a reference.
   virtual void AddChild(LayoutObject* new_child,
                         LayoutObject* before_child = nullptr);
@@ -843,7 +843,7 @@
   // For renderer creation, the inline-* values create the same renderer
   // as the non-inline version. The difference is that inline-* sets
   // is_inline_ during initialization. This means that
-  // "display: inline-table" creates a LayoutTable, like "display: table".
+  // "display: inline-table" creates a LayoutNGTable, like "display: table".
   //
   // Ideally every Element::createLayoutObject would call this function to
   // respond to 'display' but there are deep rooted assumptions about
@@ -890,16 +890,8 @@
   }
   bool IsFrameSet() const {
     NOT_DESTROYED();
-    return IsOfType(kLayoutObjectFrameSet);
-  }
-  bool IsLayoutNGFrameSet() const {
-    NOT_DESTROYED();
     return IsOfType(kLayoutObjectNGFrameSet);
   }
-  bool IsFrameSetIncludingNG() const {
-    NOT_DESTROYED();
-    return IsFrameSet() || IsLayoutNGFrameSet();
-  }
   bool IsInsideListMarkerForCustomContent() const {
     NOT_DESTROYED();
     return IsOfType(kLayoutObjectInsideListMarker);
@@ -1048,26 +1040,14 @@
     NOT_DESTROYED();
     return IsOfType(kLayoutObjectTableCell);
   }
-  bool IsTableCellLegacy() const {
-    NOT_DESTROYED();
-    return IsOfType(kLayoutObjectTableCellLegacy);
-  }
   bool IsTableRow() const {
     NOT_DESTROYED();
     return IsOfType(kLayoutObjectTableRow);
   }
-  bool IsLegacyTableRow() const {
-    NOT_DESTROYED();
-    return IsTableRow() && !IsLayoutNGObject();
-  }
   bool IsTableSection() const {
     NOT_DESTROYED();
     return IsOfType(kLayoutObjectTableSection);
   }
-  bool IsLegacyTableSection() const {
-    NOT_DESTROYED();
-    return IsTableSection() && !IsLayoutNGObject();
-  }
   bool IsTextArea() const {
     NOT_DESTROYED();
     return IsOfType(kLayoutObjectNGTextControlMultiLine);
@@ -2478,7 +2458,7 @@
   // - if the CSS containing block is a relatively positioned inline,
   //   the function returns the inline's enclosing non-anonymous LayoutBlock.
   //   This means that a LayoutInline would be skipped (expected as it's not a
-  //   LayoutBlock) but so would be an inline LayoutTable or LayoutBlockFlow.
+  //   LayoutBlock) but so would be an inline LayoutNGTable or LayoutBlockFlow.
   //   TODO(jchaffraix): Is that REALLY what we want here?
   // - if the CSS containing block is anonymous, we find its enclosing
   //   non-anonymous LayoutBlock.
@@ -3703,7 +3683,6 @@
     kLayoutObjectCustomScrollbarPart,
     kLayoutObjectEmbeddedObject,
     kLayoutObjectFrame,
-    kLayoutObjectFrameSet,
     kLayoutObjectIFrame,
     kLayoutObjectImage,
     kLayoutObjectInsideListMarker,
@@ -3742,7 +3721,6 @@
     kLayoutObjectTable,
     kLayoutObjectTableCaption,
     kLayoutObjectTableCell,
-    kLayoutObjectTableCellLegacy,
     kLayoutObjectTableCol,
     kLayoutObjectTableRow,
     kLayoutObjectTableSection,
diff --git a/third_party/blink/renderer/core/layout/layout_object_factory.cc b/third_party/blink/renderer/core/layout/layout_object_factory.cc
index c5923ca8..4f13710 100644
--- a/third_party/blink/renderer/core/layout/layout_object_factory.cc
+++ b/third_party/blink/renderer/core/layout/layout_object_factory.cc
@@ -8,20 +8,12 @@
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/core/html/html_frame_set_element.h"
 #include "third_party/blink/renderer/core/layout/layout_block_flow.h"
 #include "third_party/blink/renderer/core/layout/layout_counter.h"
-#include "third_party/blink/renderer/core/layout/layout_frame_set.h"
 #include "third_party/blink/renderer/core/layout/layout_inside_list_marker.h"
 #include "third_party/blink/renderer/core/layout/layout_list_item.h"
 #include "third_party/blink/renderer/core/layout/layout_list_marker.h"
 #include "third_party/blink/renderer/core/layout/layout_outside_list_marker.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
 #include "third_party/blink/renderer/core/layout/layout_text.h"
 #include "third_party/blink/renderer/core/layout/layout_text_combine.h"
 #include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
@@ -35,22 +27,14 @@
 #include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_word_break.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_progress.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_view.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h"
 #include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h"
 #include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_flow.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 #include "third_party/blink/renderer/core/mathml/mathml_element.h"
 #include "third_party/blink/renderer/core/mathml/mathml_token_element.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
@@ -114,33 +98,6 @@
   return CreateObject<LayoutBlockFlow, LayoutNGBlockFlow>(node, legacy);
 }
 
-LayoutView* LayoutObjectFactory::CreateView(Document& document,
-                                            const ComputedStyle& style) {
-  return MakeGarbageCollected<LayoutNGView>(&document);
-}
-
-LayoutBlock* LayoutObjectFactory::CreateMath(Node& node,
-                                             const ComputedStyle& style,
-                                             LegacyLayout legacy) {
-  DCHECK(IsA<MathMLElement>(node) || node.IsDocumentNode() /* is_anonymous */);
-  bool disable_ng_for_type = !RuntimeEnabledFeatures::MathMLCoreEnabled();
-  if (IsA<MathMLTokenElement>(node)) {
-    return CreateObject<LayoutBlockFlow, LayoutNGMathMLBlockFlow,
-                        LayoutBlockFlow>(node, legacy, disable_ng_for_type);
-  }
-  return CreateObject<LayoutBlock, LayoutNGMathMLBlock, LayoutBlockFlow>(
-      node, legacy, disable_ng_for_type);
-}
-
-LayoutBlock* LayoutObjectFactory::CreateCustom(Node& node,
-                                               const ComputedStyle& style,
-                                               LegacyLayout legacy) {
-  DCHECK(node.IsElementNode());
-  bool disable_ng_for_type = !RuntimeEnabledFeatures::CSSLayoutAPIEnabled();
-  return CreateObject<LayoutBlock, LayoutNGCustom, LayoutBlockFlow>(
-      node, legacy, disable_ng_for_type);
-}
-
 LayoutObject* LayoutObjectFactory::CreateListMarker(Node& node,
                                                     const ComputedStyle& style,
                                                     LegacyLayout legacy) {
@@ -169,48 +126,6 @@
                       LayoutOutsideListMarker>(node, legacy);
 }
 
-LayoutBlock* LayoutObjectFactory::CreateTable(Node& node,
-                                              const ComputedStyle& style,
-                                              LegacyLayout legacy) {
-  return CreateObject<LayoutBlock, LayoutNGTable, LayoutTable>(node, legacy);
-}
-
-LayoutTableCaption* LayoutObjectFactory::CreateTableCaption(
-    Node& node,
-    const ComputedStyle& style,
-    LegacyLayout legacy) {
-  return CreateObject<LayoutTableCaption, LayoutNGTableCaption>(node, legacy);
-}
-
-LayoutBlockFlow* LayoutObjectFactory::CreateTableCell(
-    Node& node,
-    const ComputedStyle& style,
-    LegacyLayout legacy) {
-  return CreateObject<LayoutBlockFlow, LayoutNGTableCell, LayoutTableCell>(
-      node, legacy);
-}
-
-LayoutBox* LayoutObjectFactory::CreateTableColumn(Node& node,
-                                                  const ComputedStyle& style,
-                                                  LegacyLayout legacy) {
-  return CreateObject<LayoutBox, LayoutNGTableColumn, LayoutTableCol>(node,
-                                                                      legacy);
-}
-
-LayoutBox* LayoutObjectFactory::CreateTableRow(Node& node,
-                                               const ComputedStyle& style,
-                                               LegacyLayout legacy) {
-  return CreateObject<LayoutBox, LayoutNGTableRow, LayoutTableRow>(node,
-                                                                   legacy);
-}
-
-LayoutBox* LayoutObjectFactory::CreateTableSection(Node& node,
-                                                   const ComputedStyle& style,
-                                                   LegacyLayout legacy) {
-  return CreateObject<LayoutBox, LayoutNGTableSection, LayoutTableSection>(
-      node, legacy);
-}
-
 LayoutObject* LayoutObjectFactory::CreateCounter(
     PseudoElement& pseduo,
     const CounterContentData& counter,
@@ -225,13 +140,6 @@
   return new_object;
 }
 
-LayoutBox* LayoutObjectFactory::CreateFrameSet(HTMLFrameSetElement& element,
-                                               const ComputedStyle& style,
-                                               LegacyLayout legacy) {
-  return CreateObject<LayoutBox, LayoutNGFrameSet, LayoutFrameSet>(element,
-                                                                   legacy);
-}
-
 LayoutText* LayoutObjectFactory::CreateText(Node* node,
                                             String str,
                                             LegacyLayout legacy) {
@@ -284,19 +192,6 @@
   return CreateObject<LayoutProgress, LayoutNGProgress>(*node, legacy);
 }
 
-LayoutRubyAsBlock* LayoutObjectFactory::CreateRubyAsBlock(
-    Node* node,
-    const ComputedStyle& style,
-    LegacyLayout legacy) {
-  return CreateObject<LayoutRubyAsBlock, LayoutNGRubyAsBlock>(*node, legacy);
-}
-
-LayoutObject* LayoutObjectFactory::CreateRubyText(Node* node,
-                                                  const ComputedStyle& style,
-                                                  LegacyLayout legacy) {
-  return CreateObject<LayoutRubyText, LayoutNGRubyText>(*node, legacy);
-}
-
 LayoutObject* LayoutObjectFactory::CreateBR(Node* node, LegacyLayout legacy) {
   return CreateObject<LayoutObject, LayoutNGBR, LayoutBR>(*node, legacy);
 }
@@ -307,68 +202,4 @@
       *element, legacy);
 }
 
-LayoutBox* LayoutObjectFactory::CreateAnonymousTableWithParent(
-    const LayoutObject& parent,
-    bool child_forces_legacy) {
-  scoped_refptr<const ComputedStyle> new_style =
-      parent.GetDocument().GetStyleResolver().CreateAnonymousStyleWithDisplay(
-          parent.StyleRef(),
-          parent.IsLayoutInline() ? EDisplay::kInlineTable : EDisplay::kTable);
-  LegacyLayout legacy =
-      parent.ForceLegacyLayoutForChildren() || child_forces_legacy
-          ? LegacyLayout::kForce
-          : LegacyLayout::kAuto;
-
-  LayoutBlock* new_table =
-      CreateTable(parent.GetDocument(), *new_style, legacy);
-  new_table->SetDocumentForAnonymous(&parent.GetDocument());
-  new_table->SetStyle(std::move(new_style));
-  return new_table;
-}
-
-LayoutBox* LayoutObjectFactory::CreateAnonymousTableSectionWithParent(
-    const LayoutObject& parent) {
-  scoped_refptr<const ComputedStyle> new_style =
-      parent.GetDocument().GetStyleResolver().CreateAnonymousStyleWithDisplay(
-          parent.StyleRef(), EDisplay::kTableRowGroup);
-  LegacyLayout legacy = parent.ForceLegacyLayoutForChildren()
-                            ? LegacyLayout::kForce
-                            : LegacyLayout::kAuto;
-
-  LayoutBox* new_section =
-      CreateTableSection(parent.GetDocument(), *new_style, legacy);
-  new_section->SetDocumentForAnonymous(&parent.GetDocument());
-  new_section->SetStyle(std::move(new_style));
-  return new_section;
-}
-
-LayoutBox* LayoutObjectFactory::CreateAnonymousTableRowWithParent(
-    const LayoutObject& parent) {
-  scoped_refptr<const ComputedStyle> new_style =
-      parent.GetDocument().GetStyleResolver().CreateAnonymousStyleWithDisplay(
-          parent.StyleRef(), EDisplay::kTableRow);
-  LegacyLayout legacy = parent.ForceLegacyLayoutForChildren()
-                            ? LegacyLayout::kForce
-                            : LegacyLayout::kAuto;
-  LayoutBox* new_row = CreateTableRow(parent.GetDocument(), *new_style, legacy);
-  new_row->SetDocumentForAnonymous(&parent.GetDocument());
-  new_row->SetStyle(std::move(new_style));
-  return new_row;
-}
-
-LayoutBlockFlow* LayoutObjectFactory::CreateAnonymousTableCellWithParent(
-    const LayoutObject& parent) {
-  scoped_refptr<const ComputedStyle> new_style =
-      parent.GetDocument().GetStyleResolver().CreateAnonymousStyleWithDisplay(
-          parent.StyleRef(), EDisplay::kTableCell);
-  LegacyLayout legacy = parent.ForceLegacyLayoutForChildren()
-                            ? LegacyLayout::kForce
-                            : LegacyLayout::kAuto;
-  LayoutBlockFlow* new_cell =
-      CreateTableCell(parent.GetDocument(), *new_style, legacy);
-  new_cell->SetDocumentForAnonymous(&parent.GetDocument());
-  new_cell->SetStyle(std::move(new_style));
-  return new_cell;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_object_factory.h b/third_party/blink/renderer/core/layout/layout_object_factory.h
index 3267ad24..b02d31b3 100644
--- a/third_party/blink/renderer/core/layout/layout_object_factory.h
+++ b/third_party/blink/renderer/core/layout/layout_object_factory.h
@@ -15,18 +15,13 @@
 class CounterContentData;
 class Document;
 class HTMLElement;
-class HTMLFrameSetElement;
 class LayoutBlock;
 class LayoutBlockFlow;
 class LayoutObject;
-class LayoutBox;
 enum class LegacyLayout;
 class LayoutProgress;
-class LayoutRubyAsBlock;
-class LayoutTableCaption;
 class LayoutText;
 class LayoutTextFragment;
-class LayoutView;
 class Node;
 class PseudoElement;
 
@@ -45,34 +40,12 @@
   static LayoutBlockFlow* CreateBlockFlow(Node&,
                                           const ComputedStyle&,
                                           LegacyLayout);
-  static LayoutView* CreateView(Document&, const ComputedStyle&);
-  static LayoutBlock* CreateMath(Node&, const ComputedStyle&, LegacyLayout);
-  static LayoutBlock* CreateCustom(Node&, const ComputedStyle&, LegacyLayout);
   static LayoutObject* CreateListMarker(Node&,
                                         const ComputedStyle&,
                                         LegacyLayout);
-  static LayoutBlock* CreateTable(Node&, const ComputedStyle&, LegacyLayout);
-  static LayoutTableCaption* CreateTableCaption(Node&,
-                                                const ComputedStyle&,
-                                                LegacyLayout);
-  static LayoutBlockFlow* CreateTableCell(Node&,
-                                          const ComputedStyle&,
-                                          LegacyLayout);
-  static LayoutBox* CreateTableColumn(Node&,
-                                      const ComputedStyle&,
-                                      LegacyLayout);
-
-  static LayoutBox* CreateTableRow(Node&, const ComputedStyle&, LegacyLayout);
-  static LayoutBox* CreateTableSection(Node&,
-                                       const ComputedStyle&,
-                                       LegacyLayout);
-
   static LayoutObject* CreateCounter(PseudoElement& pseduo,
                                      const CounterContentData& counter,
                                      LegacyLayout legacy);
-  static LayoutBox* CreateFrameSet(HTMLFrameSetElement& element,
-                                   const ComputedStyle& style,
-                                   LegacyLayout legacy);
 
   static LayoutText* CreateText(Node*, String, LegacyLayout);
   static LayoutText* CreateTextCombine(Node*, String, LegacyLayout);
@@ -84,32 +57,9 @@
   static LayoutProgress* CreateProgress(Node* node,
                                         const ComputedStyle& style,
                                         LegacyLayout legacy);
-  static LayoutRubyAsBlock* CreateRubyAsBlock(Node* node,
-                                              const ComputedStyle& style,
-                                              LegacyLayout legacy);
-  static LayoutObject* CreateRubyText(Node* node,
-                                      const ComputedStyle& style,
-                                      LegacyLayout legacy);
 
   static LayoutObject* CreateBR(Node*, LegacyLayout);
   static LayoutObject* CreateWordBreak(HTMLElement*, LegacyLayout);
-
-  // Anonymous creation methods
-
-  // |child_forces_legacy| true if creating parents boxes for legacy child.
-  // Table must match child's type.
-  static LayoutBox* CreateAnonymousTableWithParent(
-      const LayoutObject& parent,
-      bool child_forces_legacy = false);
-
-  static LayoutBox* CreateAnonymousTableSectionWithParent(
-      const LayoutObject& parent);
-
-  static LayoutBox* CreateAnonymousTableRowWithParent(
-      const LayoutObject& parent);
-
-  static LayoutBlockFlow* CreateAnonymousTableCellWithParent(
-      const LayoutObject& parent);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_ruby.cc b/third_party/blink/renderer/core/layout/layout_ruby.cc
index 8315c34..6a65508 100644
--- a/third_party/blink/renderer/core/layout/layout_ruby.cc
+++ b/third_party/blink/renderer/core/layout/layout_ruby.cc
@@ -31,21 +31,23 @@
 #include "third_party/blink/renderer/core/layout/layout_ruby.h"
 
 #include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 
 namespace blink {
 
 // === generic helper functions to avoid excessive code duplication ===
 
-static LayoutRubyRun* LastRubyRun(const LayoutObject* ruby) {
-  return To<LayoutRubyRun>(ruby->SlowLastChild());
+// static
+LayoutNGRubyRun* LayoutRubyAsInline::LastRubyRun(const LayoutObject& ruby) {
+  return To<LayoutNGRubyRun>(ruby.SlowLastChild());
 }
 
-static inline LayoutRubyRun* FindRubyRunParent(LayoutObject* child) {
+// static
+LayoutNGRubyRun* LayoutRubyAsInline::FindRubyRunParent(LayoutObject* child) {
   while (child && !child->IsRubyRun())
     child = child->Parent();
-  return To<LayoutRubyRun>(child);
+  return To<LayoutNGRubyRun>(child);
 }
 
 // === ruby as inline object ===
@@ -80,7 +82,7 @@
       run = run->Parent();
     if (run) {
       if (before_child == run)
-        before_child = To<LayoutRubyRun>(before_child)->FirstChild();
+        before_child = To<LayoutNGRubyRun>(before_child)->FirstChild();
       DCHECK(!before_child || before_child->IsDescendantOf(run));
       run->AddChild(child, before_child);
       return;
@@ -92,9 +94,9 @@
   // If the new child would be appended, try to add the child to the previous
   // run if possible, or create a new run otherwise.
   // (The LayoutRubyRun object will handle the details)
-  LayoutRubyRun* last_run = LastRubyRun(this);
+  auto* last_run = LastRubyRun(*this);
   if (!last_run || last_run->HasRubyText()) {
-    last_run = &LayoutRubyRun::Create(this, *ContainingBlock());
+    last_run = &LayoutNGRubyRun::Create(this, *ContainingBlock());
     LayoutInline::AddChild(last_run, before_child);
     last_run->EnsureRubyBase();
   }
@@ -112,76 +114,7 @@
   }
 
   // Otherwise find the containing run and remove it from there.
-  LayoutRubyRun* run = FindRubyRunParent(child);
-  DCHECK(run);
-  run->RemoveChild(child);
-}
-
-// === ruby as block object ===
-
-LayoutRubyAsBlock::LayoutRubyAsBlock(ContainerNode* node)
-    : LayoutBlockFlow(node) {
-  UseCounter::Count(GetDocument(), WebFeature::kRenderRuby);
-}
-
-LayoutRubyAsBlock::~LayoutRubyAsBlock() = default;
-
-void LayoutRubyAsBlock::StyleDidChange(StyleDifference diff,
-                                       const ComputedStyle* old_style) {
-  NOT_DESTROYED();
-  LayoutBlockFlow::StyleDidChange(diff, old_style);
-  PropagateStyleToAnonymousChildren();
-}
-
-void LayoutRubyAsBlock::AddChild(LayoutObject* child,
-                                 LayoutObject* before_child) {
-  NOT_DESTROYED();
-  // If the child is a ruby run, just add it normally.
-  if (child->IsRubyRun()) {
-    LayoutBlockFlow::AddChild(child, before_child);
-    return;
-  }
-
-  if (before_child) {
-    // insert child into run
-    LayoutObject* run = before_child;
-    while (run && !run->IsRubyRun())
-      run = run->Parent();
-    if (run) {
-      if (before_child == run)
-        before_child = To<LayoutRubyRun>(before_child)->FirstChild();
-      DCHECK(!before_child || before_child->IsDescendantOf(run));
-      run->AddChild(child, before_child);
-      return;
-    }
-    NOTREACHED();  // before_child should always have a run as parent!
-                   // Emergency fallback: fall through and just append.
-  }
-
-  // If the new child would be appended, try to add the child to the previous
-  // run if possible, or create a new run otherwise.
-  // (The LayoutRubyRun object will handle the details)
-  LayoutRubyRun* last_run = LastRubyRun(this);
-  if (!last_run || last_run->HasRubyText()) {
-    last_run = &LayoutRubyRun::Create(this, *this);
-    LayoutBlockFlow::AddChild(last_run, before_child);
-    last_run->EnsureRubyBase();
-  }
-  last_run->AddChild(child);
-}
-
-void LayoutRubyAsBlock::RemoveChild(LayoutObject* child) {
-  NOT_DESTROYED();
-  // If the child's parent is *this (must be a ruby run), just use the normal
-  // remove method.
-  if (child->Parent() == this) {
-    DCHECK(child->IsRubyRun());
-    LayoutBlockFlow::RemoveChild(child);
-    return;
-  }
-
-  // Otherwise find the containing run and remove it from there.
-  LayoutRubyRun* run = FindRubyRunParent(child);
+  auto* run = FindRubyRunParent(child);
   DCHECK(run);
   run->RemoveChild(child);
 }
diff --git a/third_party/blink/renderer/core/layout/layout_ruby.h b/third_party/blink/renderer/core/layout/layout_ruby.h
index 98fda66..6327b52 100644
--- a/third_party/blink/renderer/core/layout/layout_ruby.h
+++ b/third_party/blink/renderer/core/layout/layout_ruby.h
@@ -31,12 +31,12 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_H_
 
-#include "base/notreached.h"
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
 #include "third_party/blink/renderer/core/layout/layout_inline.h"
 
 namespace blink {
 
+class LayoutNGRubyRun;
+
 // Following the HTML 5 spec, the box object model for a <ruby> element allows
 // several runs of ruby
 // bases with their respective ruby texts looks as follows:
@@ -70,6 +70,9 @@
     return "LayoutRuby (inline)";
   }
 
+  static LayoutNGRubyRun* LastRubyRun(const LayoutObject& ruby);
+  static LayoutNGRubyRun* FindRubyRunParent(LayoutObject* child);
+
  protected:
   void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
 
@@ -84,39 +87,6 @@
   }
 };
 
-// <ruby> when used as 'display:block' or 'display:inline-block'
-class LayoutRubyAsBlock : public LayoutBlockFlow {
- public:
-  LayoutRubyAsBlock(ContainerNode*);
-  ~LayoutRubyAsBlock() override;
-
-  void AddChild(LayoutObject* child,
-                LayoutObject* before_child = nullptr) override;
-  void RemoveChild(LayoutObject* child) override;
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutRuby (block)";
-  }
-
- protected:
-  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectRuby || LayoutBlockFlow::IsOfType(type);
-  }
-
- private:
-  bool CreatesAnonymousWrapper() const override {
-    NOT_DESTROYED();
-    return true;
-  }
-  void RemoveLeftoverAnonymousBlock(LayoutBlock*) override {
-    NOT_DESTROYED();
-    NOTREACHED();
-  }
-};
-
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_H_
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_base.cc b/third_party/blink/renderer/core/layout/layout_ruby_base.cc
deleted file mode 100644
index e7b47f9..0000000
--- a/third_party/blink/renderer/core/layout/layout_ruby_base.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
-
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h"
-
-namespace blink {
-
-LayoutRubyBase::LayoutRubyBase(ContainerNode* node) : LayoutBlockFlow(nullptr) {
-  DCHECK(!node);
-  SetInline(false);
-}
-
-LayoutRubyBase::~LayoutRubyBase() = default;
-
-LayoutRubyBase* LayoutRubyBase::CreateAnonymous(Document* document,
-                                                const LayoutRubyRun& ruby_run) {
-  LayoutRubyBase* layout_object;
-  if (ruby_run.IsLayoutNGObject()) {
-    layout_object = MakeGarbageCollected<LayoutNGRubyBase>();
-  } else {
-    layout_object = MakeGarbageCollected<LayoutRubyBase>(nullptr);
-  }
-  layout_object->SetDocumentForAnonymous(document);
-  return layout_object;
-}
-
-bool LayoutRubyBase::IsChildAllowed(LayoutObject* child,
-                                    const ComputedStyle&) const {
-  NOT_DESTROYED();
-  return child->IsInline();
-}
-
-// This function removes all children that are before (!) before_child
-// and appends them to to_base.
-void LayoutRubyBase::MoveChildren(LayoutRubyBase& to_base,
-                                  LayoutObject* before_child) {
-  NOT_DESTROYED();
-  // Callers should have handled the percent height descendant map.
-  DCHECK(!HasPercentHeightDescendants());
-
-  if (before_child && before_child->Parent() != this)
-    before_child = SplitAnonymousBoxesAroundChild(before_child);
-
-  if (ChildrenInline())
-    MoveInlineChildren(to_base, before_child);
-  else
-    MoveBlockChildren(to_base, before_child);
-
-  SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
-      layout_invalidation_reason::kUnknown);
-  to_base.SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
-      layout_invalidation_reason::kUnknown);
-}
-
-void LayoutRubyBase::MoveInlineChildren(LayoutRubyBase& to_base,
-                                        LayoutObject* before_child) {
-  NOT_DESTROYED();
-  DCHECK(ChildrenInline());
-
-  if (!FirstChild())
-    return;
-
-  LayoutBlock* to_block;
-  if (to_base.ChildrenInline()) {
-    // The standard and easy case: move the children into the target base
-    to_block = &to_base;
-  } else {
-    // We need to wrap the inline objects into an anonymous block.
-    // If toBase has a suitable block, we re-use it, otherwise create a new one.
-    LayoutObject* last_child = to_base.LastChild();
-    if (last_child && last_child->IsAnonymousBlock() &&
-        last_child->ChildrenInline()) {
-      to_block = To<LayoutBlock>(last_child);
-    } else {
-      to_block = to_base.CreateAnonymousBlock();
-      to_base.Children()->AppendChildNode(&to_base, to_block);
-    }
-  }
-  // Move our inline children into the target block we determined above.
-  MoveChildrenTo(to_block, FirstChild(), before_child);
-}
-
-void LayoutRubyBase::MoveBlockChildren(LayoutRubyBase& to_base,
-                                       LayoutObject* before_child) {
-  NOT_DESTROYED();
-  DCHECK(!ChildrenInline());
-
-  if (!FirstChild())
-    return;
-
-  if (to_base.ChildrenInline())
-    to_base.MakeChildrenNonInline();
-
-  // If an anonymous block would be put next to another such block, then merge
-  // those.
-  LayoutObject* first_child_here = FirstChild();
-  LayoutObject* last_child_there = to_base.LastChild();
-  if (first_child_here->IsAnonymousBlock() &&
-      first_child_here->ChildrenInline() && last_child_there &&
-      last_child_there->IsAnonymousBlock() &&
-      last_child_there->ChildrenInline()) {
-    auto* anon_block_here = To<LayoutBlockFlow>(first_child_here);
-    auto* anon_block_there = To<LayoutBlockFlow>(last_child_there);
-    anon_block_here->MoveAllChildrenTo(anon_block_there,
-                                       anon_block_there->Children());
-    anon_block_here->DeleteLineBoxTree();
-    anon_block_here->Destroy();
-  }
-  // Move all remaining children normally. If moving all children, include our
-  // float list.
-  if (!before_child) {
-    bool full_remove_insert = to_base.HasLayer() || HasLayer();
-    // TODO(kojii): |this| is |!ChildrenInline()| when we enter this function,
-    // but it may turn to |ChildrenInline()| when |anon_block_here| is destroyed
-    // above. Probably the correct fix is to do it earlier and switch to
-    // |MoveInlineChildren()| if this happens. For the short term safe fix,
-    // using |full_remove_insert| can prevent inconsistent LayoutObject tree
-    // that leads to CHECK failures.
-    full_remove_insert |= ChildrenInline();
-    MoveAllChildrenIncludingFloatsTo(&to_base, full_remove_insert);
-  } else {
-    MoveChildrenTo(&to_base, FirstChild(), before_child);
-    RemoveFloatingObjectsFromDescendants();
-  }
-}
-
-ETextAlign LayoutRubyBase::TextAlignmentForLine(
-    bool /* endsWithSoftBreak */) const {
-  return ETextAlign::kJustify;
-}
-
-void LayoutRubyBase::AdjustInlineDirectionLineBounds(
-    unsigned expansion_opportunity_count,
-    LayoutUnit& logical_left,
-    LayoutUnit& logical_width) const {
-  NOT_DESTROYED();
-  int max_preferred_logical_width = PreferredLogicalWidths().max_size.ToInt();
-  if (max_preferred_logical_width >= logical_width)
-    return;
-
-  unsigned max_count = static_cast<unsigned>(LayoutUnit::Max().Floor());
-  if (expansion_opportunity_count > max_count)
-    expansion_opportunity_count = max_count;
-
-  // Inset the ruby base by half the inter-ideograph expansion amount.
-  LayoutUnit inset = (logical_width - max_preferred_logical_width) /
-                     (expansion_opportunity_count + 1);
-
-  logical_left += inset / 2;
-  logical_width -= inset;
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_base.h b/third_party/blink/renderer/core/layout/layout_ruby_base.h
deleted file mode 100644
index 869f2f4..0000000
--- a/third_party/blink/renderer/core/layout/layout_ruby_base.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_BASE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_BASE_H_
-
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
-
-namespace blink {
-
-class LayoutRubyRun;
-template <typename Base>
-class LayoutNGMixin;
-
-class LayoutRubyBase : public LayoutBlockFlow {
- public:
-  ~LayoutRubyBase() override;
-  static LayoutRubyBase* CreateAnonymous(Document*,
-                                         const LayoutRubyRun& ruby_run);
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutRubyBase";
-  }
-
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectRubyBase || LayoutBlockFlow::IsOfType(type);
-  }
-
-  bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
-
-  // The argument must be nullptr. It's necessary for the LayoutNGMixin
-  // constructor.
-  explicit LayoutRubyBase(ContainerNode*);
-
- private:
-  ETextAlign TextAlignmentForLine(bool ends_with_soft_break) const override;
-  void AdjustInlineDirectionLineBounds(
-      unsigned expansion_opportunity_count,
-      LayoutUnit& logical_left,
-      LayoutUnit& logical_width) const override;
-
-  void MoveChildren(LayoutRubyBase& to_base,
-                    LayoutObject* before_child = nullptr);
-  void MoveInlineChildren(LayoutRubyBase& to_base,
-                          LayoutObject* before_child = nullptr);
-  void MoveBlockChildren(LayoutRubyBase& to_base,
-                         LayoutObject* before_child = nullptr);
-
-  friend class LayoutNGMixin<LayoutRubyBase>;
-  // Allow LayoutRubyRun to manipulate the children within ruby bases.
-  friend class LayoutRubyRun;
-};
-
-template <>
-struct DowncastTraits<LayoutRubyBase> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsRubyBase();
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_BASE_H_
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_run.cc b/third_party/blink/renderer/core/layout/layout_ruby_run.cc
deleted file mode 100644
index 9a930c1a..0000000
--- a/third_party/blink/renderer/core/layout/layout_ruby_run.cc
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
-
-#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
-#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
-#include "third_party/blink/renderer/core/layout/layout_text.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
-
-namespace blink {
-
-LayoutRubyRun::LayoutRubyRun(ContainerNode* node) : LayoutBlockFlow(nullptr) {
-  DCHECK(!node);
-  SetInline(true);
-  SetIsAtomicInlineLevel(true);
-}
-
-LayoutRubyRun::~LayoutRubyRun() = default;
-
-bool LayoutRubyRun::HasRubyText() const {
-  NOT_DESTROYED();
-  // The only place where a ruby text can be is in the first position
-  // Note: As anonymous blocks, ruby runs do not have ':before' or ':after'
-  // content themselves.
-  return FirstChild() && FirstChild()->IsRubyText();
-}
-
-bool LayoutRubyRun::HasRubyBase() const {
-  NOT_DESTROYED();
-  // The only place where a ruby base can be is in the last position
-  // Note: As anonymous blocks, ruby runs do not have ':before' or ':after'
-  // content themselves.
-  return LastChild() && LastChild()->IsRubyBase();
-}
-
-LayoutRubyText* LayoutRubyRun::RubyText() const {
-  NOT_DESTROYED();
-  LayoutObject* child = FirstChild();
-  // If in future it becomes necessary to support floating or positioned ruby
-  // text, layout will have to be changed to handle them properly.
-  DCHECK(!child || !child->IsRubyText() ||
-         !child->IsFloatingOrOutOfFlowPositioned());
-  return DynamicTo<LayoutRubyText>(child);
-}
-
-LayoutRubyBase* LayoutRubyRun::RubyBase() const {
-  NOT_DESTROYED();
-  return DynamicTo<LayoutRubyBase>(LastChild());
-}
-
-LayoutRubyBase& LayoutRubyRun::EnsureRubyBase() {
-  NOT_DESTROYED();
-  if (auto* base = RubyBase())
-    return *base;
-  auto& new_base = CreateRubyBase();
-  LayoutBlockFlow::AddChild(&new_base);
-  return new_base;
-}
-
-bool LayoutRubyRun::IsChildAllowed(LayoutObject* child,
-                                   const ComputedStyle&) const {
-  NOT_DESTROYED();
-  return child->IsRubyText() || child->IsInline();
-}
-
-void LayoutRubyRun::AddChild(LayoutObject* child, LayoutObject* before_child) {
-  NOT_DESTROYED();
-  DCHECK(child);
-
-  if (child->IsRubyText()) {
-    if (!before_child) {
-      // LayoutRuby has already ascertained that we can add the child here.
-      DCHECK(!HasRubyText());
-      // prepend ruby texts as first child
-      LayoutBlockFlow::AddChild(child, FirstChild());
-    } else if (before_child->IsRubyText()) {
-      // New text is inserted just before another.
-      // In this case the new text takes the place of the old one, and
-      // the old text goes into a new run that is inserted as next sibling.
-      DCHECK_EQ(before_child->Parent(), this);
-      LayoutObject* ruby = Parent();
-      DCHECK(ruby->IsRuby());
-      auto& new_run = Create(ruby, *ContainingBlock());
-      ruby->AddChild(&new_run, NextSibling());
-      new_run.EnsureRubyBase();
-      // Add the new ruby text and move the old one to the new run
-      // Note: Doing it in this order and not using LayoutRubyRun's methods,
-      // in order to avoid automatic removal of the ruby run in case there is no
-      // other child besides the old ruby text.
-      LayoutBlockFlow::AddChild(child, before_child);
-      LayoutBlockFlow::RemoveChild(before_child);
-      new_run.AddChild(before_child);
-    } else if (RubyBase()->FirstChild()) {
-      // Insertion before a ruby base object.
-      // In this case we need insert a new run before the current one and split
-      // the base.
-      LayoutObject* ruby = Parent();
-      LayoutRubyRun& new_run = Create(ruby, *ContainingBlock());
-      ruby->AddChild(&new_run, this);
-      auto& new_base = new_run.EnsureRubyBase();
-      new_run.AddChild(child);
-
-      // Make sure we don't leave anything in the percentage descendant
-      // map before moving the children to the new base.
-      LayoutRubyBase& base = EnsureRubyBase();
-      if (HasPercentHeightDescendants() || base.HasPercentHeightDescendants()) {
-        ClearPercentHeightDescendants();
-      }
-      base.MoveChildren(new_base, before_child);
-    }
-  } else {
-    // child is not a text -> insert it into the base
-    // (append it instead if beforeChild is the ruby text)
-    LayoutRubyBase& base = EnsureRubyBase();
-    if (before_child == &base)
-      before_child = base.FirstChild();
-    if (before_child && before_child->IsRubyText())
-      before_child = nullptr;
-    DCHECK(!before_child || before_child->IsDescendantOf(&base));
-    base.AddChild(child, before_child);
-  }
-}
-
-void LayoutRubyRun::RemoveChild(LayoutObject* child) {
-  NOT_DESTROYED();
-  // If the child is a ruby text, then merge the ruby base with the base of
-  // the right sibling run, if possible.
-  if (!BeingDestroyed() && !DocumentBeingDestroyed() && child->IsRubyText()) {
-    LayoutRubyBase* base = RubyBase();
-    LayoutObject* right_neighbour = NextSibling();
-    if (base->FirstChild() && right_neighbour && right_neighbour->IsRubyRun()) {
-      auto* right_run = To<LayoutRubyRun>(right_neighbour);
-      LayoutRubyBase& right_base = right_run->EnsureRubyBase();
-      if (right_base.FirstChild()) {
-        // Collect all children in a single base, then swap the bases.
-        if (right_base.HasPercentHeightDescendants()) {
-          right_base.ClearPercentHeightDescendants();
-        }
-        right_base.MoveChildren(*base);
-        MoveChildTo(right_run, base);
-        right_run->MoveChildTo(this, &right_base);
-        DCHECK(!RubyBase()->FirstChild());
-      }
-    }
-  }
-
-  LayoutBlockFlow::RemoveChild(child);
-
-  if (!BeingDestroyed() && !DocumentBeingDestroyed()) {
-    // If this has only an empty LayoutRubyBase, destroy this sub-tree.
-    LayoutBlockFlow* base = RubyBase();
-    if (!HasRubyText() && !base->FirstChild()) {
-      LayoutBlockFlow::RemoveChild(base);
-      base->DeleteLineBoxTree();
-      base->Destroy();
-      DeleteLineBoxTree();
-      Destroy();
-    }
-  }
-}
-
-LayoutRubyBase& LayoutRubyRun::CreateRubyBase() const {
-  NOT_DESTROYED();
-  auto* layout_object = LayoutRubyBase::CreateAnonymous(&GetDocument(), *this);
-  ComputedStyleBuilder new_style_builder =
-      GetDocument().GetStyleResolver().CreateAnonymousStyleBuilderWithDisplay(
-          StyleRef(), EDisplay::kBlock);
-  new_style_builder.SetTextAlign(
-      ETextAlign::kCenter);  // FIXME: use WEBKIT_CENTER?
-  new_style_builder.SetHasLineIfEmpty(true);
-  layout_object->SetStyle(new_style_builder.TakeStyle());
-  return *layout_object;
-}
-
-// static
-LayoutRubyRun& LayoutRubyRun::Create(const LayoutObject* parent_ruby,
-                                     const LayoutBlock& containing_block) {
-  DCHECK(parent_ruby);
-  DCHECK(parent_ruby->IsRuby());
-  LayoutRubyRun* rr;
-  if (containing_block.IsLayoutNGObject()) {
-    rr = MakeGarbageCollected<LayoutNGRubyRun>();
-  } else {
-    rr = MakeGarbageCollected<LayoutRubyRun>(nullptr);
-  }
-  rr->SetDocumentForAnonymous(&parent_ruby->GetDocument());
-  scoped_refptr<const ComputedStyle> new_style =
-      parent_ruby->GetDocument()
-          .GetStyleResolver()
-          .CreateAnonymousStyleWithDisplay(parent_ruby->StyleRef(),
-                                           EDisplay::kInlineBlock);
-  rr->SetStyle(std::move(new_style));
-  return *rr;
-}
-
-LayoutObject* LayoutRubyRun::LayoutSpecialExcludedChild(
-    bool relayout_children,
-    SubtreeLayoutScope& layout_scope) {
-  NOT_DESTROYED();
-  // Don't bother positioning the LayoutRubyRun yet.
-  LayoutRubyText* rt = RubyText();
-  if (!rt)
-    return nullptr;
-  if (relayout_children)
-    layout_scope.SetChildNeedsLayout(rt);
-  rt->LayoutIfNeeded();
-  return rt;
-}
-
-void LayoutRubyRun::UpdateLayout() {
-  NOT_DESTROYED();
-  LayoutBlockFlow::UpdateLayout();
-
-  LayoutRubyText* rt = RubyText();
-  if (!rt)
-    return;
-
-  rt->SetLogicalLeft(LayoutUnit());
-
-  // Place the LayoutRubyText such that its bottom is flush with the lineTop of
-  // the first line of the LayoutRubyBase.
-  LayoutUnit last_line_ruby_text_bottom = rt->LogicalHeight();
-  LayoutUnit first_line_ruby_text_top;
-  if (RootInlineBox* root_box = rt->LastRootBox()) {
-    // In order to align, we have to ignore negative leading.
-    first_line_ruby_text_top = rt->FirstRootBox()->LogicalTopLayoutOverflow();
-    last_line_ruby_text_bottom = root_box->LogicalBottomLayoutOverflow();
-  }
-
-  RubyPosition block_start_position = StyleRef().IsFlippedLinesWritingMode()
-                                          ? RubyPosition::kAfter
-                                          : RubyPosition::kBefore;
-  if (StyleRef().GetRubyPosition() == block_start_position) {
-    LayoutUnit first_line_top;
-    if (LayoutRubyBase* rb = RubyBase()) {
-      RootInlineBox* root_box = rb->FirstRootBox();
-      if (root_box)
-        first_line_top = root_box->LogicalTopLayoutOverflow();
-      first_line_top += rb->LogicalTop();
-    }
-
-    rt->SetLogicalTop(-last_line_ruby_text_bottom + first_line_top);
-  } else {
-    LayoutUnit last_line_bottom = LogicalHeight();
-    if (LayoutRubyBase* rb = RubyBase()) {
-      RootInlineBox* root_box = rb->LastRootBox();
-      if (root_box)
-        last_line_bottom = root_box->LogicalBottomLayoutOverflow();
-      last_line_bottom += rb->LogicalTop();
-    }
-
-    rt->SetLogicalTop(-first_line_ruby_text_top + last_line_bottom);
-  }
-
-  // Update our overflow to account for the new LayoutRubyText position.
-  ComputeLayoutOverflow(ClientLogicalBottom());
-}
-
-void LayoutRubyRun::GetOverhang(bool first_line,
-                                LayoutObject* start_layout_object,
-                                LayoutObject* end_layout_object,
-                                int& start_overhang,
-                                int& end_overhang) const {
-  NOT_DESTROYED();
-  DCHECK(!NeedsLayout());
-
-  start_overhang = 0;
-  end_overhang = 0;
-
-  LayoutRubyBase* ruby_base = RubyBase();
-  LayoutRubyText* ruby_text = RubyText();
-
-  if (!ruby_base || !ruby_text)
-    return;
-
-  if (!ruby_base->FirstRootBox())
-    return;
-
-  int logical_width = LogicalWidth().ToInt();
-  int logical_left_overhang = std::numeric_limits<int>::max();
-  int logical_right_overhang = std::numeric_limits<int>::max();
-  for (RootInlineBox* root_inline_box = ruby_base->FirstRootBox();
-       root_inline_box; root_inline_box = root_inline_box->NextRootBox()) {
-    logical_left_overhang = std::min<int>(
-        logical_left_overhang, root_inline_box->LogicalLeft().ToInt());
-    logical_right_overhang = std::min<int>(
-        logical_right_overhang,
-        (logical_width - root_inline_box->LogicalRight()).ToInt());
-  }
-
-  start_overhang = StyleRef().IsLeftToRightDirection() ? logical_left_overhang
-                                                       : logical_right_overhang;
-  end_overhang = StyleRef().IsLeftToRightDirection() ? logical_right_overhang
-                                                     : logical_left_overhang;
-
-  if (!start_layout_object || !start_layout_object->IsText() ||
-      start_layout_object->Style(first_line)->FontSize() >
-          ruby_base->Style(first_line)->FontSize())
-    start_overhang = 0;
-
-  if (!end_layout_object || !end_layout_object->IsText() ||
-      end_layout_object->Style(first_line)->FontSize() >
-          ruby_base->Style(first_line)->FontSize())
-    end_overhang = 0;
-
-  // We overhang a ruby only if the neighboring layout object is a text.
-  // We can overhang the ruby by no more than half the width of the neighboring
-  // text and no more than half the font size.
-  int half_width_of_font_size = ruby_text->Style(first_line)->FontSize() / 2;
-  if (start_overhang)
-    start_overhang = std::min<int>(
-        start_overhang,
-        std::min<int>(To<LayoutText>(start_layout_object)->MinLogicalWidth(),
-                      half_width_of_font_size));
-  if (end_overhang)
-    end_overhang = std::min<int>(
-        end_overhang,
-        std::min<int>(To<LayoutText>(end_layout_object)->MinLogicalWidth(),
-                      half_width_of_font_size));
-}
-
-bool LayoutRubyRun::CanBreakBefore(
-    const LazyLineBreakIterator& iterator) const {
-  NOT_DESTROYED();
-  // TODO(kojii): It would be nice to improve this so that it isn't just
-  // hard-coded, but lookahead in this case is particularly problematic.
-  // See crbug.com/522826.
-
-  if (!iterator.PriorContextLength())
-    return true;
-  UChar ch = iterator.LastCharacter();
-  ULineBreak line_break =
-      static_cast<ULineBreak>(u_getIntPropertyValue(ch, UCHAR_LINE_BREAK));
-  // UNICODE LINE BREAKING ALGORITHM
-  // http://www.unicode.org/reports/tr14/
-  // And Requirements for Japanese Text Layout, 3.1.7 Characters Not Starting a
-  // Line
-  // http://www.w3.org/TR/2012/NOTE-jlreq-20120403/#characters_not_starting_a_line
-  switch (line_break) {
-    case U_LB_WORD_JOINER:
-    case U_LB_GLUE:
-    case U_LB_OPEN_PUNCTUATION:
-      return false;
-    default:
-      break;
-  }
-  return true;
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_run.h b/third_party/blink/renderer/core/layout/layout_ruby_run.h
deleted file mode 100644
index 0f05ba4..0000000
--- a/third_party/blink/renderer/core/layout/layout_ruby_run.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_RUN_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_RUN_H_
-
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
-#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
-
-namespace blink {
-
-class LayoutRubyBase;
-class LayoutRubyText;
-template <typename Base>
-class LayoutNGMixin;
-
-// LayoutRubyRun are 'inline-block/table' like objects,and wrap a single pairing
-// of a ruby base with its ruby text(s).
-// See layout_ruby.h for further comments on the structure
-
-class LayoutRubyRun : public LayoutBlockFlow {
- public:
-  // The argument must be nullptr.
-  explicit LayoutRubyRun(ContainerNode*);
-  static LayoutRubyRun& Create(const LayoutObject* parent_ruby,
-                               const LayoutBlock& containing_block);
-  ~LayoutRubyRun() override;
-
-  bool HasRubyText() const;
-  bool HasRubyBase() const;
-  LayoutRubyText* RubyText() const;
-  LayoutRubyBase* RubyBase() const;
-  // Creates the base if it doesn't already exist
-  LayoutRubyBase& EnsureRubyBase();
-
-  LayoutObject* LayoutSpecialExcludedChild(bool relayout_children,
-                                           SubtreeLayoutScope&) override;
-  void UpdateLayout() override;
-
-  bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
-  void AddChild(LayoutObject* child,
-                LayoutObject* before_child = nullptr) override;
-  void RemoveChild(LayoutObject* child) override;
-
-  void GetOverhang(bool first_line,
-                   LayoutObject* start_layout_object,
-                   LayoutObject* end_layout_object,
-                   int& start_overhang,
-                   int& end_overhang) const;
-
-  bool CanBreakBefore(const LazyLineBreakIterator&) const;
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutRubyRun";
-  }
-
- protected:
-  LayoutRubyBase& CreateRubyBase() const;
-
- private:
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectRubyRun || LayoutBlockFlow::IsOfType(type);
-  }
-  bool CreatesAnonymousWrapper() const override {
-    NOT_DESTROYED();
-    return true;
-  }
-  void RemoveLeftoverAnonymousBlock(LayoutBlock*) override { NOT_DESTROYED(); }
-
-  friend class LayoutNGMixin<LayoutRubyRun>;
-};
-
-template <>
-struct DowncastTraits<LayoutRubyRun> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsRubyRun();
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_RUN_H_
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_text.cc b/third_party/blink/renderer/core/layout/layout_ruby_text.cc
deleted file mode 100644
index 143333d..0000000
--- a/third_party/blink/renderer/core/layout/layout_ruby_text.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- * Copyright (C) 2011 Apple 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.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
-
-#include "third_party/blink/renderer/core/frame/web_feature.h"
-
-namespace blink {
-
-LayoutRubyText::LayoutRubyText(ContainerNode* node) : LayoutBlockFlow(node) {}
-
-LayoutRubyText::~LayoutRubyText() = default;
-
-bool LayoutRubyText::IsChildAllowed(LayoutObject* child,
-                                    const ComputedStyle&) const {
-  NOT_DESTROYED();
-  return child->IsInline();
-}
-
-void LayoutRubyText::StyleDidChange(StyleDifference diff,
-                                    const ComputedStyle* old_style) {
-  NOT_DESTROYED();
-  if (StyleRef().GetTextAlign() !=
-      ComputedStyleInitialValues::InitialTextAlign()) {
-    UseCounter::Count(GetDocument(),
-                      WebFeature::kRubyTextWithNonDefaultTextAlign);
-  }
-  LayoutBlockFlow::StyleDidChange(diff, old_style);
-}
-
-ETextAlign LayoutRubyText::TextAlignmentForLine(
-    bool ends_with_soft_break) const {
-  NOT_DESTROYED();
-  ETextAlign text_align = StyleRef().GetTextAlign();
-  // FIXME: This check is bogus since user can set the initial value.
-  if (text_align != ComputedStyleInitialValues::InitialTextAlign())
-    return LayoutBlockFlow::TextAlignmentForLine(ends_with_soft_break);
-
-  // The default behavior is to allow ruby text to expand if it is shorter than
-  // the ruby base.
-  return ETextAlign::kJustify;
-}
-
-void LayoutRubyText::AdjustInlineDirectionLineBounds(
-    unsigned expansion_opportunity_count,
-    LayoutUnit& logical_left,
-    LayoutUnit& logical_width) const {
-  NOT_DESTROYED();
-  ETextAlign text_align = StyleRef().GetTextAlign();
-  // FIXME: This check is bogus since user can set the initial value.
-  if (text_align != ComputedStyleInitialValues::InitialTextAlign()) {
-    return LayoutBlockFlow::AdjustInlineDirectionLineBounds(
-        expansion_opportunity_count, logical_left, logical_width);
-  }
-
-  int max_preferred_logical_width = PreferredLogicalWidths().max_size.ToInt();
-  if (max_preferred_logical_width >= logical_width)
-    return;
-
-  // Inset the ruby text by half the inter-ideograph expansion amount, but no
-  // more than a full-width ruby character on each side.
-  LayoutUnit inset = (logical_width - max_preferred_logical_width) /
-                     (expansion_opportunity_count + 1);
-  if (expansion_opportunity_count)
-    inset = std::min(LayoutUnit(2 * StyleRef().FontSize()), inset);
-
-  logical_left += inset / 2;
-  logical_width -= inset;
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_text.h b/third_party/blink/renderer/core/layout/layout_ruby_text.h
deleted file mode 100644
index 7eabec2b..0000000
--- a/third_party/blink/renderer/core/layout/layout_ruby_text.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_TEXT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_TEXT_H_
-
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
-
-namespace blink {
-
-class LayoutRubyText : public LayoutBlockFlow {
- public:
-  explicit LayoutRubyText(ContainerNode*);
-  ~LayoutRubyText() override;
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutRubyText";
-  }
-
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectRubyText || LayoutBlockFlow::IsOfType(type);
-  }
-
-  bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
-
-  void StyleDidChange(StyleDifference diff,
-                      const ComputedStyle* old_style) override;
-
-  bool CreatesNewFormattingContext() const final {
-    NOT_DESTROYED();
-    // Ruby text objects are pushed around after layout, to become flush with
-    // the associated ruby base. As such, we cannot let floats leak out from
-    // ruby text objects.
-    return true;
-  }
-
- private:
-  ETextAlign TextAlignmentForLine(bool ends_with_soft_break) const override;
-  void AdjustInlineDirectionLineBounds(
-      unsigned expansion_opportunity_count,
-      LayoutUnit& logical_left,
-      LayoutUnit& logical_width) const override;
-};
-
-template <>
-struct DowncastTraits<LayoutRubyText> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsRubyText();
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_RUBY_TEXT_H_
diff --git a/third_party/blink/renderer/core/layout/layout_table.cc b/third_party/blink/renderer/core/layout/layout_table.cc
deleted file mode 100644
index a528dc615..0000000
--- a/third_party/blink/renderer/core/layout/layout_table.cc
+++ /dev/null
@@ -1,1948 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc.
- *               All rights reserved.
- * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/html/html_table_element.h"
-#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/hit_test_result.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
-#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
-#include "third_party/blink/renderer/core/layout/table_layout_algorithm_auto.h"
-#include "third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.h"
-#include "third_party/blink/renderer/core/layout/text_autosizer.h"
-#include "third_party/blink/renderer/core/paint/box_painter.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/table_paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/table_painter.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-
-namespace blink {
-
-LayoutTable::LayoutTable(Element* element)
-    : LayoutBlock(element),
-      head_(nullptr),
-      foot_(nullptr),
-      first_body_(nullptr),
-      collapsed_borders_valid_(false),
-      has_collapsed_borders_(false),
-      needs_adjust_collapsed_border_joints_(false),
-      needs_invalidate_collapsed_borders_for_all_cells_(false),
-      collapsed_outer_borders_valid_(false),
-      is_any_column_ever_collapsed_(false),
-      has_col_elements_(false),
-      needs_section_recalc_(false),
-      column_logical_width_changed_(false),
-      column_structure_changed_(false),
-      column_layout_objects_valid_(false),
-      no_cell_colspan_at_least_(0),
-      h_spacing_(0),
-      v_spacing_(0),
-      collapsed_outer_border_start_(0),
-      collapsed_outer_border_end_(0),
-      collapsed_outer_border_before_(0),
-      collapsed_outer_border_after_(0),
-      collapsed_outer_border_start_overflow_(0),
-      collapsed_outer_border_end_overflow_(0) {
-  DCHECK(!ChildrenInline());
-  effective_column_positions_.Fill(0, 1);
-}
-
-LayoutTable::~LayoutTable() = default;
-
-void LayoutTable::Trace(Visitor* visitor) const {
-  visitor->Trace(captions_);
-  visitor->Trace(column_layout_objects_);
-  visitor->Trace(head_);
-  visitor->Trace(foot_);
-  visitor->Trace(first_body_);
-  visitor->Trace(table_layout_);
-  LayoutBlock::Trace(visitor);
-}
-
-void LayoutTable::StyleDidChange(StyleDifference diff,
-                                 const ComputedStyle* old_style) {
-  NOT_DESTROYED();
-  LayoutBlock::StyleDidChange(diff, old_style);
-
-  if (ShouldCollapseBorders())
-    SetHasNonCollapsedBorderDecoration(false);
-
-  bool old_fixed_table_layout =
-      old_style ? old_style->IsFixedTableLayout() : false;
-
-  // In the collapsed border model, there is no cell spacing.
-  h_spacing_ =
-      ShouldCollapseBorders() ? 0 : StyleRef().HorizontalBorderSpacing();
-  v_spacing_ = ShouldCollapseBorders() ? 0 : StyleRef().VerticalBorderSpacing();
-  DCHECK_GE(h_spacing_, 0);
-  DCHECK_GE(v_spacing_, 0);
-
-  if (!table_layout_ ||
-      StyleRef().IsFixedTableLayout() != old_fixed_table_layout) {
-    if (table_layout_)
-      table_layout_->WillChangeTableLayout();
-
-    // According to the CSS2 spec, you only use fixed table layout if an
-    // explicit width is specified on the table. Auto width implies auto table
-    // layout.
-    if (StyleRef().IsFixedTableLayout())
-      table_layout_ = MakeGarbageCollected<TableLayoutAlgorithmFixed>(this);
-    else
-      table_layout_ = MakeGarbageCollected<TableLayoutAlgorithmAuto>(this);
-  }
-
-  if (!old_style)
-    return;
-
-  if (old_style->BorderCollapse() != StyleRef().BorderCollapse()) {
-    InvalidateCollapsedBorders();
-  } else {
-    LayoutTableBoxComponent::InvalidateCollapsedBordersOnStyleChange(
-        *this, *this, diff, *old_style);
-  }
-
-  if (LayoutTableBoxComponent::DoCellsHaveDirtyWidth(*this, *this, diff,
-                                                     *old_style))
-    MarkAllCellsWidthsDirtyAndOrNeedsLayout(kMarkDirtyAndNeedsLayout);
-}
-
-static inline void ResetSectionPointerIfNotBefore(
-    Member<LayoutTableSection>& ptr,
-    LayoutObject* before) {
-  if (!before || !ptr)
-    return;
-  LayoutObject* o = before->PreviousSibling();
-  while (o && o != ptr)
-    o = o->PreviousSibling();
-  if (!o)
-    ptr = nullptr;
-}
-
-static inline bool NeedsTableSection(LayoutObject* object) {
-  // Return true if 'object' can't exist in an anonymous table without being
-  // wrapped in a table section box.
-  EDisplay display = object->StyleRef().Display();
-  return display != EDisplay::kTableCaption &&
-         display != EDisplay::kTableColumnGroup &&
-         display != EDisplay::kTableColumn;
-}
-
-void LayoutTable::AddChild(LayoutObject* child, LayoutObject* before_child) {
-  NOT_DESTROYED();
-  bool wrap_in_anonymous_section = !child->IsOutOfFlowPositioned();
-
-  // TODO(crbug.com/1345894): TODO(crbug.com/1341619): The |child| should never
-  // be NG, but the Container Queries crbug.com/1145970 may break the rule. When
-  // that happens, and if the |child|'s legacy/NG are not in the super/sub-class
-  // relationship, |To<>| will fail.
-  //
-  // The proper fix will be to fix callers preventing such code path, and for
-  // |LayoutTable*| to use proper legacy-only |Is*()| functions with
-  // |NOTREACHED()| where appropriate, but for now, |CHECK|s are added to
-  // prevent NG table-part children being added to legacy table-part parents.
-  //
-  // Following class is in super-/subclass relationships:
-  // - LayoutTableCaption
-  // Following classes are not:
-  // - LayoutTableCell
-  // - LayoutTableCol
-  // - LayoutTableRow
-  // - LayoutTableSection
-  if (child->IsTableCaption()) {
-    wrap_in_anonymous_section = false;
-  } else if (child->IsLayoutTableCol()) {
-    // TODO(crbug.com/1345894): See the TODO at the top of this function.
-    // |LayoutNGTableColumn| is not a subclass of |LayoutTableCol|.
-    CHECK(IsA<LayoutTableCol>(child));
-    has_col_elements_ = true;
-    wrap_in_anonymous_section = false;
-  } else if (child->IsTableSection()) {
-    // TODO(crbug.com/1345894): See the TODO at the top of this function.
-    // |LayoutNGTableSection| is not a subclass of |LayoutTableSection|.
-    CHECK(IsA<LayoutTableSection>(child));
-    switch (child->StyleRef().Display()) {
-      case EDisplay::kTableHeaderGroup:
-        ResetSectionPointerIfNotBefore(head_, before_child);
-        if (!head_) {
-          head_ = To<LayoutTableSection>(child);
-        } else {
-          ResetSectionPointerIfNotBefore(first_body_, before_child);
-          if (!first_body_)
-            first_body_ = To<LayoutTableSection>(child);
-        }
-        wrap_in_anonymous_section = false;
-        break;
-      case EDisplay::kTableFooterGroup:
-        ResetSectionPointerIfNotBefore(foot_, before_child);
-        if (!foot_) {
-          foot_ = To<LayoutTableSection>(child);
-          wrap_in_anonymous_section = false;
-          break;
-        }
-        [[fallthrough]];
-      case EDisplay::kTableRowGroup:
-        ResetSectionPointerIfNotBefore(first_body_, before_child);
-        if (!first_body_)
-          first_body_ = To<LayoutTableSection>(child);
-        wrap_in_anonymous_section = false;
-        break;
-      default:
-        NOTREACHED();
-    }
-  } else {
-    wrap_in_anonymous_section = true;
-  }
-
-  if (child->IsTableSection())
-    SetNeedsSectionRecalc();
-
-  if (!wrap_in_anonymous_section) {
-    if (before_child && before_child->Parent() != this)
-      before_child = SplitAnonymousBoxesAroundChild(before_child);
-
-    LayoutBox::AddChild(child, before_child);
-    return;
-  }
-
-  if (!before_child && LastChild() && LastChild()->IsTableSection() &&
-      LastChild()->IsAnonymous() && !LastChild()->IsBeforeContent()) {
-    LastChild()->AddChild(child);
-    return;
-  }
-
-  if (before_child && !before_child->IsAnonymous() &&
-      before_child->Parent() == this) {
-    LayoutObject* section = before_child->PreviousSibling();
-    if (section && section->IsTableSection() && section->IsAnonymous()) {
-      section->AddChild(child);
-      return;
-    }
-  }
-
-  LayoutObject* last_box = before_child;
-  while (last_box && last_box->Parent()->IsAnonymous() &&
-         !last_box->IsTableSection() && NeedsTableSection(last_box))
-    last_box = last_box->Parent();
-  if (last_box && last_box->IsAnonymous() && last_box->IsTablePart() &&
-      !IsAfterContent(last_box)) {
-    if (before_child == last_box)
-      before_child = last_box->SlowFirstChild();
-    last_box->AddChild(child, before_child);
-    return;
-  }
-
-  if (before_child && !before_child->IsTableSection() &&
-      NeedsTableSection(before_child))
-    before_child = nullptr;
-
-  LayoutBox* section =
-      LayoutObjectFactory::CreateAnonymousTableSectionWithParent(*this);
-  AddChild(section, before_child);
-  section->AddChild(child);
-}
-
-void LayoutTable::AddCaption(const LayoutTableCaption* caption) {
-  NOT_DESTROYED();
-  DCHECK_EQ(captions_.Find(caption), kNotFound);
-  captions_.push_back(const_cast<LayoutTableCaption*>(caption));
-}
-
-void LayoutTable::RemoveCaption(const LayoutTableCaption* old_caption) {
-  NOT_DESTROYED();
-  wtf_size_t index = captions_.Find(old_caption);
-  DCHECK_NE(index, kNotFound);
-  if (index == kNotFound)
-    return;
-
-  captions_.EraseAt(index);
-}
-
-void LayoutTable::InvalidateCachedColumns() {
-  NOT_DESTROYED();
-  column_layout_objects_valid_ = false;
-  column_layout_objects_.resize(0);
-}
-
-void LayoutTable::ColumnStructureChanged() {
-  NOT_DESTROYED();
-  column_structure_changed_ = true;
-  InvalidateCachedColumns();
-  // We don't really need to recompute our sections, but we do need to update
-  // our column count, whether we have a column, and possibly the logical width
-  // distribution too.
-  SetNeedsSectionRecalc();
-}
-
-void LayoutTable::AddColumn(const LayoutTableCol*) {
-  NOT_DESTROYED();
-  ColumnStructureChanged();
-}
-
-void LayoutTable::RemoveColumn(const LayoutTableCol*) {
-  NOT_DESTROYED();
-  ColumnStructureChanged();
-}
-
-LayoutNGTableSectionInterface* LayoutTable::FirstBodyInterface() const {
-  NOT_DESTROYED();
-  return FirstBody();
-}
-
-LayoutNGTableSectionInterface* LayoutTable::FirstSectionInterface() const {
-  NOT_DESTROYED();
-  return TopSection();
-}
-
-LayoutNGTableSectionInterface* LayoutTable::LastSectionInterface() const {
-  NOT_DESTROYED();
-  return BottomSection();
-}
-
-LayoutNGTableSectionInterface* LayoutTable::FirstNonEmptySectionInterface()
-    const {
-  NOT_DESTROYED();
-  return TopNonEmptySection();
-}
-
-LayoutNGTableSectionInterface* LayoutTable::NextSectionInterface(
-    const LayoutNGTableSectionInterface* section,
-    SkipEmptySectionsValue skip_empty_sections) const {
-  NOT_DESTROYED();
-  return SectionBelow(To<LayoutTableSection>(section->ToLayoutObject()),
-                      skip_empty_sections);
-}
-
-// Only used by NG.
-LayoutNGTableSectionInterface* LayoutTable::PreviousSectionInterface(
-    const LayoutNGTableSectionInterface* section,
-    SkipEmptySectionsValue skip_empty_sections) const {
-  NOT_DESTROYED();
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-LayoutNGTableSectionInterface* LayoutTable::LastNonEmptySectionInterface()
-    const {
-  NOT_DESTROYED();
-  return BottomNonEmptySection();
-}
-
-bool LayoutTable::IsLogicalWidthAuto() const {
-  NOT_DESTROYED();
-  const Length& style_logical_width = StyleRef().LogicalWidth();
-  return (!style_logical_width.IsSpecified() ||
-          !style_logical_width.IsPositive()) &&
-         !style_logical_width.IsContentOrIntrinsicOrFillAvailable();
-}
-
-void LayoutTable::UpdateLogicalWidth() {
-  NOT_DESTROYED();
-  RecalcSectionsIfNeeded();
-
-  // Recalculate the intrinsic logical widths now, rather than relying on them
-  // being lazily recalculated, via PreferredLogicalWidths() further below. We
-  // might not even get there.
-  UpdateCachedIntrinsicLogicalWidthsIfNeeded();
-
-  if (IsOutOfFlowPositioned()) {
-    LogicalExtentComputedValues computed_values;
-    ComputePositionedLogicalWidth(computed_values);
-    SetLogicalWidth(computed_values.extent_);
-    SetLogicalLeft(computed_values.position_);
-    SetMarginStart(computed_values.margins_.start_);
-    SetMarginEnd(computed_values.margins_.end_);
-  }
-
-  LayoutBlock* cb = ContainingBlock();
-
-  LayoutUnit available_logical_width = ContainingBlockLogicalWidthForContent();
-  bool has_perpendicular_containing_block =
-      cb->StyleRef().IsHorizontalWritingMode() !=
-      StyleRef().IsHorizontalWritingMode();
-  LayoutUnit container_width_in_inline_direction =
-      has_perpendicular_containing_block
-          ? PerpendicularContainingBlockLogicalHeight()
-          : available_logical_width;
-
-  MinMaxSizes preferred_logical_widths = PreferredLogicalWidths();
-
-  if (!IsLogicalWidthAuto()) {
-    SetLogicalWidth(ConvertStyleLogicalWidthToComputedWidth(
-        StyleRef().LogicalWidth(), container_width_in_inline_direction));
-  } else {
-    // Subtract out any fixed margins from our available width for auto width
-    // tables.
-    LayoutUnit margin_start = MinimumValueForLength(StyleRef().MarginStart(),
-                                                    available_logical_width);
-    LayoutUnit margin_end =
-        MinimumValueForLength(StyleRef().MarginEnd(), available_logical_width);
-    LayoutUnit margin_total = margin_start + margin_end;
-
-    LayoutUnit available_content_logical_width;
-    if (HasOverrideAvailableInlineSize()) {
-      available_content_logical_width =
-          (OverrideAvailableInlineSize() - margin_total).ClampNegativeToZero();
-    } else {
-      // Subtract out our margins to get the available content width.
-      available_content_logical_width =
-          (container_width_in_inline_direction - margin_total)
-              .ClampNegativeToZero();
-      auto* containing_block_flow = DynamicTo<LayoutBlockFlow>(cb);
-      if (ShrinkToAvoidFloats() && containing_block_flow &&
-          containing_block_flow->ContainsFloats() &&
-          !has_perpendicular_containing_block) {
-        available_content_logical_width = ShrinkLogicalWidthToAvoidFloats(
-            margin_start, margin_end, containing_block_flow);
-      }
-    }
-
-    // Ensure we aren't bigger than our available width.
-    LayoutUnit max_width = preferred_logical_widths.max_size;
-    // scaledWidthFromPercentColumns depends on m_layoutStruct in
-    // TableLayoutAlgorithmAuto, which |PreferredLogicalWidths()| fills in. So
-    // |ScaledWidthFromPercentColumns()| has to be called after
-    // |PreferredLogicalWidths()|.
-    LayoutUnit scaled_width = table_layout_->ScaledWidthFromPercentColumns() +
-                              BordersPaddingAndSpacingInRowDirection();
-    max_width = std::max(scaled_width, max_width);
-    SetLogicalWidth(LayoutUnit(
-        std::min(available_content_logical_width, max_width).Floor()));
-  }
-
-  // Ensure we aren't bigger than our max-width style.
-  const Length& style_max_logical_width = StyleRef().LogicalMaxWidth();
-  if ((style_max_logical_width.IsSpecified() &&
-       !style_max_logical_width.IsNegative()) ||
-      style_max_logical_width.IsContentOrIntrinsicOrFillAvailable()) {
-    LayoutUnit computed_max_logical_width =
-        ConvertStyleLogicalWidthToComputedWidth(style_max_logical_width,
-                                                available_logical_width);
-    SetLogicalWidth(LayoutUnit(
-        std::min(LogicalWidth(), computed_max_logical_width).Floor()));
-  }
-
-  // Ensure we aren't smaller than our min preferred width. This MUST be done
-  // after 'max-width' as we ignore it if it means we wouldn't accommodate our
-  // content.
-  SetLogicalWidth(LayoutUnit(
-      std::max(LogicalWidth(), preferred_logical_widths.min_size).Floor()));
-
-  // Ensure we aren't smaller than our min-width style.
-  const Length& style_min_logical_width = StyleRef().LogicalMinWidth();
-  if ((style_min_logical_width.IsSpecified() &&
-       !style_min_logical_width.IsNegative()) ||
-      style_min_logical_width.IsContentOrIntrinsicOrFillAvailable()) {
-    LayoutUnit computed_min_logical_width =
-        ConvertStyleLogicalWidthToComputedWidth(style_min_logical_width,
-                                                available_logical_width);
-    SetLogicalWidth(LayoutUnit(
-        std::max(LogicalWidth(), computed_min_logical_width).Floor()));
-  }
-
-  // Finally, with our true width determined, compute our margins for real.
-  ComputedMarginValues margin_values;
-  ComputeMarginsForDirection(kInlineDirection, cb, available_logical_width,
-                             LogicalWidth(), margin_values.start_,
-                             margin_values.end_, StyleRef().MarginStart(),
-                             StyleRef().MarginEnd());
-  SetMarginStart(margin_values.start_);
-  SetMarginEnd(margin_values.end_);
-
-  // We should NEVER shrink the table below the min-content logical width, or
-  // else the table can't accommodate its own content which doesn't match CSS
-  // nor what authors expect.
-  // FIXME: When we convert to sub-pixel layout for tables we can remove the int
-  // conversion. http://crbug.com/241198
-  DCHECK_GE(LogicalWidth().Floor(), preferred_logical_widths.min_size.Floor());
-  if (HasOverrideLogicalWidth())
-    SetLogicalWidth(OverrideLogicalWidth());
-}
-
-// This method takes a ComputedStyle's logical width, min-width, or max-width
-// length and computes its actual value.
-LayoutUnit LayoutTable::ConvertStyleLogicalWidthToComputedWidth(
-    const Length& style_logical_width,
-    LayoutUnit available_width) const {
-  NOT_DESTROYED();
-  if (style_logical_width.IsContentOrIntrinsicOrFillAvailable()) {
-    return ComputeIntrinsicLogicalWidthUsing(style_logical_width,
-                                             available_width);
-  }
-
-  // HTML tables' width styles already include borders and paddings, but CSS
-  // tables' width styles do not.
-  LayoutUnit borders;
-  bool is_css_table = !IsA<HTMLTableElement>(GetNode());
-  if (is_css_table && style_logical_width.IsSpecified() &&
-      style_logical_width.IsPositive() &&
-      StyleRef().BoxSizing() == EBoxSizing::kContentBox) {
-    borders = BorderStart() + BorderEnd() +
-              (ShouldCollapseBorders() ? LayoutUnit()
-                                       : PaddingStart() + PaddingEnd());
-  }
-
-  return MinimumValueForLength(style_logical_width, available_width) + borders;
-}
-
-LayoutUnit LayoutTable::ConvertStyleLogicalHeightToComputedHeight(
-    const Length& style_logical_height) const {
-  NOT_DESTROYED();
-  LayoutUnit border_and_padding_before =
-      BorderBefore() +
-      (ShouldCollapseBorders() ? LayoutUnit() : PaddingBefore());
-  LayoutUnit border_and_padding_after =
-      BorderAfter() + (ShouldCollapseBorders() ? LayoutUnit() : PaddingAfter());
-  LayoutUnit border_and_padding =
-      border_and_padding_before + border_and_padding_after;
-  LayoutUnit computed_logical_height;
-  if (style_logical_height.IsFixed()) {
-    // HTML tables size as though CSS height includes border/padding, CSS tables
-    // do not.
-    LayoutUnit borders = LayoutUnit();
-    // FIXME: We cannot apply box-sizing: content-box on <table> which other
-    // browsers allow.
-    if (IsA<HTMLTableElement>(GetNode()) ||
-        StyleRef().BoxSizing() == EBoxSizing::kBorderBox) {
-      borders = border_and_padding;
-    }
-    computed_logical_height =
-        LayoutUnit(style_logical_height.Value() - borders);
-  } else if (style_logical_height.IsPercentOrCalc()) {
-    computed_logical_height =
-        ComputePercentageLogicalHeight(style_logical_height);
-  } else if (style_logical_height.IsContentOrIntrinsicOrFillAvailable()) {
-    computed_logical_height = ComputeIntrinsicLogicalContentHeightUsing(
-        kMainOrPreferredSize, style_logical_height,
-        LogicalHeight() - border_and_padding, border_and_padding);
-  } else {
-    NOTREACHED();
-  }
-  return computed_logical_height.ClampNegativeToZero();
-}
-
-void LayoutTable::LayoutCaption(LayoutTableCaption& caption,
-                                SubtreeLayoutScope& layouter) {
-  NOT_DESTROYED();
-  if (!caption.NeedsLayout())
-    MarkChildForPaginationRelayoutIfNeeded(caption, layouter);
-  if (caption.NeedsLayout()) {
-    // The margins may not be available but ensure the caption is at least
-    // located beneath any previous sibling caption so that it does not
-    // mistakenly think any floats in the previous caption intrude into it.
-    caption.SetLogicalLocation(
-        LayoutPoint(caption.MarginStart(),
-                    CollapsedMarginBeforeForChild(caption) + LogicalHeight()));
-    // If LayoutTableCaption ever gets a layout() function, use it here.
-    caption.LayoutIfNeeded();
-  }
-  // Apply the margins to the location now that they are definitely available
-  // from layout
-  LayoutUnit caption_logical_top =
-      CollapsedMarginBeforeForChild(caption) + LogicalHeight();
-  caption.SetLogicalLocation(
-      LayoutPoint(caption.MarginStart(), caption_logical_top));
-  if (View()->GetLayoutState()->IsPaginated())
-    UpdateFragmentationInfoForChild(caption);
-
-  if (!SelfNeedsLayout())
-    caption.SetShouldCheckForPaintInvalidation();
-
-  SetLogicalHeight(LogicalHeight() + caption.LogicalHeight() +
-                   CollapsedMarginBeforeForChild(caption) +
-                   CollapsedMarginAfterForChild(caption));
-}
-
-void LayoutTable::LayoutSection(
-    LayoutTableSection& section,
-    SubtreeLayoutScope& layouter,
-    LayoutUnit logical_left,
-    TableHeightChangingValue table_height_changing) {
-  NOT_DESTROYED();
-  section.SetLogicalLocation(LayoutPoint(logical_left, LogicalHeight()));
-  if (column_logical_width_changed_)
-    layouter.SetChildNeedsLayout(&section);
-  if (!section.NeedsLayout())
-    MarkChildForPaginationRelayoutIfNeeded(section, layouter);
-  bool needed_layout = section.NeedsLayout();
-  if (needed_layout)
-    section.UpdateLayout();
-  if (needed_layout || table_height_changing == kTableHeightChanging) {
-    section.SetLogicalHeight(LayoutUnit(section.CalcRowLogicalHeight()));
-    section.DetermineIfHeaderGroupShouldRepeat();
-  }
-
-  if (View()->GetLayoutState()->IsPaginated())
-    UpdateFragmentationInfoForChild(section);
-  SetLogicalHeight(LogicalHeight() + section.LogicalHeight());
-}
-
-LayoutUnit LayoutTable::LogicalHeightFromStyle() const {
-  NOT_DESTROYED();
-  LayoutUnit computed_logical_height;
-  const Length& logical_height_length = StyleRef().LogicalHeight();
-  if (logical_height_length.IsContentOrIntrinsicOrFillAvailable() ||
-      (logical_height_length.IsSpecified() &&
-       logical_height_length.IsPositive())) {
-    computed_logical_height =
-        ConvertStyleLogicalHeightToComputedHeight(logical_height_length);
-  }
-
-  const Length& logical_max_height_length = StyleRef().LogicalMaxHeight();
-  if (logical_max_height_length.IsFillAvailable() ||
-      (logical_max_height_length.IsSpecified() &&
-       !logical_max_height_length.IsNegative() &&
-       !logical_max_height_length.IsMinContent() &&
-       !logical_max_height_length.IsMaxContent() &&
-       !logical_max_height_length.IsMinIntrinsic() &&
-       !logical_max_height_length.IsFitContent())) {
-    LayoutUnit computed_max_logical_height =
-        ConvertStyleLogicalHeightToComputedHeight(logical_max_height_length);
-    computed_logical_height =
-        std::min(computed_logical_height, computed_max_logical_height);
-  }
-
-  Length logical_min_height_length = StyleRef().LogicalMinHeight();
-  if (logical_min_height_length.IsMinContent() ||
-      logical_min_height_length.IsMaxContent() ||
-      logical_min_height_length.IsMinIntrinsic() ||
-      logical_min_height_length.IsFitContent())
-    logical_min_height_length = Length::Auto();
-
-  if (logical_min_height_length.IsContentOrIntrinsicOrFillAvailable() ||
-      (logical_min_height_length.IsSpecified() &&
-       !logical_min_height_length.IsNegative())) {
-    LayoutUnit computed_min_logical_height =
-        ConvertStyleLogicalHeightToComputedHeight(logical_min_height_length);
-    computed_logical_height =
-        std::max(computed_logical_height, computed_min_logical_height);
-  }
-
-  return computed_logical_height;
-}
-
-void LayoutTable::DistributeExtraLogicalHeight(int extra_logical_height) {
-  NOT_DESTROYED();
-  if (extra_logical_height <= 0)
-    return;
-
-  // FIXME: Distribute the extra logical height between all table sections
-  // instead of giving it all to the first one.
-  if (LayoutTableSection* section = FirstBody())
-    extra_logical_height -=
-        section->DistributeExtraLogicalHeightToRows(extra_logical_height);
-
-  DCHECK(!FirstBody() || !extra_logical_height);
-}
-
-void LayoutTable::SimplifiedNormalFlowLayout() {
-  NOT_DESTROYED();
-  // FIXME: We should walk through the items in the tree in tree order to do the
-  // layout here instead of walking through individual parts of the tree.
-  // crbug.com/442737
-  for (auto& caption : captions_)
-    caption->LayoutIfNeeded();
-
-  for (LayoutTableSection* section = TopSection(); section;
-       section = SectionBelow(section)) {
-    section->LayoutIfNeeded();
-    section->LayoutRows();
-    section->ComputeLayoutOverflowFromDescendants();
-    section->UpdateAfterLayout();
-  }
-}
-
-RecalcLayoutOverflowResult LayoutTable::RecalcLayoutOverflow() {
-  NOT_DESTROYED();
-  RecalcSelfLayoutOverflow();
-
-  if (!ChildNeedsLayoutOverflowRecalc())
-    return RecalcLayoutOverflowResult();
-
-  ClearChildNeedsLayoutOverflowRecalc();
-
-  // If the table sections we keep pointers to have gone away then the table
-  // will be rebuilt and overflow will get recalculated anyway so return early.
-  if (NeedsSectionRecalc())
-    return RecalcLayoutOverflowResult();
-
-  bool children_layout_overflow_changed = false;
-  for (LayoutTableSection* section = TopSection(); section;
-       section = SectionBelow(section)) {
-    children_layout_overflow_changed |=
-        section->RecalcLayoutOverflow().layout_overflow_changed;
-  }
-
-  children_layout_overflow_changed |=
-      RecalcPositionedDescendantsLayoutOverflow().layout_overflow_changed;
-
-  return {children_layout_overflow_changed, /* rebuild_fragment_tree */ false};
-}
-
-void LayoutTable::RecalcVisualOverflow() {
-  NOT_DESTROYED();
-  for (const auto& caption : captions_) {
-    if (!caption->HasSelfPaintingLayer())
-      caption->RecalcVisualOverflow();
-  }
-
-  for (LayoutTableSection* section = TopSection(); section;
-       section = SectionBelow(section)) {
-    if (!section->HasSelfPaintingLayer())
-      section->RecalcVisualOverflow();
-  }
-
-  RecalcSelfVisualOverflow();
-}
-
-void LayoutTable::UpdateLayout() {
-  NOT_DESTROYED();
-  DCHECK(NeedsLayout());
-
-  if (SimplifiedLayout())
-    return;
-
-  // Note: LayoutTable is handled differently than other LayoutBlocks and the
-  // LayoutScope
-  //       must be created before the table begins laying out.
-  TextAutosizer::LayoutScope text_autosizer_layout_scope(this);
-
-  RecalcSectionsIfNeeded();
-
-  SubtreeLayoutScope layouter(*this);
-
-  {
-    LayoutState state(*this);
-    LayoutUnit old_logical_width = LogicalWidth();
-    LayoutUnit old_logical_height = LogicalHeight();
-
-    SetLogicalHeight(LayoutUnit());
-    UpdateLogicalWidth();
-
-    if (LogicalWidth() != old_logical_width) {
-      for (unsigned i = 0; i < captions_.size(); i++) {
-        layouter.SetNeedsLayout(captions_[i],
-                                layout_invalidation_reason::kTableChanged);
-      }
-    }
-    // FIXME: The optimisation below doesn't work since the internal table
-    // layout could have changed. We need to add a flag to the table
-    // layout that tells us if something has changed in the min max
-    // calculations to do it correctly.
-    // if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
-    table_layout_->UpdateLayout();
-
-    // Lay out top captions.
-    // FIXME: Collapse caption margin.
-    for (unsigned i = 0; i < captions_.size(); i++) {
-      if (captions_[i]->StyleRef().CaptionSide() == ECaptionSide::kBottom)
-        continue;
-      LayoutCaption(*captions_[i], layouter);
-    }
-
-    LayoutTableSection* top_section = TopSection();
-    LayoutTableSection* bottom_section = BottomSection();
-
-    // This is the border-before edge of the "table box", relative to the "table
-    // wrapper box", i.e. right after all top captions.
-    // https://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#model
-    LayoutUnit table_box_logical_top = LogicalHeight();
-
-    bool collapsing = ShouldCollapseBorders();
-    LayoutUnit border_and_padding_before =
-        BorderBefore() + (collapsing ? LayoutUnit() : PaddingBefore());
-    LayoutUnit border_and_padding_after =
-        BorderAfter() + (collapsing ? LayoutUnit() : PaddingAfter());
-
-    SetLogicalHeight(table_box_logical_top + border_and_padding_before);
-
-    LayoutUnit section_logical_left = LayoutUnit(
-        StyleRef().IsLeftToRightDirection() ? BorderStart() : BorderEnd());
-    if (!collapsing) {
-      section_logical_left +=
-          StyleRef().IsLeftToRightDirection() ? PaddingStart() : PaddingEnd();
-    }
-    LayoutUnit current_available_logical_height =
-        AvailableLogicalHeight(kIncludeMarginBorderPadding);
-    TableHeightChangingValue table_height_changing =
-        old_available_logical_height_ && old_available_logical_height_ !=
-                                             current_available_logical_height
-            ? kTableHeightChanging
-            : kTableHeightNotChanging;
-    old_available_logical_height_ = current_available_logical_height;
-
-    // Lay out table footer to get its raw height. This will help us decide
-    // if we can repeat it in each page/column.
-    LayoutTableSection* footer = Footer();
-    if (footer) {
-      if (footer->GetLegacyPaginationBreakability() != kAllowAnyBreaks) {
-        footer->LayoutIfNeeded();
-        int footer_logical_height = footer->CalcRowLogicalHeight();
-        footer->SetLogicalHeight(LayoutUnit(footer_logical_height));
-      }
-      footer->DetermineIfFooterGroupShouldRepeat();
-    }
-
-    // Lay out table header group.
-    LayoutTableSection* header = Header();
-    if (header) {
-      LayoutSection(*header, layouter, section_logical_left,
-                    table_height_changing);
-    }
-
-    LayoutUnit original_offset_for_table_headers =
-        state.HeightOffsetForTableHeaders();
-    LayoutUnit offset_for_table_headers = original_offset_for_table_headers;
-    LayoutUnit original_offset_for_table_footers =
-        state.HeightOffsetForTableFooters();
-    LayoutUnit offset_for_table_footers = original_offset_for_table_footers;
-    if (state.IsPaginated() && IsPageLogicalHeightKnown()) {
-      // If the repeating header group allows at least one row of content,
-      // then store the offset for other sections to offset their rows
-      // against.
-      if (header && header->IsRepeatingHeaderGroup()) {
-        offset_for_table_headers += header->LogicalHeight();
-        // Don't include any strut in the header group - we only want the
-        // height from its content.
-        if (LayoutTableRow* row = header->FirstRow())
-          offset_for_table_headers -= row->PaginationStrut();
-        SetRowOffsetFromRepeatingHeader(offset_for_table_headers);
-      }
-
-      if (footer && footer->IsRepeatingFooterGroup()) {
-        offset_for_table_footers += footer->LogicalHeight();
-        SetRowOffsetFromRepeatingFooter(offset_for_table_footers);
-      }
-    }
-    state.SetHeightOffsetForTableHeaders(offset_for_table_headers);
-    state.SetHeightOffsetForTableFooters(offset_for_table_footers);
-
-    // Lay out table body groups, and column groups.
-    for (LayoutObject* child = FirstChild(); child;
-         child = child->NextSibling()) {
-      if (child->IsTableSection()) {
-        if (child != Header() && child != Footer()) {
-          LayoutTableSection& section = *To<LayoutTableSection>(child);
-          LayoutSection(section, layouter, section_logical_left,
-                        table_height_changing);
-        }
-      } else if (child->IsLayoutTableCol()) {
-        child->LayoutIfNeeded();
-      } else {
-        DCHECK(child->IsTableCaption());
-      }
-    }
-    // Reset these so they don't affect the layout of footers or captions.
-    state.SetHeightOffsetForTableHeaders(original_offset_for_table_headers);
-    state.SetHeightOffsetForTableFooters(original_offset_for_table_footers);
-
-    // Change logical width according to any collapsed columns.
-    Vector<int> col_collapsed_width;
-    AdjustWidthsForCollapsedColumns(col_collapsed_width);
-
-    // Lay out table footer.
-    if (LayoutTableSection* section = Footer()) {
-      LayoutSection(*section, layouter, section_logical_left,
-                    table_height_changing);
-    }
-
-    SetLogicalHeight(table_box_logical_top + border_and_padding_before);
-
-    LayoutUnit computed_logical_height = LogicalHeightFromStyle();
-    LayoutUnit total_section_logical_height;
-    if (top_section) {
-      total_section_logical_height =
-          bottom_section->LogicalBottom() - top_section->LogicalTop();
-    }
-
-    if (!state.IsPaginated() ||
-        !CrossesPageBoundary(table_box_logical_top, computed_logical_height)) {
-      DistributeExtraLogicalHeight(
-          FloorToInt(computed_logical_height - total_section_logical_height));
-    }
-
-    LayoutUnit logical_offset =
-        top_section ? top_section->LogicalTop() : LayoutUnit();
-    for (LayoutTableSection* section = top_section; section;
-         section = SectionBelow(section)) {
-      section->SetLogicalTop(logical_offset);
-      section->LayoutRows();
-      if (!IsAnyColumnEverCollapsed()) {
-        if (col_collapsed_width.size())
-          SetIsAnyColumnEverCollapsed();
-      }
-      if (IsAnyColumnEverCollapsed())
-        section->UpdateLogicalWidthForCollapsedCells(col_collapsed_width);
-      logical_offset += section->LogicalHeight();
-    }
-
-    if (!top_section &&
-        computed_logical_height > total_section_logical_height &&
-        !GetDocument().InQuirksMode()) {
-      // Completely empty tables (with no sections or anything) should at least
-      // honor specified height in strict mode.
-      SetLogicalHeight(LogicalHeight() + computed_logical_height);
-    }
-
-    // position the table sections
-    LayoutTableSection* section = top_section;
-    while (section) {
-      section->SetLogicalLocation(
-          LayoutPoint(section_logical_left, LogicalHeight()));
-
-      SetLogicalHeight(LogicalHeight() + section->LogicalHeight());
-
-      section->UpdateAfterLayout();
-
-      section = SectionBelow(section);
-    }
-
-    SetLogicalHeight(LogicalHeight() + border_and_padding_after);
-
-    // Lay out bottom captions.
-    for (unsigned i = 0; i < captions_.size(); i++) {
-      if (captions_[i]->StyleRef().CaptionSide() != ECaptionSide::kBottom)
-        continue;
-      LayoutCaption(*captions_[i], layouter);
-    }
-
-    UpdateLogicalHeight();
-
-    // table can be containing block of positioned elements.
-    bool dimension_changed = old_logical_width != LogicalWidth() ||
-                             old_logical_height != LogicalHeight();
-    LayoutPositionedObjects(dimension_changed);
-
-    ComputeLayoutOverflow(ClientLogicalBottom());
-    UpdateAfterLayout();
-  }
-
-  // FIXME: This value isn't the intrinsic content logical height, but we need
-  // to update the value as its used by flexbox layout. crbug.com/367324
-  SetIntrinsicContentLogicalHeight(ContentLogicalHeight());
-
-  column_logical_width_changed_ = false;
-  ClearNeedsLayout();
-}
-
-void LayoutTable::AdjustWidthsForCollapsedColumns(
-    Vector<int>& col_collapsed_width) {
-  NOT_DESTROYED();
-  DCHECK(!col_collapsed_width.size());
-  if (!RuntimeEnabledFeatures::VisibilityCollapseColumnEnabled())
-    return;
-
-  unsigned n_eff_cols = NumEffectiveColumns();
-
-  // Update vector of collapsed widths.
-  for (unsigned i = 0; i < n_eff_cols; ++i) {
-    // TODO(joysyu): Here, we are at O(n^2) for every table that has ever had a
-    // collapsed column. ColElementAtAbsoluteColumn() is currently O(n);
-    // ideally, it would be O(1). We have to improve the runtime before shipping
-    // visibility:collapse for columns. See discussion at
-    // https://chromium-review.googlesource.com/c/chromium/src/+/602506/18/third_party/WebKit/Source/core/layout/LayoutTable.cpp
-    if (IsAbsoluteColumnCollapsed(EffectiveColumnToAbsoluteColumn(i))) {
-      if (!col_collapsed_width.size())
-        col_collapsed_width.Grow(n_eff_cols);
-      col_collapsed_width[i] =
-          EffectiveColumnPositions()[i + 1] - EffectiveColumnPositions()[i];
-    }
-  }
-
-  if (!col_collapsed_width.size())
-    return;
-
-  // Adjust column positions according to collapsed widths.
-  int total_collapsed_width = 0;
-  for (unsigned i = 0; i < n_eff_cols; ++i) {
-    total_collapsed_width += col_collapsed_width[i];
-    SetEffectiveColumnPosition(
-        i + 1, EffectiveColumnPositions()[i + 1] - total_collapsed_width);
-  }
-
-  SetLogicalWidth(LogicalWidth() - total_collapsed_width);
-  DCHECK_GE(LogicalWidth(), 0);
-}
-
-bool LayoutTable::IsAbsoluteColumnCollapsed(
-    unsigned absolute_column_index) const {
-  NOT_DESTROYED();
-  ColAndColGroup colElement = ColElementAtAbsoluteColumn(absolute_column_index);
-  LayoutTableCol* col = colElement.col;
-  LayoutTableCol* colgroup = colElement.colgroup;
-  return (col && col->StyleRef().Visibility() == EVisibility::kCollapse) ||
-         (colgroup &&
-          colgroup->StyleRef().Visibility() == EVisibility::kCollapse);
-}
-
-void LayoutTable::InvalidateCollapsedBorders() {
-  NOT_DESTROYED();
-  collapsed_borders_valid_ = false;
-  needs_invalidate_collapsed_borders_for_all_cells_ = true;
-  collapsed_outer_borders_valid_ = false;
-  SetShouldCheckForPaintInvalidation();
-}
-
-void LayoutTable::InvalidateCollapsedBordersForAllCellsIfNeeded() {
-  NOT_DESTROYED();
-  DCHECK(ShouldCollapseBorders());
-
-  if (!needs_invalidate_collapsed_borders_for_all_cells_)
-    return;
-  needs_invalidate_collapsed_borders_for_all_cells_ = false;
-
-  for (LayoutObject* section = FirstChild(); section;
-       section = section->NextSibling()) {
-    if (!section->IsTableSection())
-      continue;
-    for (LayoutTableRow* row = To<LayoutTableSection>(section)->FirstRow(); row;
-         row = row->NextRow()) {
-      for (LayoutTableCell* cell = row->FirstCell(); cell;
-           cell = cell->NextCell()) {
-        DCHECK_EQ(cell->Table(), this);
-        cell->InvalidateCollapsedBorderValues();
-        cell->SetHasNonCollapsedBorderDecoration(
-            !ShouldCollapseBorders() && cell->StyleRef().HasBorderDecoration());
-      }
-    }
-  }
-}
-
-void LayoutTable::ComputeVisualOverflow(bool) {
-  NOT_DESTROYED();
-  LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
-  ClearVisualOverflow();
-  AddVisualOverflowFromChildren();
-  AddVisualEffectOverflow();
-
-  if (VisualOverflowRect() != previous_visual_overflow_rect) {
-    InvalidateIntersectionObserverCachedRects();
-    SetShouldCheckForPaintInvalidation();
-    GetFrameView()->SetIntersectionObservationState(LocalFrameView::kDesired);
-  }
-}
-
-void LayoutTable::AddVisualOverflowFromChildren() {
-  NOT_DESTROYED();
-  // Add overflow from borders.
-  // Technically it's odd that we are incorporating the borders into layout
-  // overflow, which is only supposed to be about overflow from our
-  // descendant objects, but since tables don't support overflow:auto, this
-  // works out fine.
-  UpdateCollapsedOuterBorders();
-  if (ShouldCollapseBorders() && (collapsed_outer_border_start_overflow_ ||
-                                  collapsed_outer_border_end_overflow_)) {
-    LogicalToPhysical<LayoutUnit> physical_border_overflow(
-        StyleRef().GetWritingDirection(),
-        LayoutUnit(collapsed_outer_border_start_overflow_),
-        LayoutUnit(collapsed_outer_border_end_overflow_), LayoutUnit(),
-        LayoutUnit());
-    LayoutRect border_overflow(PixelSnappedBorderBoxRect());
-    border_overflow.Expand(LayoutRectOutsets(
-        physical_border_overflow.Top(), physical_border_overflow.Right(),
-        physical_border_overflow.Bottom(), physical_border_overflow.Left()));
-    AddSelfVisualOverflow(border_overflow);
-  }
-
-  // Add overflow from our caption.
-  for (const auto& caption : captions_)
-    AddVisualOverflowFromChild(*caption);
-
-  // Add overflow from our sections.
-  for (LayoutTableSection* section = TopSection(); section;
-       section = SectionBelow(section))
-    AddVisualOverflowFromChild(*section);
-}
-
-void LayoutTable::AddLayoutOverflowFromChildren() {
-  NOT_DESTROYED();
-  // Add overflow from borders.
-  // Technically it's odd that we are incorporating the borders into layout
-  // overflow, which is only supposed to be about overflow from our
-  // descendant objects, but since tables don't support overflow:auto, this
-  // works out fine.
-  UpdateCollapsedOuterBorders();
-  if (ShouldCollapseBorders() && (collapsed_outer_border_start_overflow_ ||
-                                  collapsed_outer_border_end_overflow_)) {
-    LogicalToPhysical<LayoutUnit> physical_border_overflow(
-        StyleRef().GetWritingDirection(),
-        LayoutUnit(collapsed_outer_border_start_overflow_),
-        LayoutUnit(collapsed_outer_border_end_overflow_), LayoutUnit(),
-        LayoutUnit());
-    LayoutRect border_overflow(PixelSnappedBorderBoxRect());
-    border_overflow.Expand(LayoutRectOutsets(
-        physical_border_overflow.Top(), physical_border_overflow.Right(),
-        physical_border_overflow.Bottom(), physical_border_overflow.Left()));
-    AddLayoutOverflow(border_overflow);
-  }
-
-  // Add overflow from our caption.
-  for (unsigned i = 0; i < captions_.size(); i++)
-    AddLayoutOverflowFromChild(*captions_[i]);
-
-  // Add overflow from our sections.
-  for (LayoutTableSection* section = TopSection(); section;
-       section = SectionBelow(section))
-    AddLayoutOverflowFromChild(*section);
-}
-
-void LayoutTable::PaintObject(const PaintInfo& paint_info,
-                              const PhysicalOffset& paint_offset) const {
-  NOT_DESTROYED();
-  TablePainter(*this).PaintObject(paint_info, paint_offset);
-}
-
-void LayoutTable::SubtractCaptionRect(PhysicalRect& rect) const {
-  NOT_DESTROYED();
-  for (unsigned i = 0; i < captions_.size(); i++) {
-    LayoutUnit caption_logical_height = captions_[i]->LogicalHeight() +
-                                        captions_[i]->MarginBefore() +
-                                        captions_[i]->MarginAfter();
-    bool caption_is_before =
-        (captions_[i]->StyleRef().CaptionSide() != ECaptionSide::kBottom) ^
-        StyleRef().IsFlippedBlocksWritingMode();
-    if (StyleRef().IsHorizontalWritingMode()) {
-      rect.size.height -= caption_logical_height;
-      if (caption_is_before)
-        rect.offset.top += caption_logical_height;
-    } else {
-      rect.size.width -= caption_logical_height;
-      if (caption_is_before)
-        rect.offset.left += caption_logical_height;
-    }
-  }
-}
-
-void LayoutTable::MarkAllCellsWidthsDirtyAndOrNeedsLayout(
-    WhatToMarkAllCells what_to_mark) {
-  NOT_DESTROYED();
-  for (LayoutObject* child = Children()->FirstChild(); child;
-       child = child->NextSibling()) {
-    if (!child->IsTableSection())
-      continue;
-    LayoutTableSection* section = To<LayoutTableSection>(child);
-    section->MarkAllCellsWidthsDirtyAndOrNeedsLayout(what_to_mark);
-  }
-}
-
-void LayoutTable::PaintBoxDecorationBackground(
-    const PaintInfo& paint_info,
-    const PhysicalOffset& paint_offset) const {
-  NOT_DESTROYED();
-  TablePainter(*this).PaintBoxDecorationBackground(paint_info, paint_offset);
-}
-
-void LayoutTable::PaintMask(const PaintInfo& paint_info,
-                            const PhysicalOffset& paint_offset) const {
-  NOT_DESTROYED();
-  TablePainter(*this).PaintMask(paint_info, paint_offset);
-}
-
-MinMaxSizes LayoutTable::ComputeIntrinsicLogicalWidths() const {
-  NOT_DESTROYED();
-  RecalcSectionsIfNeeded();
-  // FIXME: Restructure the table layout code so that we can make this method
-  // const.
-  MinMaxSizes sizes;
-  const_cast<LayoutTable*>(this)->table_layout_->ComputeIntrinsicLogicalWidths(
-      sizes.min_size, sizes.max_size);
-
-  // FIXME: We should include captions widths here like we do in
-  // computePreferredLogicalWidths.
-  sizes += LayoutUnit(BordersPaddingAndSpacingInRowDirection().ToInt());
-  return sizes;
-}
-
-MinMaxSizes LayoutTable::PreferredLogicalWidths() const {
-  NOT_DESTROYED();
-  MinMaxSizes sizes = IntrinsicLogicalWidths();
-
-  table_layout_->ApplyPreferredLogicalWidthQuirks(sizes.min_size,
-                                                  sizes.max_size);
-
-  for (const auto& caption : captions_) {
-    LayoutUnit min_preferred_logical_width =
-        caption->PreferredLogicalWidths().min_size;
-    sizes.Encompass(min_preferred_logical_width);
-  }
-
-  const ComputedStyle& style_to_use = StyleRef();
-  // FIXME: This should probably be checking for isSpecified since you should be
-  // able to use percentage or calc values for min-width.
-  if (style_to_use.LogicalMinWidth().IsFixed() &&
-      style_to_use.LogicalMinWidth().Value() > 0) {
-    sizes.Encompass(AdjustBorderBoxLogicalWidthForBoxSizing(
-        style_to_use.LogicalMinWidth().Value()));
-  }
-
-  // FIXME: This should probably be checking for isSpecified since you should be
-  // able to use percentage or calc values for maxWidth.
-  if (style_to_use.LogicalMaxWidth().IsFixed()) {
-    // We don't constrain m_minPreferredLogicalWidth as the table should be at
-    // least the size of its min-content, regardless of 'max-width'.
-    sizes.max_size =
-        std::min(sizes.max_size, AdjustBorderBoxLogicalWidthForBoxSizing(
-                                     style_to_use.LogicalMaxWidth().Value()));
-  }
-
-  // 2 cases need this:
-  // 1. When max_preferred_logical_width is shrunk to the specified max-width in
-  //    the block above but max-width < min_preferred_logical_width.
-  // 2. We buggily calculate min > max for some tables with colspans and
-  //    percent widths. See fast/table/spans-min-greater-than-max-crash.html and
-  //    http://crbug.com/857185
-  sizes.max_size = std::max(sizes.min_size, sizes.max_size);
-  return sizes;
-}
-
-LayoutTableSection* LayoutTable::TopNonEmptySection() const {
-  NOT_DESTROYED();
-  LayoutTableSection* section = TopSection();
-  if (section && !section->NumRows())
-    section = SectionBelow(section, kSkipEmptySections);
-  return section;
-}
-
-LayoutTableSection* LayoutTable::BottomNonEmptySection() const {
-  NOT_DESTROYED();
-  LayoutTableSection* section = BottomSection();
-  if (section && !section->NumRows())
-    section = SectionAbove(section, kSkipEmptySections);
-  return section;
-}
-
-void LayoutTable::SplitEffectiveColumn(unsigned index, unsigned first_span) {
-  NOT_DESTROYED();
-  // We split the column at |index|, taking |firstSpan| cells from the span.
-  DCHECK_GT(effective_columns_[index].span, first_span);
-  effective_columns_.insert(index, first_span);
-  effective_columns_[index + 1].span -= first_span;
-
-  // Propagate the change in our columns representation to the sections that
-  // don't need cell recalc. If they do, they will be synced up directly with
-  // m_columns later.
-  for (LayoutObject* child = FirstChild(); child;
-       child = child->NextSibling()) {
-    if (!child->IsTableSection())
-      continue;
-
-    LayoutTableSection* section = To<LayoutTableSection>(child);
-    if (section->NeedsCellRecalc())
-      continue;
-
-    section->SplitEffectiveColumn(index, first_span);
-  }
-
-  effective_column_positions_.Grow(NumEffectiveColumns() + 1);
-}
-
-void LayoutTable::AppendEffectiveColumn(unsigned span) {
-  NOT_DESTROYED();
-  unsigned new_column_index = effective_columns_.size();
-  effective_columns_.push_back(span);
-
-  // Unless the table has cell(s) with colspan that exceed the number of columns
-  // afforded by the other rows in the table we can use the fast path when
-  // mapping columns to effective columns.
-  if (span == 1 && no_cell_colspan_at_least_ + 1 == NumEffectiveColumns()) {
-    no_cell_colspan_at_least_++;
-  }
-
-  // Propagate the change in our columns representation to the sections that
-  // don't need cell recalc. If they do, they will be synced up directly with
-  // m_columns later.
-  for (LayoutObject* child = FirstChild(); child;
-       child = child->NextSibling()) {
-    if (!child->IsTableSection())
-      continue;
-
-    LayoutTableSection* section = To<LayoutTableSection>(child);
-    if (section->NeedsCellRecalc())
-      continue;
-
-    section->AppendEffectiveColumn(new_column_index);
-  }
-
-  effective_column_positions_.Grow(NumEffectiveColumns() + 1);
-}
-
-LayoutTableCol* LayoutTable::FirstColumn() const {
-  NOT_DESTROYED();
-  for (LayoutObject* child = FirstChild(); child;
-       child = child->NextSibling()) {
-    if (child->IsLayoutTableCol())
-      return To<LayoutTableCol>(child);
-  }
-
-  return nullptr;
-}
-
-void LayoutTable::UpdateColumnCache() const {
-  NOT_DESTROYED();
-  DCHECK(has_col_elements_);
-  DCHECK(column_layout_objects_.empty());
-  DCHECK(!column_layout_objects_valid_);
-
-  for (LayoutTableCol* column_layout_object = FirstColumn();
-       column_layout_object;
-       column_layout_object = column_layout_object->NextColumn()) {
-    if (column_layout_object->IsTableColumnGroupWithColumnChildren())
-      continue;
-    column_layout_objects_.push_back(column_layout_object);
-  }
-  column_layout_objects_valid_ = true;
-  // TODO(joysyu): There may be an optimization opportunity to set
-  // is_any_column_ever_collapsed_ to false here.
-}
-
-LayoutTable::ColAndColGroup LayoutTable::SlowColElementAtAbsoluteColumn(
-    unsigned absolute_column_index) const {
-  NOT_DESTROYED();
-  DCHECK(has_col_elements_);
-
-  if (!column_layout_objects_valid_)
-    UpdateColumnCache();
-
-  unsigned column_count = 0;
-  for (unsigned i = 0; i < column_layout_objects_.size(); i++) {
-    LayoutTableCol* column_layout_object = column_layout_objects_[i];
-    DCHECK(!column_layout_object->IsTableColumnGroupWithColumnChildren());
-    unsigned span = column_layout_object->Span();
-    unsigned start_col = column_count;
-    DCHECK_GE(span, 1u);
-    unsigned end_col = column_count + span - 1;
-    column_count += span;
-    if (column_count > absolute_column_index) {
-      ColAndColGroup col_and_col_group;
-      bool is_at_start_edge = start_col == absolute_column_index;
-      bool is_at_end_edge = end_col == absolute_column_index;
-      if (column_layout_object->IsTableColumnGroup()) {
-        col_and_col_group.colgroup = column_layout_object;
-        col_and_col_group.adjoins_start_border_of_col_group = is_at_start_edge;
-        col_and_col_group.adjoins_end_border_of_col_group = is_at_end_edge;
-      } else {
-        col_and_col_group.col = column_layout_object;
-        col_and_col_group.colgroup =
-            column_layout_object->EnclosingColumnGroup();
-        if (col_and_col_group.colgroup) {
-          col_and_col_group.adjoins_start_border_of_col_group =
-              is_at_start_edge && !col_and_col_group.col->PreviousSibling();
-          col_and_col_group.adjoins_end_border_of_col_group =
-              is_at_end_edge && !col_and_col_group.col->NextSibling();
-        }
-      }
-      return col_and_col_group;
-    }
-  }
-  return ColAndColGroup();
-}
-
-void LayoutTable::RecalcSections() const {
-  NOT_DESTROYED();
-  DCHECK(needs_section_recalc_);
-
-  head_ = nullptr;
-  foot_ = nullptr;
-  first_body_ = nullptr;
-  has_col_elements_ = false;
-
-  // We need to get valid pointers to caption, head, foot and first body again
-  LayoutObject* next_sibling;
-  for (LayoutObject* child = FirstChild(); child; child = next_sibling) {
-    next_sibling = child->NextSibling();
-    switch (child->StyleRef().Display()) {
-      case EDisplay::kTableColumn:
-      case EDisplay::kTableColumnGroup:
-        has_col_elements_ = true;
-        break;
-      case EDisplay::kTableHeaderGroup:
-        if (child->IsTableSection()) {
-          LayoutTableSection* section = To<LayoutTableSection>(child);
-          if (!head_)
-            head_ = section;
-          else if (!first_body_)
-            first_body_ = section;
-          section->RecalcCellsIfNeeded();
-        }
-        break;
-      case EDisplay::kTableFooterGroup:
-        if (child->IsTableSection()) {
-          LayoutTableSection* section = To<LayoutTableSection>(child);
-          if (!foot_)
-            foot_ = section;
-          else if (!first_body_)
-            first_body_ = section;
-          section->RecalcCellsIfNeeded();
-        }
-        break;
-      case EDisplay::kTableRowGroup:
-        if (child->IsTableSection()) {
-          LayoutTableSection* section = To<LayoutTableSection>(child);
-          if (!first_body_)
-            first_body_ = section;
-          section->RecalcCellsIfNeeded();
-        }
-        break;
-      default:
-        break;
-    }
-  }
-
-  // repair column count (addChild can grow it too much, because it always adds
-  // elements to the last row of a section)
-  unsigned max_cols = 0;
-  for (LayoutObject* child = FirstChild(); child;
-       child = child->NextSibling()) {
-    if (child->IsTableSection()) {
-      LayoutTableSection* section = To<LayoutTableSection>(child);
-      if (column_structure_changed_) {
-        section->MarkAllCellsWidthsDirtyAndOrNeedsLayout(
-            LayoutTable::kMarkDirtyAndNeedsLayout);
-      }
-      unsigned section_cols = section->NumEffectiveColumns();
-      if (section_cols > max_cols)
-        max_cols = section_cols;
-    }
-  }
-  column_structure_changed_ = false;
-
-  effective_columns_.resize(max_cols);
-  effective_column_positions_.resize(max_cols + 1);
-  no_cell_colspan_at_least_ = CalcNoCellColspanAtLeast();
-
-  DCHECK(SelfNeedsLayout());
-
-  needs_section_recalc_ = false;
-}
-
-LayoutUnit LayoutTable::BorderLeft() const {
-  NOT_DESTROYED();
-  if (ShouldCollapseBorders()) {
-    UpdateCollapsedOuterBorders();
-    return LayoutUnit(LogicalCollapsedOuterBorderToPhysical().Left());
-  }
-  return LayoutUnit(LayoutBlock::BorderLeft().ToInt());
-}
-
-LayoutUnit LayoutTable::BorderRight() const {
-  NOT_DESTROYED();
-  if (ShouldCollapseBorders()) {
-    UpdateCollapsedOuterBorders();
-    return LayoutUnit(LogicalCollapsedOuterBorderToPhysical().Right());
-  }
-  return LayoutUnit(LayoutBlock::BorderRight().ToInt());
-}
-
-LayoutUnit LayoutTable::BorderTop() const {
-  NOT_DESTROYED();
-  if (ShouldCollapseBorders()) {
-    UpdateCollapsedOuterBorders();
-    return LayoutUnit(LogicalCollapsedOuterBorderToPhysical().Top());
-  }
-  return LayoutUnit(LayoutBlock::BorderTop().ToInt());
-}
-
-LayoutUnit LayoutTable::BorderBottom() const {
-  NOT_DESTROYED();
-  if (ShouldCollapseBorders()) {
-    UpdateCollapsedOuterBorders();
-    return LayoutUnit(LogicalCollapsedOuterBorderToPhysical().Bottom());
-  }
-  return LayoutUnit(LayoutBlock::BorderBottom().ToInt());
-}
-
-LayoutTableSection* LayoutTable::SectionAbove(
-    const LayoutTableSection* section,
-    SkipEmptySectionsValue skip_empty_sections) const {
-  NOT_DESTROYED();
-  RecalcSectionsIfNeeded();
-
-  if (section == head_)
-    return nullptr;
-
-  LayoutObject* prev_section =
-      section == foot_ ? LastChild() : section->PreviousSibling();
-  while (prev_section) {
-    if (prev_section->IsTableSection() && prev_section != head_ &&
-        prev_section != foot_ &&
-        (skip_empty_sections == kDoNotSkipEmptySections ||
-         To<LayoutTableSection>(prev_section)->NumRows()))
-      break;
-    prev_section = prev_section->PreviousSibling();
-  }
-  if (!prev_section && head_ &&
-      (skip_empty_sections == kDoNotSkipEmptySections || head_->NumRows()))
-    prev_section = head_;
-  return To<LayoutTableSection>(prev_section);
-}
-
-LayoutTableSection* LayoutTable::SectionBelow(
-    const LayoutTableSection* section,
-    SkipEmptySectionsValue skip_empty_sections) const {
-  NOT_DESTROYED();
-  RecalcSectionsIfNeeded();
-
-  if (section == foot_)
-    return nullptr;
-
-  LayoutObject* next_section =
-      section == head_ ? FirstChild() : section->NextSibling();
-  while (next_section) {
-    if (next_section->IsTableSection() && next_section != head_ &&
-        next_section != foot_ &&
-        (skip_empty_sections == kDoNotSkipEmptySections ||
-         To<LayoutTableSection>(next_section)->NumRows()))
-      break;
-    next_section = next_section->NextSibling();
-  }
-  if (!next_section && foot_ &&
-      (skip_empty_sections == kDoNotSkipEmptySections || foot_->NumRows()))
-    next_section = foot_;
-  return To<LayoutTableSection>(next_section);
-}
-
-LayoutTableSection* LayoutTable::BottomSection() const {
-  NOT_DESTROYED();
-  RecalcSectionsIfNeeded();
-
-  if (foot_)
-    return foot_;
-
-  if (head_ && !first_body_)
-    return head_;
-
-  for (LayoutObject* child = LastChild(); child;
-       child = child->PreviousSibling()) {
-    if (child == head_)
-      continue;
-    if (child->IsTableSection())
-      return To<LayoutTableSection>(child);
-  }
-
-  return nullptr;
-}
-
-LayoutTableCell* LayoutTable::CellAbove(const LayoutTableCell& cell) const {
-  NOT_DESTROYED();
-  RecalcSectionsIfNeeded();
-
-  // Find the section and row to look in
-  unsigned r = cell.RowIndex();
-  LayoutTableSection* section = nullptr;
-  unsigned r_above = 0;
-  if (r > 0) {
-    // cell is not in the first row, so use the above row in its own section
-    section = cell.Section();
-    r_above = r - 1;
-  } else {
-    section = SectionAbove(cell.Section(), kSkipEmptySections);
-    if (section) {
-      DCHECK(section->NumRows());
-      r_above = section->NumRows() - 1;
-    }
-  }
-
-  // Look up the cell in the section's grid, which requires effective col index
-  if (section) {
-    unsigned eff_col =
-        AbsoluteColumnToEffectiveColumn(cell.AbsoluteColumnIndex());
-    return section->PrimaryCellAt(r_above, eff_col);
-  }
-  return nullptr;
-}
-
-LayoutTableCell* LayoutTable::CellBelow(const LayoutTableCell& cell) const {
-  NOT_DESTROYED();
-  RecalcSectionsIfNeeded();
-
-  // Find the section and row to look in
-  unsigned r = cell.RowIndex() + cell.ResolvedRowSpan() - 1;
-  LayoutTableSection* section = nullptr;
-  unsigned r_below = 0;
-  if (r < cell.Section()->NumRows() - 1) {
-    // The cell is not in the last row, so use the next row in the section.
-    section = cell.Section();
-    r_below = r + 1;
-  } else {
-    section = SectionBelow(cell.Section(), kSkipEmptySections);
-    if (section)
-      r_below = 0;
-  }
-
-  // Look up the cell in the section's grid, which requires effective col index
-  if (section) {
-    unsigned eff_col =
-        AbsoluteColumnToEffectiveColumn(cell.AbsoluteColumnIndex());
-    return section->PrimaryCellAt(r_below, eff_col);
-  }
-  return nullptr;
-}
-
-LayoutTableCell* LayoutTable::CellPreceding(const LayoutTableCell& cell) const {
-  NOT_DESTROYED();
-  RecalcSectionsIfNeeded();
-
-  LayoutTableSection* section = cell.Section();
-  unsigned eff_col =
-      AbsoluteColumnToEffectiveColumn(cell.AbsoluteColumnIndex());
-  if (!eff_col)
-    return nullptr;
-
-  // If we hit a colspan back up to a real cell.
-  return section->PrimaryCellAt(cell.RowIndex(), eff_col - 1);
-}
-
-LayoutTableCell* LayoutTable::CellFollowing(const LayoutTableCell& cell) const {
-  NOT_DESTROYED();
-  RecalcSectionsIfNeeded();
-
-  unsigned eff_col = AbsoluteColumnToEffectiveColumn(
-      cell.AbsoluteColumnIndex() + cell.ColSpan());
-  return cell.Section()->PrimaryCellAt(cell.RowIndex(), eff_col);
-}
-
-LayoutUnit LayoutTable::BaselinePosition(
-    FontBaseline baseline_type,
-    bool first_line,
-    LineDirectionMode direction,
-    LinePositionMode line_position_mode) const {
-  NOT_DESTROYED();
-  DCHECK_EQ(line_position_mode, kPositionOnContainingLine);
-  LayoutUnit baseline = FirstLineBoxBaseline();
-  if (baseline != -1) {
-    if (IsInline())
-      return BeforeMarginInLineDirection(direction) + baseline;
-    return baseline;
-  }
-
-  return LayoutBox::BaselinePosition(baseline_type, first_line, direction,
-                                     line_position_mode);
-}
-
-LayoutUnit LayoutTable::InlineBlockBaseline(LineDirectionMode) const {
-  NOT_DESTROYED();
-  // Tables are skipped when computing an inline-block's baseline.
-  return LayoutUnit(-1);
-}
-
-LayoutUnit LayoutTable::FirstLineBoxBaseline() const {
-  NOT_DESTROYED();
-  // The baseline of a 'table' is the same as the 'inline-table' baseline per
-  // CSS 3 Flexbox (CSS 2.1 doesn't define the baseline of a 'table' only an
-  // 'inline-table'). This is also needed to properly determine the baseline of
-  // a cell if it has a table child.
-
-  if (IsWritingModeRoot() || ShouldApplyLayoutContainment())
-    return LayoutUnit(-1);
-
-  RecalcSectionsIfNeeded();
-
-  const LayoutTableSection* top_non_empty_section = TopNonEmptySection();
-  if (!top_non_empty_section)
-    return LayoutUnit(-1);
-
-  LayoutUnit baseline = top_non_empty_section->FirstLineBoxBaseline();
-  if (baseline >= 0)
-    return top_non_empty_section->LogicalTop() + baseline;
-
-  // FF, Presto and IE use the top of the section as the baseline if its first
-  // row is empty of cells or content.
-  // The baseline of an empty row isn't specified by CSS 2.1.
-  if (top_non_empty_section->FirstRow() &&
-      !top_non_empty_section->FirstRow()->FirstCell())
-    return top_non_empty_section->LogicalTop();
-
-  return LayoutUnit(-1);
-}
-
-PhysicalRect LayoutTable::OverflowClipRect(
-    const PhysicalOffset& location,
-    OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior) const {
-  NOT_DESTROYED();
-  if (ShouldCollapseBorders()) {
-    // Though the outer halves of the collapsed borders are considered as the
-    // the border area of the table by means of the box model, they are actually
-    // contents of the table and should not be clipped off. The overflow clip
-    // rect is BorderBoxRect() + location.
-    return PhysicalRect(location, Size());
-  }
-
-  PhysicalRect rect =
-      LayoutBlock::OverflowClipRect(location, overlay_scrollbar_clip_behavior);
-
-  // If we have a caption, expand the clip to include the caption.
-  // FIXME: Technically this is wrong, but it's virtually impossible to fix this
-  // for real until captions have been re-written.
-  // FIXME: This code assumes (like all our other caption code) that only
-  // top/bottom are supported.  When we actually support left/right and stop
-  // mapping them to top/bottom, we might have to hack this code first
-  // (depending on what order we do these bug fixes in).
-  if (!captions_.empty()) {
-    if (StyleRef().IsHorizontalWritingMode()) {
-      rect.size.height = Size().Height();
-      rect.offset.top = location.top;
-    } else {
-      rect.size.width = Size().Width();
-      rect.offset.left = location.left;
-    }
-  }
-
-  return rect;
-}
-
-bool LayoutTable::NodeAtPoint(HitTestResult& result,
-                              const HitTestLocation& hit_test_location,
-                              const PhysicalOffset& accumulated_offset,
-                              HitTestPhase phase) {
-  NOT_DESTROYED();
-  // Check kids first.
-  bool skip_children = (result.GetHitTestRequest().GetStopNode() == this);
-  if (!skip_children &&
-      (!HasNonVisibleOverflow() ||
-       hit_test_location.Intersects(OverflowClipRect(accumulated_offset)))) {
-    for (LayoutObject* child = LastChild(); child;
-         child = child->PreviousSibling()) {
-      if (child->IsBox() && !To<LayoutBox>(child)->HasSelfPaintingLayer() &&
-          (child->IsTableSection() || child->IsTableCaption())) {
-        PhysicalOffset child_accumulated_offset =
-            accumulated_offset + To<LayoutBox>(child)->PhysicalLocation(this);
-        if (child->NodeAtPoint(result, hit_test_location,
-                               child_accumulated_offset, phase)) {
-          UpdateHitTestResult(result,
-                              hit_test_location.Point() - accumulated_offset);
-          return true;
-        }
-      }
-    }
-  }
-
-  // Check our bounds next.
-  PhysicalRect bounds_rect(accumulated_offset, Size());
-  if (VisibleToHitTestRequest(result.GetHitTestRequest()) &&
-      (phase == HitTestPhase::kSelfBlockBackground) &&
-      hit_test_location.Intersects(bounds_rect)) {
-    UpdateHitTestResult(result, hit_test_location.Point() - accumulated_offset);
-    if (result.AddNodeToListBasedTestResult(GetNode(), hit_test_location,
-                                            bounds_rect) == kStopHitTesting)
-      return true;
-  }
-
-  return false;
-}
-
-LayoutBox* LayoutTable::CreateAnonymousBoxWithSameTypeAs(
-    const LayoutObject* parent) const {
-  NOT_DESTROYED();
-  return LayoutObjectFactory::CreateAnonymousTableWithParent(*parent);
-}
-
-void LayoutTable::EnsureIsReadyForPaintInvalidation() {
-  NOT_DESTROYED();
-  LayoutBlock::EnsureIsReadyForPaintInvalidation();
-
-  if (collapsed_borders_valid_)
-    return;
-
-  collapsed_borders_valid_ = true;
-  has_collapsed_borders_ = false;
-  needs_adjust_collapsed_border_joints_ = false;
-  if (!ShouldCollapseBorders())
-    return;
-
-  CollapsedBorderValue first_border;
-  for (auto* section = TopSection(); section; section = SectionBelow(section)) {
-    for (auto* row = section->FirstRow(); row; row = row->NextRow()) {
-      for (auto* cell = row->FirstCell(); cell; cell = cell->NextCell()) {
-        DCHECK_EQ(cell->Table(), this);
-        // Determine if there are any collapsed borders, and if so set
-        // has_collapsed_borders_.
-        const auto* values = cell->GetCollapsedBorderValues();
-        if (!values)
-          continue;
-        has_collapsed_borders_ = true;
-
-        // Determine if there are any differences other than color in any of the
-        // borders of any cells (even if not adjacent), and if so set
-        // needs_adjust_collapsed_border_joints_.
-        if (needs_adjust_collapsed_border_joints_)
-          continue;
-        for (int i = 0; i < 4; ++i) {
-          const auto& border = values->Borders()[i];
-          if (!first_border.Exists()) {
-            first_border = border;
-          } else if (!first_border.IsSameIgnoringColor(border)) {
-            needs_adjust_collapsed_border_joints_ = true;
-            break;
-          }
-        }
-      }
-    }
-  }
-}
-
-void LayoutTable::InvalidatePaint(
-    const PaintInvalidatorContext& context) const {
-  NOT_DESTROYED();
-  TablePaintInvalidator(*this, context).InvalidatePaint();
-}
-
-LayoutUnit LayoutTable::PaddingTop() const {
-  NOT_DESTROYED();
-  if (ShouldCollapseBorders())
-    return LayoutUnit();
-
-  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
-  // sub-pixel aware.
-  return LayoutUnit(LayoutBlock::PaddingTop().ToInt());
-}
-
-LayoutUnit LayoutTable::PaddingBottom() const {
-  NOT_DESTROYED();
-  if (ShouldCollapseBorders())
-    return LayoutUnit();
-
-  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
-  // sub-pixel aware.
-  return LayoutUnit(LayoutBlock::PaddingBottom().ToInt());
-}
-
-LayoutUnit LayoutTable::PaddingLeft() const {
-  NOT_DESTROYED();
-  if (ShouldCollapseBorders())
-    return LayoutUnit();
-
-  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
-  // sub-pixel aware.
-  return LayoutUnit(LayoutBlock::PaddingLeft().ToInt());
-}
-
-LayoutUnit LayoutTable::PaddingRight() const {
-  NOT_DESTROYED();
-  if (ShouldCollapseBorders())
-    return LayoutUnit();
-
-  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
-  // sub-pixel aware.
-  return LayoutUnit(LayoutBlock::PaddingRight().ToInt());
-}
-
-void LayoutTable::UpdateCollapsedOuterBorders() const {
-  NOT_DESTROYED();
-  if (collapsed_outer_borders_valid_)
-    return;
-
-  // Something needs our collapsed borders before we've calculated them. Return
-  // the old ones.
-  if (NeedsSectionRecalc())
-    return;
-
-  collapsed_outer_borders_valid_ = true;
-  if (!ShouldCollapseBorders())
-    return;
-
-  collapsed_outer_border_start_ = 0;
-  collapsed_outer_border_end_ = 0;
-  collapsed_outer_border_before_ = 0;
-  collapsed_outer_border_after_ = 0;
-  collapsed_outer_border_start_overflow_ = 0;
-  collapsed_outer_border_end_overflow_ = 0;
-
-  const auto* top_section = TopNonEmptySection();
-  if (!top_section)
-    return;
-
-  // The table's before outer border width is the maximum before outer border
-  // widths of all cells in the first row. See the CSS 2.1 spec, section 17.6.2.
-  unsigned top_cols = top_section->NumCols(0);
-  for (unsigned col = 0; col < top_cols; ++col) {
-    if (const auto* cell = top_section->PrimaryCellAt(0, col)) {
-      collapsed_outer_border_before_ = std::max(
-          collapsed_outer_border_before_, cell->CollapsedOuterBorderBefore());
-    }
-  }
-
-  // The table's after outer border width is the maximum after outer border
-  // widths of all cells in the last row. See the CSS 2.1 spec, section 17.6.2.
-  const auto* bottom_section = BottomNonEmptySection();
-  DCHECK(bottom_section);
-  unsigned row_index = bottom_section->NumRows() - 1;
-  unsigned bottom_cols = bottom_section->NumCols(row_index);
-  for (unsigned col = 0; col < bottom_cols; ++col) {
-    if (const auto* cell = bottom_section->PrimaryCellAt(row_index, col)) {
-      collapsed_outer_border_after_ = std::max(
-          collapsed_outer_border_after_, cell->CollapsedOuterBorderAfter());
-    }
-  }
-
-  // The table's start and end outer border widths are the border outer widths
-  // of the first and last cells in the first row. See the CSS 2.1 spec,
-  // section 17.6.2.
-  bool first_row = true;
-  unsigned max_border_start = 0;
-  unsigned max_border_end = 0;
-  for (const auto* section = top_section; section;
-       section = SectionBelow(section, kSkipEmptySections)) {
-    for (const auto* row = section->FirstRow(); row; row = row->NextRow()) {
-      if (const auto* cell = row->FirstCell()) {
-        auto border_start = cell->CollapsedOuterBorderStart();
-        if (first_row)
-          collapsed_outer_border_start_ = border_start;
-        max_border_start = std::max(max_border_start, border_start);
-      }
-      if (const auto* cell = row->LastCell()) {
-        auto border_end = cell->CollapsedOuterBorderEnd();
-        if (first_row)
-          collapsed_outer_border_end_ = border_end;
-        max_border_end = std::max(max_border_end, border_end);
-      }
-      first_row = false;
-    }
-  }
-
-  // Record the overflows caused by wider collapsed borders of the first/last
-  // cell in rows other than the first.
-  collapsed_outer_border_start_overflow_ =
-      max_border_start - collapsed_outer_border_start_;
-  collapsed_outer_border_end_overflow_ =
-      max_border_end - collapsed_outer_border_end_;
-}
-
-// LayoutNGTableCellInterface API
-bool LayoutTable::IsFirstCell(const LayoutNGTableCellInterface& cell) const {
-  NOT_DESTROYED();
-  const LayoutTableCell& layout_cell =
-      To<LayoutTableCell>(*cell.ToLayoutObject());
-  return !(CellPreceding(layout_cell) || CellAbove(layout_cell));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_table.h b/third_party/blink/renderer/core/layout/layout_table.h
deleted file mode 100644
index 441ce51..0000000
--- a/third_party/blink/renderer/core/layout/layout_table.h
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010 Apple Inc.
- *               All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/css/css_property_names.h"
-#include "third_party/blink/renderer/core/layout/layout_block.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h"
-#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class LayoutNGTableSectionInterface;
-class LayoutTableCol;
-class LayoutTableCaption;
-class LayoutTableCell;
-class LayoutTableSection;
-class TableLayoutAlgorithm;
-
-enum TableHeightChangingValue { kTableHeightNotChanging, kTableHeightChanging };
-
-// LayoutTable is the LayoutObject associated with
-// display: table or inline-table.
-//
-// LayoutTable is the coordinator for determining the overall table structure.
-// The reason is that LayoutTableSection children have a local view over what
-// their structure is but don't account for other LayoutTableSection. Thus
-// LayoutTable helps keep consistency across LayoutTableSection. See e.g.
-// |m_effectiveColumns| below.
-//
-// LayoutTable expects only 3 types of children:
-// - zero or more LayoutTableCol
-// - zero or more LayoutTableCaption
-// - zero or more LayoutTableSection
-// This is aligned with what HTML5 expects:
-// https://html.spec.whatwg.org/C/#the-table-element
-// with one difference: we allow more than one caption as we follow what
-// CSS expects (https://bugs.webkit.org/show_bug.cgi?id=69773).
-// Those expectations are enforced by LayoutTable::addChild, that wraps unknown
-// children into an anonymous LayoutTableSection. This is what the "generate
-// missing child wrapper" step in CSS mandates in
-// http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes.
-//
-// LayoutTable assumes a pretty strict structure that is mandated by CSS:
-// (note that this structure in HTML is enforced by the HTML5 Parser).
-//
-//                 LayoutTable
-//                 |        |
-//  LayoutTableSection    LayoutTableCaption
-//                 |
-//      LayoutTableRow
-//                 |
-//     LayoutTableCell
-//
-// This means that we have to generate some anonymous table wrappers in order to
-// satisfy the structure. See again
-// http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes.
-// The anonymous table wrappers are inserted in LayoutTable::addChild,
-// LayoutTableSection::addChild, LayoutTableRow::addChild and
-// LayoutObject::addChild.
-//
-// Note that this yields to interesting issues in the insertion code. The DOM
-// code is unaware of the anonymous LayoutObjects and thus can insert
-// LayoutObjects into a different part of the layout tree. An example is:
-//
-// <!DOCTYPE html>
-// <style>
-// tablerow { display: table-row; }
-// tablecell { display: table-cell; border: 5px solid purple; }
-// </style>
-// <tablerow id="firstRow">
-//     <tablecell>Short first row.</tablecell>
-// </tablerow>
-// <tablecell id="cell">Long second row, shows the table structure.</tablecell>
-//
-// The page generates a single anonymous table (LayoutTable) and table row group
-// (LayoutTableSection) to wrap the <tablerow> (#firstRow) and an anonymous
-// table row (LayoutTableRow) for the second <tablecell>.
-// It is possible for JavaScript to insert a new element between these 2
-// <tablecell> (using Node.insertBefore), requiring us to split the anonymous
-// table (or the anonymous table row group) in 2. Also note that even
-// though the second <tablecell> and <tablerow> are siblings in the DOM tree,
-// they are not in the layout tree.
-//
-//
-// Note about absolute column index vs effective column index:
-//
-// To save memory at the expense of massive code complexity, the code tries
-// to coalesce columns. This means that we try to the wider column grouping
-// seen over the LayoutTableSections.
-//
-// Note that this is also a defensive pattern as <td colspan="6666666666">
-// only allocates a single entry in this Vector. This argument is weak
-// though as we cap colspans in HTMLTableCellElement.
-//
-// The following example would have 2 entries [ 3, 2 ] in effectiveColumns():
-// <table>
-//   <tr>
-//     <td colspan="3"></td>
-//     <td colspan="2"></td>
-//   </tr>
-// </table>
-//
-// Columns can be split if we add a row with a different colspan structure.
-// See splitEffectiveColumn() and appendEffectiveColumn() for operations
-// over effectiveColumns() and effectiveColumnPositions().
-//
-// See absoluteColumnToEffectiveColumn() for converting an absolute column
-// index into an index into effectiveColumns() and effectiveColumnPositions().
-
-class CORE_EXPORT LayoutTable final : public LayoutBlock,
-                                      public LayoutNGTableInterface {
- public:
-  explicit LayoutTable(Element*);
-  ~LayoutTable() override;
-  void Trace(Visitor*) const override;
-
-  // Per CSS 3 writing-mode: "The first and second values of the
-  // 'border-spacing' property represent spacing between columns and rows
-  // respectively, not necessarily the horizontal and vertical spacing
-  // respectively".
-  int16_t HBorderSpacing() const final {
-    NOT_DESTROYED();
-    return h_spacing_;
-  }
-  int16_t VBorderSpacing() const final {
-    NOT_DESTROYED();
-    return v_spacing_;
-  }
-
-  bool ShouldCollapseBorders() const final {
-    NOT_DESTROYED();
-    return StyleRef().BorderCollapse() == EBorderCollapse::kCollapse;
-  }
-
-  LayoutUnit BorderLeft() const override;
-  LayoutUnit BorderRight() const override;
-  LayoutUnit BorderTop() const override;
-  LayoutUnit BorderBottom() const override;
-
-  void AddChild(LayoutObject* child,
-                LayoutObject* before_child = nullptr) override;
-
-  struct ColumnStruct {
-    DISALLOW_NEW();
-    explicit ColumnStruct(unsigned initial_span = 1) : span(initial_span) {}
-
-    unsigned span;
-  };
-
-  void ForceSectionsRecalc() final {
-    NOT_DESTROYED();
-    SetNeedsSectionRecalc();
-    RecalcSections();
-  }
-
-  const Vector<ColumnStruct>& EffectiveColumns() const {
-    NOT_DESTROYED();
-    return effective_columns_;
-  }
-  const Vector<int>& EffectiveColumnPositions() const {
-    NOT_DESTROYED();
-    return effective_column_positions_;
-  }
-  void SetEffectiveColumnPosition(unsigned index, int position) {
-    NOT_DESTROYED();
-    // Note that if our horizontal border-spacing changed, our position will
-    // change but not our column's width. In practice, horizontal border-spacing
-    // won't change often.
-    column_logical_width_changed_ |=
-        effective_column_positions_[index] != position;
-    effective_column_positions_[index] = position;
-  }
-
-  LayoutTableSection* Header() const {
-    NOT_DESTROYED();
-    DCHECK(!NeedsSectionRecalc());
-    return head_;
-  }
-  LayoutTableSection* Footer() const {
-    NOT_DESTROYED();
-    DCHECK(!NeedsSectionRecalc());
-    return foot_;
-  }
-  LayoutTableSection* FirstBody() const {
-    NOT_DESTROYED();
-    DCHECK(!NeedsSectionRecalc());
-    return first_body_;
-  }
-
-  void SetRowOffsetFromRepeatingHeader(LayoutUnit offset) {
-    NOT_DESTROYED();
-    row_offset_from_repeating_header_ = offset;
-  }
-  LayoutUnit RowOffsetFromRepeatingHeader() const final {
-    NOT_DESTROYED();
-    return row_offset_from_repeating_header_;
-  }
-
-  void SetRowOffsetFromRepeatingFooter(LayoutUnit offset) {
-    NOT_DESTROYED();
-    row_offset_from_repeating_footer_ = offset;
-  }
-  LayoutUnit RowOffsetFromRepeatingFooter() const final {
-    NOT_DESTROYED();
-    return row_offset_from_repeating_footer_;
-  }
-
-  // These functions return nullptr if the table has no sections.
-  LayoutTableSection* TopSection() const;
-  LayoutTableSection* BottomSection() const;
-
-  // These functions return nullptr if the table has no non-empty sections.
-  LayoutTableSection* TopNonEmptySection() const;
-  LayoutTableSection* BottomNonEmptySection() const;
-
-  unsigned LastEffectiveColumnIndex() const {
-    NOT_DESTROYED();
-    return NumEffectiveColumns() - 1;
-  }
-
-  void SplitEffectiveColumn(unsigned index, unsigned first_span);
-  void AppendEffectiveColumn(unsigned span);
-  unsigned NumEffectiveColumns() const {
-    NOT_DESTROYED();
-    return effective_columns_.size();
-  }
-  unsigned SpanOfEffectiveColumn(unsigned effective_column_index) const {
-    NOT_DESTROYED();
-    return effective_columns_[effective_column_index].span;
-  }
-
-  unsigned AbsoluteColumnToEffectiveColumn(
-      unsigned absolute_column_index) const final {
-    NOT_DESTROYED();
-    if (absolute_column_index < no_cell_colspan_at_least_)
-      return absolute_column_index;
-
-    unsigned effective_column = no_cell_colspan_at_least_;
-    unsigned num_columns = NumEffectiveColumns();
-    for (unsigned c = no_cell_colspan_at_least_;
-         effective_column < num_columns &&
-         c + effective_columns_[effective_column].span - 1 <
-             absolute_column_index;
-         ++effective_column)
-      c += effective_columns_[effective_column].span;
-    return effective_column;
-  }
-
-  unsigned EffectiveColumnToAbsoluteColumn(
-      unsigned effective_column_index) const {
-    NOT_DESTROYED();
-    if (effective_column_index < no_cell_colspan_at_least_)
-      return effective_column_index;
-
-    unsigned c = no_cell_colspan_at_least_;
-    for (unsigned i = no_cell_colspan_at_least_; i < effective_column_index;
-         i++)
-      c += effective_columns_[i].span;
-    return c;
-  }
-
-  LayoutUnit BorderSpacingInRowDirection() const {
-    NOT_DESTROYED();
-    if (unsigned effective_column_count = NumEffectiveColumns())
-      return static_cast<LayoutUnit>(effective_column_count + 1) *
-             HBorderSpacing();
-
-    return LayoutUnit();
-  }
-
-  // The collapsing border model dissallows paddings on table, which is why we
-  // override those functions.
-  // See http://www.w3.org/TR/CSS2/tables.html#collapsing-borders.
-  LayoutUnit PaddingTop() const override;
-  LayoutUnit PaddingBottom() const override;
-  LayoutUnit PaddingLeft() const override;
-  LayoutUnit PaddingRight() const override;
-
-  LayoutUnit BordersPaddingAndSpacingInRowDirection() const {
-    NOT_DESTROYED();
-    // 'border-spacing' only applies to separate borders (see 17.6.1 The
-    // separated borders model).
-    return BorderStart() + BorderEnd() +
-           (ShouldCollapseBorders() ? LayoutUnit()
-                                    : (PaddingStart() + PaddingEnd() +
-                                       BorderSpacingInRowDirection()));
-  }
-
-  // Return the first column or column-group.
-  LayoutTableCol* FirstColumn() const;
-
-  struct ColAndColGroup {
-    STACK_ALLOCATED();
-
-   public:
-    LayoutTableCol* col = nullptr;
-    LayoutTableCol* colgroup = nullptr;
-    bool adjoins_start_border_of_col_group = false;
-    bool adjoins_end_border_of_col_group = false;
-    LayoutTableCol* InnermostColOrColGroup() { return col ? col : colgroup; }
-  };
-  ColAndColGroup ColElementAtAbsoluteColumn(
-      unsigned absolute_column_index) const {
-    NOT_DESTROYED();
-    // The common case is to not have col/colgroup elements, make that case
-    // fast.
-    if (!has_col_elements_)
-      return ColAndColGroup();
-    return SlowColElementAtAbsoluteColumn(absolute_column_index);
-  }
-  bool HasColElements() const {
-    NOT_DESTROYED();
-    return has_col_elements_;
-  }
-
-  bool NeedsSectionRecalc() const {
-    NOT_DESTROYED();
-    return needs_section_recalc_;
-  }
-  void SetNeedsSectionRecalc() {
-    NOT_DESTROYED();
-    if (DocumentBeingDestroyed())
-      return;
-    // For all we know, sections may have been deleted at this point. Don't
-    // keep pointers dangling around.
-    head_ = nullptr;
-    foot_ = nullptr;
-    first_body_ = nullptr;
-
-    needs_section_recalc_ = true;
-    SetNeedsLayoutAndFullPaintInvalidation(
-        layout_invalidation_reason::kTableChanged);
-
-    // Grid structure affects cell adjacence relationships which affect
-    // conflict resolution of collapsed borders.
-    InvalidateCollapsedBorders();
-  }
-
-  LayoutTableSection* SectionAbove(
-      const LayoutTableSection*,
-      SkipEmptySectionsValue = kDoNotSkipEmptySections) const;
-  LayoutTableSection* SectionBelow(
-      const LayoutTableSection*,
-      SkipEmptySectionsValue = kDoNotSkipEmptySections) const;
-
-  // Returns the adjacent cell to the logical top, logical bottom, logical left
-  // and logical right, respectively, of the given cell, in the table's
-  // direction. If there are multiple adjacent cells in the direction due to row
-  // or col spans, returns the primary LayoutTableCell of the first (in DOM
-  // order) adjacent TableGridCell in the direction. Returns nullptr if there
-  // are no adjacent cells in the direction.
-  LayoutTableCell* CellAbove(const LayoutTableCell&) const;
-  LayoutTableCell* CellBelow(const LayoutTableCell&) const;
-  LayoutTableCell* CellPreceding(const LayoutTableCell&) const;
-  LayoutTableCell* CellFollowing(const LayoutTableCell&) const;
-
-  void InvalidateCollapsedBorders();
-  void InvalidateCollapsedBordersForAllCellsIfNeeded();
-
-  bool HasCollapsedBorders() const {
-    NOT_DESTROYED();
-    DCHECK(collapsed_borders_valid_);
-    return has_collapsed_borders_;
-  }
-  bool NeedsAdjustCollapsedBorderJoints() const {
-    NOT_DESTROYED();
-    DCHECK(collapsed_borders_valid_);
-    return needs_adjust_collapsed_border_joints_;
-  }
-
-  bool HasSections() const {
-    NOT_DESTROYED();
-    return Header() || Footer() || FirstBody();
-  }
-
-  void RecalcSectionsIfNeeded() const final {
-    NOT_DESTROYED();
-    if (needs_section_recalc_)
-      RecalcSections();
-  }
-
-  LayoutBox* CreateAnonymousBoxWithSameTypeAs(
-      const LayoutObject* parent) const override;
-
-  void AddCaption(const LayoutTableCaption*);
-  void RemoveCaption(const LayoutTableCaption*);
-  void AddColumn(const LayoutTableCol*);
-  void RemoveColumn(const LayoutTableCol*);
-
-  void PaintBoxDecorationBackground(
-      const PaintInfo&,
-      const PhysicalOffset& paint_offset) const final;
-
-  void PaintMask(const PaintInfo&,
-                 const PhysicalOffset& paint_offset) const final;
-
-  void SubtractCaptionRect(PhysicalRect&) const;
-
-  bool IsLogicalWidthAuto() const;
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutTable";
-  }
-
-  // Whether a table has opaque foreground depends on many factors, e.g. border
-  // spacing, missing cells, etc. For simplicity, just conservatively assume
-  // foreground of all tables are not opaque.
-  bool ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect&,
-                                         unsigned) const override {
-    NOT_DESTROYED();
-    return false;
-  }
-
-  enum WhatToMarkAllCells { kMarkDirtyOnly, kMarkDirtyAndNeedsLayout };
-  void MarkAllCellsWidthsDirtyAndOrNeedsLayout(WhatToMarkAllCells);
-
-  bool IsAbsoluteColumnCollapsed(unsigned absolute_column_index) const;
-
-  bool IsAnyColumnEverCollapsed() const {
-    NOT_DESTROYED();
-    return is_any_column_ever_collapsed_;
-  }
-
-  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
-  void SimplifiedNormalFlowLayout() override;
-
-  RecalcLayoutOverflowResult RecalcLayoutOverflow() final;
-  void RecalcVisualOverflow() final;
-
-  void EnsureIsReadyForPaintInvalidation() override;
-  void InvalidatePaint(const PaintInvalidatorContext&) const override;
-  void ColumnStructureChanged();
-
-  // LayoutNGTableInterface methods start.
-
-  const LayoutNGTableInterface* ToLayoutNGTableInterface() const final {
-    NOT_DESTROYED();
-    return this;
-  }
-  const LayoutObject* ToLayoutObject() const final {
-    NOT_DESTROYED();
-    return this;
-  }
-  LayoutObject* ToMutableLayoutObject() final {
-    NOT_DESTROYED();
-    return this;
-  }
-  LayoutNGTableSectionInterface* FirstBodyInterface() const final;
-  LayoutNGTableSectionInterface* FirstSectionInterface() const final;
-  LayoutNGTableSectionInterface* FirstNonEmptySectionInterface() const final;
-  LayoutNGTableSectionInterface* LastSectionInterface() const final;
-  LayoutNGTableSectionInterface* LastNonEmptySectionInterface() const final;
-  LayoutNGTableSectionInterface* NextSectionInterface(
-      const LayoutNGTableSectionInterface*,
-      SkipEmptySectionsValue) const final;
-  LayoutNGTableSectionInterface* PreviousSectionInterface(
-      const LayoutNGTableSectionInterface*,
-      SkipEmptySectionsValue) const final;
-  bool IsFirstCell(const LayoutNGTableCellInterface&) const final;
-
-  // LayoutNGTableInterface methods end.
-
- private:
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectTable || LayoutBlock::IsOfType(type);
-  }
-
-  void PaintObject(const PaintInfo&,
-                   const PhysicalOffset& paint_offset) const override;
-  void UpdateLayout() override;
-  MinMaxSizes ComputeIntrinsicLogicalWidths() const override;
-  MinMaxSizes PreferredLogicalWidths() const override;
-  bool NodeAtPoint(HitTestResult&,
-                   const HitTestLocation&,
-                   const PhysicalOffset& accumulated_offset,
-                   HitTestPhase) override;
-
-  LayoutUnit BaselinePosition(
-      FontBaseline,
-      bool first_line,
-      LineDirectionMode,
-      LinePositionMode = kPositionOnContainingLine) const override;
-  LayoutUnit FirstLineBoxBaseline() const override;
-  LayoutUnit InlineBlockBaseline(LineDirectionMode) const override;
-
-  ColAndColGroup SlowColElementAtAbsoluteColumn(unsigned col) const;
-
-  void UpdateColumnCache() const;
-  void InvalidateCachedColumns();
-
-  void UpdateLogicalWidth() override;
-
-  LayoutUnit ConvertStyleLogicalWidthToComputedWidth(
-      const Length& style_logical_width,
-      LayoutUnit available_width) const;
-  LayoutUnit ConvertStyleLogicalHeightToComputedHeight(
-      const Length& style_logical_height) const;
-
-  PhysicalRect OverflowClipRect(const PhysicalOffset& location,
-                                OverlayScrollbarClipBehavior =
-                                    kIgnoreOverlayScrollbarSize) const override;
-
-  void ComputeVisualOverflow(bool recompute_floats) final;
-
-  void AddVisualOverflowFromChildren();
-  void AddLayoutOverflowFromChildren() override;
-
-  void RecalcSections() const;
-
-  void UpdateCollapsedOuterBorders() const;
-
-  void LayoutCaption(LayoutTableCaption&, SubtreeLayoutScope&);
-  void LayoutSection(LayoutTableSection&,
-                     SubtreeLayoutScope&,
-                     LayoutUnit logical_left,
-                     TableHeightChangingValue);
-
-  // If any columns are collapsed, populates given vector with how much width is
-  // collapsed in each column. If no columns are collapsed, given vector remains
-  // empty. Logical width of table is adjusted.
-  void AdjustWidthsForCollapsedColumns(Vector<int>&);
-
-  // Return the logical height based on the height, min-height and max-height
-  // properties from CSS. Will return 0 if auto.
-  LayoutUnit LogicalHeightFromStyle() const;
-
-  void DistributeExtraLogicalHeight(int extra_logical_height);
-
-  void SetIsAnyColumnEverCollapsed() {
-    NOT_DESTROYED();
-    is_any_column_ever_collapsed_ = true;
-  }
-
-  // TODO(layout-dev): All mutables in this class are lazily updated by
-  // recalcSections() which is called by various getter methods (e.g.
-  // borderBefore(), borderAfter()).
-  // They allow dirty layout even after DocumentLifecycle::LayoutClean which
-  // seems not proper. crbug.com/538236.
-
-  // Holds spans (number of absolute columns) of effective columns.
-  // See "absolute column index vs effective column index" in comments of
-  // LayoutTable.
-  mutable Vector<ColumnStruct> effective_columns_;
-
-  // Holds the logical layout positions of effective columns, and the last item
-  // (whose index is numEffectiveColumns()) holds the position of the imaginary
-  // column after the last column.
-  // Because of the last item, m_effectiveColumnPositions.size() is always
-  // numEffectiveColumns() + 1.
-  mutable Vector<int> effective_column_positions_;
-
-  // The captions associated with this object.
-  mutable HeapVector<Member<LayoutTableCaption>> captions_;
-
-  // Holds pointers to LayoutTableCol objects for <col>s and <colgroup>s under
-  // this table.
-  // There is no direct relationship between the size of and index into this
-  // vector and those of m_effectiveColumns because they hold different things.
-  mutable HeapVector<Member<LayoutTableCol>> column_layout_objects_;
-
-  mutable Member<LayoutTableSection> head_;
-  mutable Member<LayoutTableSection> foot_;
-  mutable Member<LayoutTableSection> first_body_;
-
-  // The layout algorithm used by this table.
-  //
-  // CSS 2.1 defines 2 types of table layouts toggled with 'table-layout':
-  // fixed (TableLayoutAlgorithmFixed) and auto (TableLayoutAlgorithmAuto).
-  // See http://www.w3.org/TR/CSS21/tables.html#width-layout.
-  //
-  // The layout algorithm is delegated to TableLayoutAlgorithm. This enables
-  // changing 'table-layout' without having to reattach the <table>.
-  //
-  // As the algorithm is dependent on the style, this field is nullptr before
-  // the first style is applied in styleDidChange().
-  Member<TableLayoutAlgorithm> table_layout_;
-
-  // Collapsed borders are SUPER EXPENSIVE to compute. The reason is that we
-  // need to compare a cells border against all the adjoining cells, rows,
-  // row groups, column, column groups and table. Thus we cache the values in
-  // LayoutTableCells and some status here.
-  bool collapsed_borders_valid_ : 1;
-  bool has_collapsed_borders_ : 1;
-  bool needs_adjust_collapsed_border_joints_ : 1;
-  bool needs_invalidate_collapsed_borders_for_all_cells_ : 1;
-  mutable bool collapsed_outer_borders_valid_ : 1;
-
-  // Whether any column in the table section is or has been collapsed.
-  bool is_any_column_ever_collapsed_ : 1;
-
-  mutable bool has_col_elements_ : 1;
-  mutable bool needs_section_recalc_ : 1;
-
-  bool column_logical_width_changed_ : 1;
-  // This flag indicates whether any columns (with or without fixed widths) have
-  // been added or removed since the last layout. If they have, then the true
-  // size of the cell contents needs to be determined with a full layout before
-  // the layout cache is updated. The layout cache can be invalid when layout is
-  // valid (e.g. if the table is being painted for the first time).
-  mutable bool column_structure_changed_ : 1;
-  mutable bool column_layout_objects_valid_ : 1;
-  mutable unsigned no_cell_colspan_at_least_;
-  unsigned CalcNoCellColspanAtLeast() const {
-    NOT_DESTROYED();
-    for (unsigned c = 0; c < NumEffectiveColumns(); c++) {
-      if (effective_columns_[c].span > 1)
-        return c;
-    }
-    return NumEffectiveColumns();
-  }
-
-  LogicalToPhysical<unsigned> LogicalCollapsedOuterBorderToPhysical() const {
-    NOT_DESTROYED();
-    return LogicalToPhysical<unsigned>(
-        StyleRef().GetWritingDirection(), collapsed_outer_border_start_,
-        collapsed_outer_border_end_, collapsed_outer_border_before_,
-        collapsed_outer_border_after_);
-  }
-
-  int16_t h_spacing_;
-  int16_t v_spacing_;
-
-  // See UpdateCollapsedOuterBorders().
-  mutable unsigned collapsed_outer_border_start_;
-  mutable unsigned collapsed_outer_border_end_;
-  mutable unsigned collapsed_outer_border_before_;
-  mutable unsigned collapsed_outer_border_after_;
-  mutable unsigned collapsed_outer_border_start_overflow_;
-  mutable unsigned collapsed_outer_border_end_overflow_;
-
-  LayoutUnit row_offset_from_repeating_header_;
-  LayoutUnit row_offset_from_repeating_footer_;
-  LayoutUnit old_available_logical_height_;
-};
-
-inline LayoutTableSection* LayoutTable::TopSection() const {
-  DCHECK(!NeedsSectionRecalc());
-  if (head_)
-    return head_;
-  if (first_body_)
-    return first_body_;
-  return foot_;
-}
-
-// To<LayoutTable>() helper.
-template <>
-struct DowncastTraits<LayoutTable> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsTable() && !object.IsLayoutNGObject();
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_H_
diff --git a/third_party/blink/renderer/core/layout/layout_table_box_component.cc b/third_party/blink/renderer/core/layout/layout_table_box_component.cc
deleted file mode 100644
index e8ef19f..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_box_component.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2016 The Chromium Authors
-// 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/core/layout/layout_table_box_component.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
-#include "third_party/blink/renderer/core/style/computed_style.h"
-
-namespace blink {
-
-void LayoutTableBoxComponent::Trace(Visitor* visitor) const {
-  visitor->Trace(children_);
-  LayoutBox::Trace(visitor);
-}
-
-void LayoutTableBoxComponent::InvalidateCollapsedBordersOnStyleChange(
-    const LayoutObject& table_part,
-    LayoutTable& table,
-    const StyleDifference& diff,
-    const ComputedStyle& old_style) {
-  if (!table.ShouldCollapseBorders())
-    return;
-  if (!old_style.BorderEquals(table_part.StyleRef()))
-    table.InvalidateCollapsedBorders();
-}
-
-bool LayoutTableBoxComponent::DoCellsHaveDirtyWidth(
-    const LayoutObject& table_part,
-    const LayoutTable& table,
-    const StyleDifference& diff,
-    const ComputedStyle& old_style) {
-  // ComputedStyle::diffNeedsFullLayoutAndPaintInvalidation sets needsFullLayout
-  // when border sizes change: checking diff.needsFullLayout() is an
-  // optimization, not required for correctness.
-  // TODO(dgrogan): Remove tablePart.needsLayout()? Perhaps it was an old
-  // optimization but now it seems that diff.needsFullLayout() implies
-  // tablePart.needsLayout().
-  return diff.NeedsFullLayout() && table_part.NeedsLayout() &&
-         table.ShouldCollapseBorders() &&
-         !old_style.BorderSizeEquals(*table_part.Style());
-}
-
-void LayoutTableBoxComponent::MutableForPainting::UpdatePaintResult(
-    PaintResult paint_result,
-    const CullRect& paint_rect) {
-  // A table row or section may paint large background display item which
-  // contains paint operations of the background in each contained cell.
-  // The display item can be clipped by the paint rect to avoid painting
-  // on areas not interested. If we didn't fully paint and paint rect changes,
-  // we need to invalidate the display item (using setDisplayItemUncached()
-  // because we are already in painting.)
-  auto& box = static_cast<LayoutTableBoxComponent&>(layout_object_);
-  if (box.last_paint_result_ != kFullyPainted &&
-      box.last_paint_rect_ != paint_rect)
-    static_cast<const DisplayItemClient&>(layout_object_).Invalidate();
-
-  box.last_paint_result_ = paint_result;
-  box.last_paint_rect_ = paint_rect;
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_table_box_component.h b/third_party/blink/renderer/core/layout/layout_table_box_component.h
deleted file mode 100644
index 6a9196f..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_box_component.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2016 The Chromium Authors
-// 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_CORE_LAYOUT_LAYOUT_TABLE_BOX_COMPONENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_BOX_COMPONENT_H_
-
-#include "base/check_op.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/paint/paint_result.h"
-#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
-
-namespace blink {
-
-// Common super class for LayoutTableCol, LayoutTableSection and LayoutTableRow.
-// Also provides utility functions for all table parts.
-class CORE_EXPORT LayoutTableBoxComponent : public LayoutBox {
- public:
-  static void InvalidateCollapsedBordersOnStyleChange(
-      const LayoutObject& table_part,
-      LayoutTable&,
-      const StyleDifference&,
-      const ComputedStyle& old_style);
-
-  static bool DoCellsHaveDirtyWidth(const LayoutObject& table_part,
-                                    const LayoutTable&,
-                                    const StyleDifference&,
-                                    const ComputedStyle& old_style);
-
-  void Trace(Visitor*) const override;
-
-  class MutableForPainting : public LayoutObject::MutableForPainting {
-   public:
-    void UpdatePaintResult(PaintResult, const CullRect& paint_rect);
-
-   private:
-    friend class LayoutTableBoxComponent;
-    MutableForPainting(const LayoutTableBoxComponent& box)
-        : LayoutObject::MutableForPainting(box) {}
-  };
-  MutableForPainting GetMutableForPainting() const {
-    NOT_DESTROYED();
-    return MutableForPainting(*this);
-  }
-
-  // Should use TableStyle() instead of own style to determine cell order.
-  const ComputedStyle& TableStyle() const {
-    NOT_DESTROYED();
-    return Table()->StyleRef();
-  }
-
-  BorderValue BorderStartInTableDirection() const {
-    NOT_DESTROYED();
-    return StyleRef().BorderStartUsing(TableStyle());
-  }
-  BorderValue BorderEndInTableDirection() const {
-    NOT_DESTROYED();
-    return StyleRef().BorderEndUsing(TableStyle());
-  }
-  BorderValue BorderBeforeInTableDirection() const {
-    NOT_DESTROYED();
-    return StyleRef().BorderBeforeUsing(TableStyle());
-  }
-  BorderValue BorderAfterInTableDirection() const {
-    NOT_DESTROYED();
-    return StyleRef().BorderAfterUsing(TableStyle());
-  }
-
- protected:
-  explicit LayoutTableBoxComponent(Element* element)
-      : LayoutBox(element), last_paint_result_(kMayBeClippedByCullRect) {
-    NOT_DESTROYED();
-  }
-
-  const LayoutObjectChildList* Children() const {
-    NOT_DESTROYED();
-    return &children_;
-  }
-  LayoutObjectChildList* Children() {
-    NOT_DESTROYED();
-    return &children_;
-  }
-
-  LayoutObject* FirstChild() const {
-    NOT_DESTROYED();
-    DCHECK_EQ(Children(), VirtualChildren());
-    return Children()->FirstChild();
-  }
-  LayoutObject* LastChild() const {
-    NOT_DESTROYED();
-    DCHECK_EQ(Children(), VirtualChildren());
-    return Children()->LastChild();
-  }
-
- private:
-  // Column, section and row's visibility has rules different from other
-  // elements. For example, column's visibility:hidden doesn't apply; row's
-  // visibility:hidden shouldn't hide row's background painted behind visible
-  // cells, etc.
-  bool VisualRectRespectsVisibility() const final {
-    NOT_DESTROYED();
-    return false;
-  }
-
-  // If you have a LayoutTableBoxComponent, use firstChild or lastChild instead.
-  void SlowFirstChild() const = delete;
-  void SlowLastChild() const = delete;
-
-  LayoutObjectChildList* VirtualChildren() override {
-    NOT_DESTROYED();
-    return Children();
-  }
-  const LayoutObjectChildList* VirtualChildren() const override {
-    NOT_DESTROYED();
-    return Children();
-  }
-
-  virtual LayoutTable* Table() const = 0;
-
-  LayoutObjectChildList children_;
-
-  friend class MutableForPainting;
-  PaintResult last_paint_result_;
-  CullRect last_paint_rect_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_BOX_COMPONENT_H_
diff --git a/third_party/blink/renderer/core/layout/layout_table_caption.cc b/third_party/blink/renderer/core/layout/layout_table_caption.cc
deleted file mode 100644
index a7d834fc..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_caption.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2011 Robert Hogan <robert@roberthogan.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-
-namespace blink {
-
-LayoutTableCaption::LayoutTableCaption(ContainerNode* node)
-    : LayoutBlockFlow(node) {}
-
-LayoutTableCaption::~LayoutTableCaption() = default;
-
-LayoutUnit LayoutTableCaption::ContainingBlockLogicalWidthForContent() const {
-  NOT_DESTROYED();
-  LayoutBlock* cb = ContainingBlock();
-  return cb->LogicalWidth();
-}
-
-void LayoutTableCaption::InsertedIntoTree() {
-  NOT_DESTROYED();
-  LayoutBlockFlow::InsertedIntoTree();
-
-  Table()->AddCaption(this);
-}
-
-void LayoutTableCaption::WillBeRemovedFromTree() {
-  NOT_DESTROYED();
-  LayoutBlockFlow::WillBeRemovedFromTree();
-
-  Table()->RemoveCaption(this);
-}
-
-LayoutTable* LayoutTableCaption::Table() const {
-  NOT_DESTROYED();
-  return To<LayoutTable>(Parent());
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_table_caption.h b/third_party/blink/renderer/core/layout/layout_table_caption.h
deleted file mode 100644
index 237128ba..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_caption.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2011 Robert Hogan <robert@roberthogan.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_CAPTION_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_CAPTION_H_
-
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
-
-namespace blink {
-
-class LayoutTable;
-
-// LayoutTableCaption is used to represent a table caption
-// (display: table-caption).
-//
-// Table captions are full block-flows, which is why they inherit from
-// LayoutBlockFlow. This is the only internal table part that allows margins.
-// All other elements simply ignore it to satisfy the table model.
-//
-// This class is very simple as the logic for handling the caption is done in
-// LayoutTable. In particular, the placement and sizing is done in
-// LayoutTable::LayoutCaption. The function is called at different timing
-// depending on the 'caption-side' property: "top" is laid out before table row
-// groups when "bottom" ones are laid out after. This ensures that "top"
-// captions are visually before the row groups and "bottom" ones are after.
-//
-// See http://www.w3.org/TR/CSS21/tables.html#caption-position for the
-// positioning.
-class LayoutTableCaption : public LayoutBlockFlow {
- public:
-  explicit LayoutTableCaption(ContainerNode*);
-  ~LayoutTableCaption() override;
-  LayoutUnit ContainingBlockLogicalWidthForContent() const override;
-
- protected:
-  bool CreatesNewFormattingContext() const final {
-    NOT_DESTROYED();
-    return true;
-  }
-
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectTableCaption || LayoutBlockFlow::IsOfType(type);
-  }
-
- private:
-  void InsertedIntoTree() override;
-  void WillBeRemovedFromTree() override;
-
-  LayoutTable* Table() const;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_CAPTION_H_
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell.cc b/third_party/blink/renderer/core/layout/layout_table_cell.cc
deleted file mode 100644
index bd5ec4e4..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_cell.cc
+++ /dev/null
@@ -1,1265 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc.
- *               All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-
-#include "third_party/blink/renderer/core/css/css_property_value_set.h"
-#include "third_party/blink/renderer/core/css/properties/longhands.h"
-#include "third_party/blink/renderer/core/editing/editing_utilities.h"
-#include "third_party/blink/renderer/core/html/html_table_cell_element.h"
-#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/collapsed_border_value.h"
-#include "third_party/blink/renderer/core/layout/geometry/transform_state.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-#include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
-#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/table_cell_paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/table_cell_painter.h"
-#include "third_party/blink/renderer/platform/wtf/size_assertions.h"
-#include "ui/gfx/geometry/quad_f.h"
-
-namespace blink {
-
-struct SameSizeAsLayoutTableCell : public LayoutBlockFlow,
-                                   public LayoutNGTableCellInterface {
-  unsigned bitfields;
-  int paddings[2];
-  void* pointer1;
-};
-
-struct SameSizeAsCollapsedBorderValue {
-  Color color;
-  unsigned bitfields;
-};
-
-ASSERT_SIZE(LayoutTableCell, SameSizeAsLayoutTableCell);
-ASSERT_SIZE(CollapsedBorderValue, SameSizeAsCollapsedBorderValue);
-
-LayoutTableCell::LayoutTableCell(Element* element)
-    : LayoutBlockFlow(element),
-      absolute_column_index_(kUnsetColumnIndex),
-      cell_children_need_layout_(false),
-      is_spanning_collapsed_row_(false),
-      is_spanning_collapsed_column_(false),
-      collapsed_border_values_valid_(false),
-      collapsed_borders_need_paint_invalidation_(false),
-      intrinsic_padding_before_(0),
-      intrinsic_padding_after_(0) {
-  // We only update the flags when notified of DOM changes in
-  // colSpanOrRowSpanChanged() so we need to set their initial values here in
-  // case something asks for colSpan()/rowSpan() before then.
-  UpdateColAndRowSpanFlags();
-}
-
-void LayoutTableCell::WillBeRemovedFromTree() {
-  NOT_DESTROYED();
-  LayoutBlockFlow::WillBeRemovedFromTree();
-
-  Section()->SetNeedsCellRecalc();
-
-  // When borders collapse, removing a cell can affect the the width of
-  // neighboring cells.
-  LayoutTable* enclosing_table = Table();
-  DCHECK(enclosing_table);
-  if (!enclosing_table->ShouldCollapseBorders())
-    return;
-  if (PreviousCell()) {
-    // TODO(dgrogan): Should this be setChildNeedsLayout or setNeedsLayout?
-    // remove-cell-with-border-box.html only passes with setNeedsLayout but
-    // other places use setChildNeedsLayout.
-    PreviousCell()->SetNeedsLayout(layout_invalidation_reason::kTableChanged);
-    PreviousCell()->SetIntrinsicLogicalWidthsDirty();
-  }
-  if (NextCell()) {
-    // TODO(dgrogan): Same as above re: setChildNeedsLayout vs setNeedsLayout.
-    NextCell()->SetNeedsLayout(layout_invalidation_reason::kTableChanged);
-    NextCell()->SetIntrinsicLogicalWidthsDirty();
-  }
-}
-
-unsigned LayoutTableCell::ParseColSpanFromDOM() const {
-  NOT_DESTROYED();
-  DCHECK(GetNode());
-  // TODO(dgrogan): HTMLTableCellElement::colSpan() already clamps to something
-  // smaller than maxColumnIndex; can we just DCHECK here?
-  if (auto* cell_element = DynamicTo<HTMLTableCellElement>(GetNode()))
-    return std::min<unsigned>(cell_element->colSpan(), kMaxColumnIndex);
-  return 1;
-}
-
-unsigned LayoutTableCell::ParseRowSpanFromDOM() const {
-  NOT_DESTROYED();
-  DCHECK(GetNode());
-  if (auto* cell_element = DynamicTo<HTMLTableCellElement>(GetNode()))
-    return std::min<unsigned>(cell_element->rowSpan(), kMaxRowIndex);
-  return 1;
-}
-
-void LayoutTableCell::UpdateColAndRowSpanFlags() {
-  NOT_DESTROYED();
-  // The vast majority of table cells do not have a colspan or rowspan,
-  // so we keep a bool to know if we need to bother reading from the DOM.
-  has_col_span_ = GetNode() && ParseColSpanFromDOM() != 1;
-  has_row_span_ = GetNode() && ParseRowSpanFromDOM() != 1;
-}
-
-void LayoutTableCell::ColSpanOrRowSpanChanged() {
-  NOT_DESTROYED();
-  DCHECK(GetNode());
-  DCHECK(IsA<HTMLTableCellElement>(*GetNode()));
-
-  UpdateColAndRowSpanFlags();
-
-  SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
-      layout_invalidation_reason::kAttributeChanged);
-  if (Parent() && Section()) {
-    Section()->SetNeedsCellRecalc();
-    if (Table() && Table()->ShouldCollapseBorders())
-      collapsed_borders_need_paint_invalidation_ = true;
-  }
-}
-
-Length LayoutTableCell::LogicalWidthFromColumns(
-    LayoutTableCol* first_col_for_this_cell,
-    const Length& width_from_style) const {
-  NOT_DESTROYED();
-  DCHECK(first_col_for_this_cell);
-  DCHECK_EQ(first_col_for_this_cell,
-            Table()
-                ->ColElementAtAbsoluteColumn(AbsoluteColumnIndex())
-                .InnermostColOrColGroup());
-  LayoutTableCol* table_col = first_col_for_this_cell;
-
-  unsigned col_span_count = ColSpan();
-  int col_width_sum = 0;
-  for (unsigned i = 1; i <= col_span_count; i++) {
-    const Length& col_width = table_col->StyleRef().LogicalWidth();
-
-    // Percentage value should be returned only for colSpan == 1.
-    // Otherwise we return original width for the cell.
-    if (!col_width.IsFixed()) {
-      if (col_span_count > 1)
-        return width_from_style;
-      return col_width;
-    }
-
-    col_width_sum += col_width.Value();
-    table_col = table_col->NextColumn();
-    // If no next <col> tag found for the span we just return what we have for
-    // now.
-    if (!table_col)
-      break;
-  }
-
-  // Column widths specified on <col> apply to the border box of the cell, see
-  // bug 8126.
-  // FIXME: Why is border/padding ignored in the negative width case?
-  if (col_width_sum > 0) {
-    return Length::Fixed(
-        std::max(0, col_width_sum - BorderAndPaddingLogicalWidth().Ceil()));
-  }
-  return Length::Fixed(col_width_sum);
-}
-
-MinMaxSizes LayoutTableCell::PreferredLogicalWidths() const {
-  NOT_DESTROYED();
-  // The child cells rely on the grids up in the sections to do their
-  // computePreferredLogicalWidths work.  Normally the sections are set up
-  // early, as table cells are added, but relayout can cause the cells to be
-  // freed, leaving stale pointers in the sections' grids. We must refresh those
-  // grids before the child cells try to use them.
-  Table()->RecalcSectionsIfNeeded();
-
-  // We don't want the preferred width from children to be affected by any
-  // notional height on the cell, such as can happen when a percent sized image
-  // scales up its width to match the available height. Setting a zero override
-  // height prevents this from happening.
-  auto* mutable_this = const_cast<LayoutTableCell*>(this);
-  LayoutUnit logical_height =
-      HasOverrideLogicalHeight() ? OverrideLogicalHeight() : LayoutUnit(-1);
-  if (logical_height > -1)
-    mutable_this->SetOverrideLogicalHeight(LayoutUnit());
-  MinMaxSizes sizes = LayoutBlockFlow::PreferredLogicalWidths();
-  if (logical_height > -1)
-    mutable_this->SetOverrideLogicalHeight(logical_height);
-
-  if (GetNode() && StyleRef().ShouldWrapLine()) {
-    // See if nowrap was set.
-    Length w = StyleOrColLogicalWidth();
-    const AtomicString& nowrap =
-        To<Element>(GetNode())->FastGetAttribute(html_names::kNowrapAttr);
-    if (!nowrap.IsNull() && w.IsFixed()) {
-      // Nowrap is set, but we didn't actually use it because of the fixed width
-      // set on the cell. Even so, it is a WinIE/Moz trait to make the minwidth
-      // of the cell into the fixed width. They do this even in strict mode, so
-      // do not make this a quirk. Affected the top of hiptop.com.
-      sizes.min_size = std::max(sizes.min_size, LayoutUnit(w.Value()));
-    }
-  }
-
-  return sizes;
-}
-
-void LayoutTableCell::ComputeIntrinsicPadding(int collapsed_height,
-                                              int row_height,
-                                              EVerticalAlign vertical_align,
-                                              SubtreeLayoutScope& layouter) {
-  NOT_DESTROYED();
-  int old_intrinsic_padding_before = IntrinsicPaddingBefore();
-  int old_intrinsic_padding_after = IntrinsicPaddingAfter();
-  int logical_height_without_intrinsic_padding = PixelSnappedLogicalHeight() -
-                                                 old_intrinsic_padding_before -
-                                                 old_intrinsic_padding_after;
-
-  int intrinsic_padding_before = 0;
-  switch (vertical_align) {
-    case EVerticalAlign::kSub:
-    case EVerticalAlign::kSuper:
-    case EVerticalAlign::kTextTop:
-    case EVerticalAlign::kTextBottom:
-    case EVerticalAlign::kLength:
-    case EVerticalAlign::kBaseline: {
-      LayoutUnit baseline = CellBaselinePosition();
-      if (baseline > BorderBefore() + PaddingBefore()) {
-        intrinsic_padding_before = (Section()->RowBaseline(RowIndex()) -
-                                    (baseline - old_intrinsic_padding_before))
-                                       .Round();
-      }
-      break;
-    }
-    case EVerticalAlign::kTop:
-      break;
-    case EVerticalAlign::kMiddle:
-      intrinsic_padding_before = (row_height + collapsed_height -
-                                  logical_height_without_intrinsic_padding) /
-                                 2;
-      break;
-    case EVerticalAlign::kBottom:
-      intrinsic_padding_before = row_height + collapsed_height -
-                                 logical_height_without_intrinsic_padding;
-      break;
-    case EVerticalAlign::kBaselineMiddle:
-      break;
-  }
-
-  int intrinsic_padding_after = row_height -
-                                logical_height_without_intrinsic_padding -
-                                intrinsic_padding_before;
-  SetIntrinsicPaddingBefore(intrinsic_padding_before);
-  SetIntrinsicPaddingAfter(intrinsic_padding_after);
-
-  // FIXME: Changing an intrinsic padding shouldn't trigger a relayout as it
-  // only shifts the cell inside the row but doesn't change the logical height.
-  if (intrinsic_padding_before != old_intrinsic_padding_before ||
-      intrinsic_padding_after != old_intrinsic_padding_after)
-    layouter.SetNeedsLayout(this, layout_invalidation_reason::kPaddingChanged);
-}
-
-void LayoutTableCell::UpdateLogicalWidth() {
-  NOT_DESTROYED();
-}
-
-void LayoutTableCell::SetCellLogicalWidth(int table_layout_logical_width,
-                                          SubtreeLayoutScope& layouter) {
-  NOT_DESTROYED();
-  if (table_layout_logical_width == LogicalWidth())
-    return;
-
-  layouter.SetNeedsLayout(this, layout_invalidation_reason::kSizeChanged);
-
-  SetLogicalWidth(LayoutUnit(table_layout_logical_width));
-  SetCellChildrenNeedLayout(true);
-}
-
-void LayoutTableCell::UpdateLayout() {
-  NOT_DESTROYED();
-  DCHECK(NeedsLayout());
-
-  UpdateBlockLayout(CellChildrenNeedLayout());
-
-  // FIXME: This value isn't the intrinsic content logical height, but we need
-  // to update the value as its used by flexbox layout. crbug.com/367324
-  SetIntrinsicContentLogicalHeight(ContentLogicalHeight());
-
-  SetCellChildrenNeedLayout(false);
-}
-
-LayoutUnit LayoutTableCell::PaddingTop() const {
-  NOT_DESTROYED();
-  auto result =
-      ComputedCSSPaddingTop() + LogicalIntrinsicPaddingToPhysical().Top();
-  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
-  // sub-pixel aware.
-  return StyleRef().IsHorizontalWritingMode() ? LayoutUnit(result.ToInt())
-                                              : result;
-}
-
-LayoutUnit LayoutTableCell::PaddingBottom() const {
-  NOT_DESTROYED();
-  auto result =
-      ComputedCSSPaddingBottom() + LogicalIntrinsicPaddingToPhysical().Bottom();
-  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
-  // sub-pixel aware.
-  return StyleRef().IsHorizontalWritingMode() ? LayoutUnit(result.ToInt())
-                                              : result;
-}
-
-LayoutUnit LayoutTableCell::PaddingLeft() const {
-  NOT_DESTROYED();
-  auto result =
-      ComputedCSSPaddingLeft() + LogicalIntrinsicPaddingToPhysical().Left();
-  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
-  // sub-pixel aware.
-  return StyleRef().IsHorizontalWritingMode() ? result
-                                              : LayoutUnit(result.ToInt());
-}
-
-LayoutUnit LayoutTableCell::PaddingRight() const {
-  NOT_DESTROYED();
-  auto result =
-      ComputedCSSPaddingRight() + LogicalIntrinsicPaddingToPhysical().Right();
-  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
-  // sub-pixel aware.
-  return StyleRef().IsHorizontalWritingMode() ? result
-                                              : LayoutUnit(result.ToInt());
-}
-
-void LayoutTableCell::SetOverrideLogicalHeightFromRowHeight(
-    LayoutUnit row_height) {
-  NOT_DESTROYED();
-  ClearIntrinsicPadding();
-  SetOverrideLogicalHeight(row_height);
-}
-
-PhysicalOffset LayoutTableCell::OffsetFromContainerInternal(
-    const LayoutObject* o,
-    bool ignore_scroll_offset) const {
-  NOT_DESTROYED();
-  DCHECK_EQ(o, Container());
-
-  PhysicalOffset offset =
-      LayoutBlockFlow::OffsetFromContainerInternal(o, ignore_scroll_offset);
-  if (Parent())
-    offset -= ParentBox()->PhysicalLocation();
-
-  return offset;
-}
-
-void LayoutTableCell::SetIsSpanningCollapsedRow(bool spanning_collapsed_row) {
-  NOT_DESTROYED();
-  if (is_spanning_collapsed_row_ != spanning_collapsed_row) {
-    is_spanning_collapsed_row_ = spanning_collapsed_row;
-    SetOverflowClipAxes(ComputeOverflowClipAxes());
-  }
-}
-
-void LayoutTableCell::SetIsSpanningCollapsedColumn(
-    bool spanning_collapsed_column) {
-  NOT_DESTROYED();
-  if (is_spanning_collapsed_column_ != spanning_collapsed_column) {
-    is_spanning_collapsed_column_ = spanning_collapsed_column;
-    SetOverflowClipAxes(ComputeOverflowClipAxes());
-  }
-}
-
-void LayoutTableCell::ComputeVisualOverflow(bool recompute_floats) {
-  NOT_DESTROYED();
-  LayoutBlockFlow::ComputeVisualOverflow(recompute_floats);
-
-  UpdateCollapsedBorderValues();
-  if (!collapsed_border_values_)
-    return;
-
-  // Calculate local visual rect of collapsed borders.
-  // Our border rect already includes the inner halves of the collapsed borders,
-  // so here we get the outer halves.
-  bool rtl = !TableStyle().IsLeftToRightDirection();
-  unsigned left = CollapsedBorderHalfLeft(true);
-  unsigned right = CollapsedBorderHalfRight(true);
-  unsigned top = CollapsedBorderHalfTop(true);
-  unsigned bottom = CollapsedBorderHalfBottom(true);
-
-  // TODO(layout-ng): The following looks incorrect for vertical direction.
-  // This cell's borders may be lengthened to match the widths of orthogonal
-  // borders of adjacent cells. Expand visual overflow to cover the lengthened
-  // parts.
-  if ((left && !rtl) || (right && rtl)) {
-    if (LayoutTableCell* preceding = Table()->CellPreceding(*this)) {
-      top = std::max(top, preceding->CollapsedBorderHalfTop(true));
-      bottom = std::max(bottom, preceding->CollapsedBorderHalfBottom(true));
-    }
-  }
-  if ((left && rtl) || (right && !rtl)) {
-    if (LayoutTableCell* following = Table()->CellFollowing(*this)) {
-      top = std::max(top, following->CollapsedBorderHalfTop(true));
-      bottom = std::max(bottom, following->CollapsedBorderHalfBottom(true));
-    }
-  }
-  if (top) {
-    if (LayoutTableCell* above = Table()->CellAbove(*this)) {
-      left = std::max(left, above->CollapsedBorderHalfLeft(true));
-      right = std::max(right, above->CollapsedBorderHalfRight(true));
-    }
-  }
-  if (bottom) {
-    if (LayoutTableCell* below = Table()->CellBelow(*this)) {
-      left = std::max(left, below->CollapsedBorderHalfLeft(true));
-      right = std::max(right, below->CollapsedBorderHalfRight(true));
-    }
-  }
-
-  LayoutRect rect = BorderBoxRect();
-  rect.ExpandEdges(LayoutUnit(top), LayoutUnit(right), LayoutUnit(bottom),
-                   LayoutUnit(left));
-  collapsed_border_values_->SetLocalVisualRect(rect);
-}
-
-OverflowClipAxes LayoutTableCell::ComputeOverflowClipAxes() const {
-  NOT_DESTROYED();
-  if (IsSpanningCollapsedRow() || IsSpanningCollapsedColumn())
-    return kOverflowClipBothAxis;
-  return LayoutBlockFlow::ComputeOverflowClipAxes();
-}
-
-LayoutUnit LayoutTableCell::CellBaselinePosition() const {
-  NOT_DESTROYED();
-  // <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>:
-  // The baseline of a cell is the baseline of the first in-flow line box in the
-  // cell, or the first in-flow table-row in the cell, whichever comes first. If
-  // there is no such line box or table-row, the baseline is the bottom of
-  // content edge of the cell box.
-  LayoutUnit first_line_baseline = FirstLineBoxBaseline();
-  if (first_line_baseline != -1)
-    return first_line_baseline;
-  return BorderBefore() + PaddingBefore() + ContentLogicalHeight();
-}
-
-// Legacy code does not support orthogonal table cells, and must match
-// row's writing mode.
-void LayoutTableCell::UpdateStyleWritingModeFromRow(const LayoutObject* row) {
-  NOT_DESTROYED();
-  DCHECK_NE(StyleRef().GetWritingMode(), row->StyleRef().GetWritingMode());
-  ComputedStyleBuilder new_style_builder(StyleRef());
-  new_style_builder.SetWritingMode(row->StyleRef().GetWritingMode());
-  new_style_builder.UpdateFontOrientation();
-  SetStyle(new_style_builder.TakeStyle(), LayoutObject::ApplyStyleChanges::kNo);
-  SetHorizontalWritingMode(StyleRef().IsHorizontalWritingMode());
-  UnmarkOrthogonalWritingModeRoot();
-
-  for (LayoutObject* child = FirstChild(); child;
-       child = child->NextSibling()) {
-    if (auto* box_child = DynamicTo<LayoutBox>(child)) {
-      if (box_child->IsOrthogonalWritingModeRoot())
-        box_child->MarkOrthogonalWritingModeRoot();
-      else
-        box_child->UnmarkOrthogonalWritingModeRoot();
-    }
-  }
-}
-
-void LayoutTableCell::StyleDidChange(StyleDifference diff,
-                                     const ComputedStyle* old_style) {
-  NOT_DESTROYED();
-  DCHECK_EQ(StyleRef().Display(), EDisplay::kTableCell);
-
-  if (Parent() &&
-      StyleRef().GetWritingMode() != Parent()->StyleRef().GetWritingMode()) {
-    UpdateStyleWritingModeFromRow(Parent());
-  }
-
-  LayoutBlockFlow::StyleDidChange(diff, old_style);
-  SetHasBoxDecorationBackground(true);
-
-  if (Row() && Section() && Table() && Table()->ShouldCollapseBorders())
-    SetHasNonCollapsedBorderDecoration(false);
-
-  if (!old_style)
-    return;
-
-  if (Parent() && Section() && StyleRef().Height() != old_style->Height())
-    Section()->RowLogicalHeightChanged(Row());
-
-  // Our intrinsic padding pushes us down to align with the baseline of other
-  // cells on the row. If our vertical-align has changed then so will the
-  // padding needed to align with other cells - clear it so we can recalculate
-  // it from scratch.
-  if (StyleRef().VerticalAlign() != old_style->VerticalAlign())
-    ClearIntrinsicPadding();
-
-  if (!Parent())
-    return;
-  LayoutTable* table = Table();
-  if (!table)
-    return;
-
-  if (old_style->Visibility() != StyleRef().Visibility() &&
-      table->ShouldCollapseBorders()) {
-    table->InvalidateCollapsedBorders();
-    collapsed_borders_need_paint_invalidation_ = true;
-  }
-
-  LayoutTableBoxComponent::InvalidateCollapsedBordersOnStyleChange(
-      *this, *table, diff, *old_style);
-
-  if (LayoutTableBoxComponent::DoCellsHaveDirtyWidth(*this, *table, diff,
-                                                     *old_style)) {
-    if (PreviousCell()) {
-      // TODO(dgrogan) Add a web test showing that SetChildNeedsLayout is
-      // needed instead of SetNeedsLayout.
-      PreviousCell()->SetChildNeedsLayout();
-      PreviousCell()->SetIntrinsicLogicalWidthsDirty(kMarkOnlyThis);
-    }
-    if (NextCell()) {
-      // TODO(dgrogan) Add a web test showing that SetChildNeedsLayout is
-      // needed instead of SetNeedsLayout.
-      NextCell()->SetChildNeedsLayout();
-      NextCell()->SetIntrinsicLogicalWidthsDirty(kMarkOnlyThis);
-    }
-  }
-}
-
-static CollapsedBorderValue ChooseBorder(const CollapsedBorderValue& border1,
-                                         const CollapsedBorderValue& border2) {
-  return border1.LessThan(border2) ? border2 : border1;
-}
-
-bool LayoutTableCell::IsInEndColumn() const {
-  NOT_DESTROYED();
-  return Table()->AbsoluteColumnToEffectiveColumn(AbsoluteColumnIndex() +
-                                                  ColSpan() - 1) ==
-         Table()->NumEffectiveColumns() - 1;
-}
-
-const CSSProperty& LayoutTableCell::ResolveBorderProperty(
-    const CSSProperty& property) const {
-  NOT_DESTROYED();
-  return property.ResolveDirectionAwareProperty(TableStyle().Direction(),
-                                                TableStyle().GetWritingMode());
-}
-
-CollapsedBorderValue LayoutTableCell::ComputeCollapsedStartBorder() const {
-  NOT_DESTROYED();
-  LayoutTable* table = Table();
-  bool in_start_column = IsInStartColumn();
-  LayoutTableCell* cell_preceding =
-      in_start_column ? nullptr : table->CellPreceding(*this);
-  // We can use the border shared with |cell_before| if it is valid.
-  if (StartsAtSameRow(cell_preceding) &&
-      cell_preceding->collapsed_border_values_valid_) {
-    return cell_preceding->GetCollapsedBorderValues()
-               ? cell_preceding->GetCollapsedBorderValues()->EndBorder()
-               : CollapsedBorderValue();
-  }
-
-  // For the start border, we need to check, in order of precedence:
-  // (1) Our start border.
-  const Longhand& start_color_property = To<Longhand>(
-      ResolveBorderProperty(GetCSSPropertyBorderInlineStartColor()));
-  const Longhand& end_color_property =
-      To<Longhand>(ResolveBorderProperty(GetCSSPropertyBorderInlineEndColor()));
-  CollapsedBorderValue result(BorderStartInTableDirection(),
-                              ResolveColor(start_color_property),
-                              kBorderPrecedenceCell);
-
-  // (2) The end border of the preceding cell.
-  if (cell_preceding) {
-    CollapsedBorderValue cell_before_adjoining_border =
-        CollapsedBorderValue(cell_preceding->BorderEndInTableDirection(),
-                             cell_preceding->ResolveColor(end_color_property),
-                             kBorderPrecedenceCell);
-    // |result| should be the 2nd argument as |cellBefore| should win in case of
-    // equality per CSS 2.1 (Border conflict resolution, point 4).
-    result = ChooseBorder(cell_before_adjoining_border, result);
-    if (!result.Exists())
-      return result;
-  }
-
-  if (in_start_column) {
-    // (3) Our row's start border.
-    result = ChooseBorder(
-        result,
-        CollapsedBorderValue(Row()->BorderStartInTableDirection(),
-                             Parent()->ResolveColor(start_color_property),
-                             kBorderPrecedenceRow));
-    if (!result.Exists())
-      return result;
-
-    // (4) Our row group's start border.
-    result = ChooseBorder(
-        result,
-        CollapsedBorderValue(Section()->BorderStartInTableDirection(),
-                             Section()->ResolveColor(start_color_property),
-                             kBorderPrecedenceRowGroup));
-    if (!result.Exists())
-      return result;
-  }
-
-  // (5) Our column and column group's start borders.
-  LayoutTable::ColAndColGroup col_and_col_group =
-      table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex());
-  if (col_and_col_group.colgroup &&
-      col_and_col_group.adjoins_start_border_of_col_group) {
-    // Only apply the colgroup's border if this cell touches the colgroup edge.
-    result = ChooseBorder(
-        result,
-        CollapsedBorderValue(
-            col_and_col_group.colgroup->BorderStartInTableDirection(),
-            col_and_col_group.colgroup->ResolveColor(start_color_property),
-            kBorderPrecedenceColumnGroup));
-    if (!result.Exists())
-      return result;
-  }
-  if (col_and_col_group.col) {
-    // Always apply the col's border irrespective of whether this cell touches
-    // it. This is per HTML5: "For the purposes of the CSS table model, the col
-    // element is expected to be treated as if it "was present as many times as
-    // its span attribute specifies".
-    result = ChooseBorder(
-        result, CollapsedBorderValue(
-                    col_and_col_group.col->BorderStartInTableDirection(),
-                    col_and_col_group.col->ResolveColor(start_color_property),
-                    kBorderPrecedenceColumn));
-    if (!result.Exists())
-      return result;
-  }
-
-  // (6) The end border of the preceding column.
-  if (cell_preceding) {
-    col_and_col_group =
-        table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() - 1);
-    // Only apply the colgroup's border if this cell touches the colgroup edge.
-    if (col_and_col_group.colgroup &&
-        col_and_col_group.adjoins_end_border_of_col_group) {
-      result = ChooseBorder(
-          CollapsedBorderValue(
-              col_and_col_group.colgroup->BorderEndInTableDirection(),
-              col_and_col_group.colgroup->ResolveColor(end_color_property),
-              kBorderPrecedenceColumnGroup),
-          result);
-      if (!result.Exists())
-        return result;
-    }
-    // Always apply the col's border irrespective of whether this cell touches
-    // it. This is per HTML5: "For the purposes of the CSS table model, the col
-    // element is expected to be treated as if it "was present as many times as
-    // its span attribute specifies".
-    if (col_and_col_group.col) {
-      result = ChooseBorder(
-          CollapsedBorderValue(
-              col_and_col_group.col->BorderEndInTableDirection(),
-              col_and_col_group.col->ResolveColor(end_color_property),
-              kBorderPrecedenceColumn),
-          result);
-      if (!result.Exists())
-        return result;
-    }
-  }
-
-  if (in_start_column) {
-    // (7) The table's start border.
-    result = ChooseBorder(
-        result, CollapsedBorderValue(table->StyleRef().BorderStart(),
-                                     table->ResolveColor(start_color_property),
-                                     kBorderPrecedenceTable));
-    if (!result.Exists())
-      return result;
-  }
-
-  return result;
-}
-
-CollapsedBorderValue LayoutTableCell::ComputeCollapsedEndBorder() const {
-  NOT_DESTROYED();
-  LayoutTable* table = Table();
-  // Note: We have to use the effective column information instead of whether we
-  // have a cell after as a table doesn't have to be regular (any row can have
-  // less cells than the total cell count).
-  bool in_end_column = IsInEndColumn();
-  LayoutTableCell* cell_following =
-      in_end_column ? nullptr : table->CellFollowing(*this);
-  // We can use the border shared with |cell_after| if it is valid.
-  if (StartsAtSameRow(cell_following) &&
-      cell_following->collapsed_border_values_valid_) {
-    return cell_following->GetCollapsedBorderValues()
-               ? cell_following->GetCollapsedBorderValues()->StartBorder()
-               : CollapsedBorderValue();
-  }
-
-  // For end border, we need to check, in order of precedence:
-  // (1) Our end border.
-  const Longhand& start_color_property = To<Longhand>(
-      ResolveBorderProperty(GetCSSPropertyBorderInlineStartColor()));
-  const Longhand& end_color_property =
-      To<Longhand>(ResolveBorderProperty(GetCSSPropertyBorderInlineEndColor()));
-  CollapsedBorderValue result = CollapsedBorderValue(
-      BorderEndInTableDirection(), ResolveColor(end_color_property),
-      kBorderPrecedenceCell);
-
-  // (2) The start border of the following cell.
-  if (cell_following) {
-    CollapsedBorderValue cell_after_adjoining_border =
-        CollapsedBorderValue(cell_following->BorderStartInTableDirection(),
-                             cell_following->ResolveColor(start_color_property),
-                             kBorderPrecedenceCell);
-    result = ChooseBorder(result, cell_after_adjoining_border);
-    if (!result.Exists())
-      return result;
-  }
-
-  if (in_end_column) {
-    // (3) Our row's end border.
-    result = ChooseBorder(
-        result, CollapsedBorderValue(Row()->BorderEndInTableDirection(),
-                                     Parent()->ResolveColor(end_color_property),
-                                     kBorderPrecedenceRow));
-    if (!result.Exists())
-      return result;
-
-    // (4) Our row group's end border.
-    result = ChooseBorder(
-        result,
-        CollapsedBorderValue(Section()->BorderEndInTableDirection(),
-                             Section()->ResolveColor(end_color_property),
-                             kBorderPrecedenceRowGroup));
-    if (!result.Exists())
-      return result;
-  }
-
-  // (5) Our column and column group's end borders.
-  LayoutTable::ColAndColGroup col_and_col_group =
-      table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan() - 1);
-  if (col_and_col_group.colgroup &&
-      col_and_col_group.adjoins_end_border_of_col_group) {
-    // Only apply the colgroup's border if this cell touches the colgroup edge.
-    result = ChooseBorder(
-        result,
-        CollapsedBorderValue(
-            col_and_col_group.colgroup->BorderEndInTableDirection(),
-            col_and_col_group.colgroup->ResolveColor(end_color_property),
-            kBorderPrecedenceColumnGroup));
-    if (!result.Exists())
-      return result;
-  }
-  if (col_and_col_group.col) {
-    // Always apply the col's border irrespective of whether this cell touches
-    // it. This is per HTML5: "For the purposes of the CSS table model, the col
-    // element is expected to be treated as if it "was present as many times as
-    // its span attribute specifies".
-    result = ChooseBorder(
-        result, CollapsedBorderValue(
-                    col_and_col_group.col->BorderEndInTableDirection(),
-                    col_and_col_group.col->ResolveColor(end_color_property),
-                    kBorderPrecedenceColumn));
-    if (!result.Exists())
-      return result;
-  }
-
-  // (6) The start border of the next column.
-  if (!in_end_column) {
-    col_and_col_group =
-        table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan());
-    if (col_and_col_group.colgroup &&
-        col_and_col_group.adjoins_start_border_of_col_group) {
-      // Only apply the colgroup's border if this cell touches the colgroup
-      // edge.
-      result = ChooseBorder(
-          result,
-          CollapsedBorderValue(
-              col_and_col_group.colgroup->BorderStartInTableDirection(),
-              col_and_col_group.colgroup->ResolveColor(start_color_property),
-              kBorderPrecedenceColumnGroup));
-      if (!result.Exists())
-        return result;
-    }
-    if (col_and_col_group.col) {
-      // Always apply the col's border irrespective of whether this cell touches
-      // it. This is per HTML5: "For the purposes of the CSS table model, the
-      // col element is expected to be treated as if it "was present as many
-      // times as its span attribute specifies".
-      result = ChooseBorder(
-          result, CollapsedBorderValue(
-                      col_and_col_group.col->BorderStartInTableDirection(),
-                      col_and_col_group.col->ResolveColor(start_color_property),
-                      kBorderPrecedenceColumn));
-      if (!result.Exists())
-        return result;
-    }
-  }
-
-  if (in_end_column) {
-    // (7) The table's end border.
-    result = ChooseBorder(
-        result, CollapsedBorderValue(table->StyleRef().BorderEnd(),
-                                     table->ResolveColor(end_color_property),
-                                     kBorderPrecedenceTable));
-    if (!result.Exists())
-      return result;
-  }
-
-  return result;
-}
-
-CollapsedBorderValue LayoutTableCell::ComputeCollapsedBeforeBorder() const {
-  NOT_DESTROYED();
-  LayoutTable* table = Table();
-  LayoutTableCell* cell_above = table->CellAbove(*this);
-  // We can use the border shared with |cell_above| if it is valid.
-  if (StartsAtSameColumn(cell_above) &&
-      cell_above->collapsed_border_values_valid_) {
-    return cell_above->GetCollapsedBorderValues()
-               ? cell_above->GetCollapsedBorderValues()->AfterBorder()
-               : CollapsedBorderValue();
-  }
-
-  // For before border, we need to check, in order of precedence:
-  // (1) Our before border.
-  const Longhand& before_color_property = To<Longhand>(
-      ResolveBorderProperty(GetCSSPropertyBorderBlockStartColor()));
-  const Longhand& after_color_property =
-      To<Longhand>(ResolveBorderProperty(GetCSSPropertyBorderBlockEndColor()));
-  CollapsedBorderValue result = CollapsedBorderValue(
-      StyleRef().BorderBeforeStyle(), StyleRef().BorderBeforeWidth(),
-      ResolveColor(before_color_property), kBorderPrecedenceCell);
-
-  if (cell_above) {
-    // (2) A before cell's after border.
-    result = ChooseBorder(
-        CollapsedBorderValue(cell_above->StyleRef().BorderAfterStyle(),
-                             cell_above->StyleRef().BorderAfterWidth(),
-                             cell_above->ResolveColor(after_color_property),
-                             kBorderPrecedenceCell),
-        result);
-    if (!result.Exists())
-      return result;
-  }
-
-  // (3) Our row's before border.
-  result = ChooseBorder(
-      result,
-      CollapsedBorderValue(Parent()->StyleRef().BorderBeforeStyle(),
-                           Parent()->StyleRef().BorderBeforeWidth(),
-                           Parent()->ResolveColor(before_color_property),
-                           kBorderPrecedenceRow));
-  if (!result.Exists())
-    return result;
-
-  // (4) The previous row's after border.
-  if (cell_above) {
-    LayoutObject* prev_row = nullptr;
-    if (cell_above->Section() == Section())
-      prev_row = Parent()->PreviousSibling();
-    else
-      prev_row = cell_above->Section()->LastRow();
-
-    if (prev_row) {
-      result = ChooseBorder(
-          CollapsedBorderValue(prev_row->StyleRef().BorderAfterStyle(),
-                               prev_row->StyleRef().BorderAfterWidth(),
-                               prev_row->ResolveColor(after_color_property),
-                               kBorderPrecedenceRow),
-          result);
-      if (!result.Exists())
-        return result;
-    }
-  }
-
-  // Now check row groups.
-  LayoutTableSection* curr_section = Section();
-  if (!RowIndex()) {
-    // (5) Our row group's before border.
-    result = ChooseBorder(
-        result,
-        CollapsedBorderValue(curr_section->StyleRef().BorderBeforeStyle(),
-                             curr_section->StyleRef().BorderBeforeWidth(),
-                             curr_section->ResolveColor(before_color_property),
-                             kBorderPrecedenceRowGroup));
-    if (!result.Exists())
-      return result;
-
-    // (6) Previous row group's after border.
-    curr_section = table->SectionAbove(curr_section, kSkipEmptySections);
-    if (curr_section) {
-      result = ChooseBorder(
-          CollapsedBorderValue(curr_section->StyleRef().BorderAfterStyle(),
-                               curr_section->StyleRef().BorderAfterWidth(),
-                               curr_section->ResolveColor(after_color_property),
-                               kBorderPrecedenceRowGroup),
-          result);
-      if (!result.Exists())
-        return result;
-    }
-  }
-
-  if (!curr_section) {
-    // (8) Our column and column group's before borders.
-    LayoutTableCol* col_elt =
-        table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex())
-            .InnermostColOrColGroup();
-    if (col_elt) {
-      result = ChooseBorder(
-          result,
-          CollapsedBorderValue(col_elt->StyleRef().BorderBeforeStyle(),
-                               col_elt->StyleRef().BorderBeforeWidth(),
-                               col_elt->ResolveColor(before_color_property),
-                               kBorderPrecedenceColumn));
-      if (!result.Exists())
-        return result;
-      if (LayoutTableCol* enclosing_column_group =
-              col_elt->EnclosingColumnGroup()) {
-        result = ChooseBorder(
-            result,
-            CollapsedBorderValue(
-                enclosing_column_group->StyleRef().BorderBeforeStyle(),
-                enclosing_column_group->StyleRef().BorderBeforeWidth(),
-                enclosing_column_group->ResolveColor(before_color_property),
-                kBorderPrecedenceColumnGroup));
-        if (!result.Exists())
-          return result;
-      }
-    }
-
-    // (9) The table's before border.
-    result = ChooseBorder(
-        result, CollapsedBorderValue(table->StyleRef().BorderBeforeStyle(),
-                                     table->StyleRef().BorderBeforeWidth(),
-                                     table->ResolveColor(before_color_property),
-                                     kBorderPrecedenceTable));
-    if (!result.Exists())
-      return result;
-  }
-
-  return result;
-}
-
-CollapsedBorderValue LayoutTableCell::ComputeCollapsedAfterBorder() const {
-  NOT_DESTROYED();
-  LayoutTable* table = Table();
-  LayoutTableCell* cell_below = table->CellBelow(*this);
-  // We can use the border shared with |cell_below| if it is valid.
-  if (StartsAtSameColumn(cell_below) &&
-      cell_below->collapsed_border_values_valid_) {
-    return cell_below->GetCollapsedBorderValues()
-               ? cell_below->GetCollapsedBorderValues()->BeforeBorder()
-               : CollapsedBorderValue();
-  }
-
-  // For after border, we need to check, in order of precedence:
-  // (1) Our after border.
-  const Longhand& before_color_property = To<Longhand>(
-      ResolveBorderProperty(GetCSSPropertyBorderBlockStartColor()));
-  const Longhand& after_color_property =
-      To<Longhand>(ResolveBorderProperty(GetCSSPropertyBorderBlockEndColor()));
-  CollapsedBorderValue result = CollapsedBorderValue(
-      StyleRef().BorderAfterStyle(), StyleRef().BorderAfterWidth(),
-      ResolveColor(after_color_property), kBorderPrecedenceCell);
-
-  if (cell_below) {
-    // (2) An after cell's before border.
-    result = ChooseBorder(
-        result,
-        CollapsedBorderValue(cell_below->StyleRef().BorderBeforeStyle(),
-                             cell_below->StyleRef().BorderBeforeWidth(),
-                             cell_below->ResolveColor(before_color_property),
-                             kBorderPrecedenceCell));
-    if (!result.Exists())
-      return result;
-  }
-
-  // (3) Our row's after border. (FIXME: Deal with rowspan!)
-  result = ChooseBorder(
-      result, CollapsedBorderValue(Parent()->StyleRef().BorderAfterStyle(),
-                                   Parent()->StyleRef().BorderAfterWidth(),
-                                   Parent()->ResolveColor(after_color_property),
-                                   kBorderPrecedenceRow));
-  if (!result.Exists())
-    return result;
-
-  // (4) The next row's before border.
-  if (cell_below) {
-    result = ChooseBorder(
-        result, CollapsedBorderValue(
-                    cell_below->Parent()->StyleRef().BorderBeforeStyle(),
-                    cell_below->Parent()->StyleRef().BorderBeforeWidth(),
-                    cell_below->Parent()->ResolveColor(before_color_property),
-                    kBorderPrecedenceRow));
-    if (!result.Exists())
-      return result;
-  }
-
-  // Now check row groups.
-  LayoutTableSection* curr_section = Section();
-  if (RowIndex() + ResolvedRowSpan() >= curr_section->NumRows()) {
-    // (5) Our row group's after border.
-    result = ChooseBorder(
-        result,
-        CollapsedBorderValue(curr_section->StyleRef().BorderAfterStyle(),
-                             curr_section->StyleRef().BorderAfterWidth(),
-                             curr_section->ResolveColor(after_color_property),
-                             kBorderPrecedenceRowGroup));
-    if (!result.Exists())
-      return result;
-
-    // (6) Following row group's before border.
-    curr_section = table->SectionBelow(curr_section, kSkipEmptySections);
-    if (curr_section) {
-      result = ChooseBorder(
-          result, CollapsedBorderValue(
-                      curr_section->StyleRef().BorderBeforeStyle(),
-                      curr_section->StyleRef().BorderBeforeWidth(),
-                      curr_section->ResolveColor(before_color_property),
-                      kBorderPrecedenceRowGroup));
-      if (!result.Exists())
-        return result;
-    }
-  }
-
-  if (!curr_section) {
-    // (8) Our column and column group's after borders.
-    LayoutTableCol* col_elt =
-        table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex())
-            .InnermostColOrColGroup();
-    if (col_elt) {
-      result = ChooseBorder(
-          result,
-          CollapsedBorderValue(col_elt->StyleRef().BorderAfterStyle(),
-                               col_elt->StyleRef().BorderAfterWidth(),
-                               col_elt->ResolveColor(after_color_property),
-                               kBorderPrecedenceColumn));
-      if (!result.Exists())
-        return result;
-      if (LayoutTableCol* enclosing_column_group =
-              col_elt->EnclosingColumnGroup()) {
-        result = ChooseBorder(
-            result,
-            CollapsedBorderValue(
-                enclosing_column_group->StyleRef().BorderAfterStyle(),
-                enclosing_column_group->StyleRef().BorderAfterWidth(),
-                enclosing_column_group->ResolveColor(after_color_property),
-                kBorderPrecedenceColumnGroup));
-        if (!result.Exists())
-          return result;
-      }
-    }
-
-    // (9) The table's after border.
-    result = ChooseBorder(
-        result, CollapsedBorderValue(table->StyleRef().BorderAfterStyle(),
-                                     table->StyleRef().BorderAfterWidth(),
-                                     table->ResolveColor(after_color_property),
-                                     kBorderPrecedenceTable));
-    if (!result.Exists())
-      return result;
-  }
-
-  return result;
-}
-
-LayoutUnit LayoutTableCell::BorderLeft() const {
-  NOT_DESTROYED();
-  return Table()->ShouldCollapseBorders()
-             ? LayoutUnit(CollapsedBorderHalfLeft(false))
-             : LayoutBlockFlow::BorderLeft();
-}
-
-LayoutUnit LayoutTableCell::BorderRight() const {
-  NOT_DESTROYED();
-  return Table()->ShouldCollapseBorders()
-             ? LayoutUnit(CollapsedBorderHalfRight(false))
-             : LayoutBlockFlow::BorderRight();
-}
-
-LayoutUnit LayoutTableCell::BorderTop() const {
-  NOT_DESTROYED();
-  return Table()->ShouldCollapseBorders()
-             ? LayoutUnit(CollapsedBorderHalfTop(false))
-             : LayoutBlockFlow::BorderTop();
-}
-
-LayoutUnit LayoutTableCell::BorderBottom() const {
-  NOT_DESTROYED();
-  return Table()->ShouldCollapseBorders()
-             ? LayoutUnit(CollapsedBorderHalfBottom(false))
-             : LayoutBlockFlow::BorderBottom();
-}
-
-bool LayoutTableCell::IsFirstColumnCollapsed() const {
-  NOT_DESTROYED();
-  if (!RuntimeEnabledFeatures::VisibilityCollapseColumnEnabled())
-    return false;
-  if (!HasSetAbsoluteColumnIndex())
-    return false;
-  return Table()->IsAbsoluteColumnCollapsed(AbsoluteColumnIndex());
-}
-
-void LayoutTableCell::UpdateCollapsedBorderValues() const {
-  NOT_DESTROYED();
-  bool changed = false;
-
-  if (!Table()->ShouldCollapseBorders()) {
-    if (collapsed_border_values_) {
-      changed = true;
-      collapsed_border_values_ = nullptr;
-    }
-  } else {
-    Table()->InvalidateCollapsedBordersForAllCellsIfNeeded();
-    if (Section())
-      Section()->RecalcCellsIfNeeded();
-    if (collapsed_border_values_valid_)
-      return;
-
-    collapsed_border_values_valid_ = true;
-
-    auto new_values = std::make_unique<CollapsedBorderValues>(
-        ComputeCollapsedStartBorder(), ComputeCollapsedEndBorder(),
-        ComputeCollapsedBeforeBorder(), ComputeCollapsedAfterBorder());
-
-    // We need to save collapsed border if has a non-zero width even if it's
-    // invisible because the width affects table layout.
-    if (!new_values->HasNonZeroWidthBorder()) {
-      if (collapsed_border_values_) {
-        changed = true;
-        collapsed_border_values_ = nullptr;
-      }
-    } else if (!collapsed_border_values_ ||
-               !collapsed_border_values_->VisuallyEquals(*new_values)) {
-      changed = true;
-      collapsed_border_values_ = std::move(new_values);
-    }
-  }
-
-  if (!changed && !collapsed_borders_need_paint_invalidation_)
-    return;
-
-  // Invalidate the rows which will paint the collapsed borders.
-  auto row_span = ResolvedRowSpan();
-  for (auto r = RowIndex(); r < RowIndex() + row_span; ++r) {
-    if (auto* row = Section()->RowLayoutObjectAt(r))
-      row->SetShouldDoFullPaintInvalidation();
-  }
-  collapsed_borders_need_paint_invalidation_ = false;
-}
-
-void LayoutTableCell::PaintBoxDecorationBackground(
-    const PaintInfo& paint_info,
-    const PhysicalOffset& paint_offset) const {
-  NOT_DESTROYED();
-  TableCellPainter(*this).PaintBoxDecorationBackground(paint_info,
-                                                       paint_offset);
-}
-
-void LayoutTableCell::PaintMask(const PaintInfo& paint_info,
-                                const PhysicalOffset& paint_offset) const {
-  NOT_DESTROYED();
-  TableCellPainter(*this).PaintMask(paint_info, paint_offset);
-}
-
-void LayoutTableCell::ScrollbarsChanged(bool horizontal_scrollbar_changed,
-                                        bool vertical_scrollbar_changed,
-                                        ScrollbarChangeContext context) {
-  NOT_DESTROYED();
-  LayoutBlock::ScrollbarsChanged(horizontal_scrollbar_changed,
-                                 vertical_scrollbar_changed);
-
-  // The intrinsic-padding adjustment for scrollbars is directly handled by NG.
-  if (IsLayoutNGObject())
-    return;
-
-  if (context != kLayout)
-    return;
-
-  int scrollbar_height = ComputeLogicalScrollbars().BlockSum().ToInt();
-  // Not sure if we should be doing something when a scrollbar goes away or not.
-  if (!scrollbar_height)
-    return;
-
-  // We only care if the scrollbar that affects our intrinsic padding has been
-  // added.
-  if ((IsHorizontalWritingMode() && !horizontal_scrollbar_changed) ||
-      (!IsHorizontalWritingMode() && !vertical_scrollbar_changed))
-    return;
-
-  // Shrink our intrinsic padding as much as possible to accommodate the
-  // scrollbar.
-  if (StyleRef().VerticalAlign() == EVerticalAlign::kMiddle) {
-    LayoutUnit total_height = LogicalHeight();
-    LayoutUnit height_without_intrinsic_padding =
-        total_height - IntrinsicPaddingBefore() - IntrinsicPaddingAfter();
-    total_height -= scrollbar_height;
-    LayoutUnit new_before_padding =
-        (total_height - height_without_intrinsic_padding) / 2;
-    LayoutUnit new_after_padding =
-        total_height - height_without_intrinsic_padding - new_before_padding;
-    SetIntrinsicPaddingBefore(new_before_padding.ToInt());
-    SetIntrinsicPaddingAfter(new_after_padding.ToInt());
-  } else {
-    SetIntrinsicPaddingAfter(IntrinsicPaddingAfter() - scrollbar_height);
-  }
-}
-
-LayoutTableCell* LayoutTableCell::CreateAnonymous(
-    Document* document,
-    scoped_refptr<ComputedStyle> style,
-    LegacyLayout legacy) {
-  LayoutBlockFlow* layout_object =
-      LayoutObjectFactory::CreateTableCell(*document, *style, legacy);
-  layout_object->SetDocumentForAnonymous(document);
-  layout_object->SetStyle(std::move(style));
-  return To<LayoutTableCell>(layout_object);
-}
-
-LayoutBox* LayoutTableCell::CreateAnonymousBoxWithSameTypeAs(
-    const LayoutObject* parent) const {
-  NOT_DESTROYED();
-  return LayoutObjectFactory::CreateAnonymousTableCellWithParent(*parent);
-}
-
-bool LayoutTableCell::BackgroundIsKnownToBeOpaqueInRect(
-    const PhysicalRect& local_rect) const {
-  NOT_DESTROYED();
-  // If this object has layer, the area of collapsed borders should be
-  // transparent to expose the collapsed borders painted on the underlying
-  // layer.
-  if (HasLayer() && Table()->ShouldCollapseBorders())
-    return false;
-  return LayoutBlockFlow::BackgroundIsKnownToBeOpaqueInRect(local_rect);
-}
-
-bool LayoutTableCell::HasLineIfEmpty() const {
-  NOT_DESTROYED();
-  if (GetNode() && IsEditable(*GetNode()))
-    return true;
-
-  return LayoutBlock::HasLineIfEmpty();
-}
-
-void LayoutTableCell::InvalidatePaint(
-    const PaintInvalidatorContext& context) const {
-  NOT_DESTROYED();
-  TableCellPaintInvalidator(*this, context).InvalidatePaint();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell.h b/third_party/blink/renderer/core/layout/layout_table_cell.h
deleted file mode 100644
index 98ceb88..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_cell.h
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2013 Apple Inc.
- *               All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_CELL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_CELL_H_
-
-#include <memory>
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/collapsed_border_value.h"
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_interface.h"
-#include "third_party/blink/renderer/platform/geometry/length_functions.h"
-#include "third_party/blink/renderer/platform/text/writing_mode_utils.h"
-
-namespace blink {
-
-#define BITS_OF_ABSOLUTE_COLUMN_INDEX 25
-static const unsigned kUnsetColumnIndex =
-    (1u << BITS_OF_ABSOLUTE_COLUMN_INDEX) - 1;
-static const unsigned kMaxColumnIndex = kUnsetColumnIndex - 1;
-
-class SubtreeLayoutScope;
-class LayoutNGTableInterface;
-
-// LayoutTableCell is used to represent a table cell (display: table-cell).
-//
-// Because rows are as tall as the tallest cell, cells need to be aligned into
-// the enclosing row space. To achieve this, LayoutTableCell introduces the
-// concept of 'intrinsic padding'. Those 2 paddings are used to shift the box
-// into the row as follows:
-//
-//        --------------------------------
-//        ^  ^
-//        |  |
-//        |  |    cell's border before
-//        |  |
-//        |  v
-//        |  ^
-//        |  |
-//        |  | m_intrinsicPaddingBefore
-//        |  |
-//        |  v
-//        |  -----------------------------
-//        |  |                           |
-// row    |  |   cell's padding box      |
-// height |  |                           |
-//        |  -----------------------------
-//        |  ^
-//        |  |
-//        |  | m_intrinsicPaddingAfter
-//        |  |
-//        |  v
-//        |  ^
-//        |  |
-//        |  |    cell's border after
-//        |  |
-//        v  v
-//        ---------------------------------
-//
-// Note that this diagram is not impacted by collapsing or separate borders
-// (see 'border-collapse').
-// Also there is no margin on table cell (or any internal table element).
-//
-// LayoutTableCell is positioned with respect to the enclosing
-// LayoutTableSection. See callers of
-// LayoutTableSection::setLogicalPositionForCell() for when it is placed.
-class CORE_EXPORT LayoutTableCell : public LayoutBlockFlow,
-                                    public LayoutNGTableCellInterface {
- public:
-  explicit LayoutTableCell(Element*);
-
-  unsigned ColSpan() const final {
-    NOT_DESTROYED();
-    if (!has_col_span_)
-      return 1;
-    return ParseColSpanFromDOM();
-  }
-  unsigned ParsedRowSpan() const {
-    NOT_DESTROYED();
-    if (!has_row_span_)
-      return 1;
-    return ParseRowSpanFromDOM();
-  }
-  unsigned ResolvedRowSpan() const final {
-    NOT_DESTROYED();
-    unsigned row_span = ParsedRowSpan();
-    if (!row_span) {
-      DCHECK(!Section()->NeedsCellRecalc());
-      row_span = Section()->NumRows() - RowIndex();
-    }
-    return std::min<unsigned>(row_span, kMaxRowIndex);
-  }
-
-  // Called from HTMLTableCellElement.
-  void ColSpanOrRowSpanChanged() final;
-
-  void SetAbsoluteColumnIndex(unsigned column) {
-    NOT_DESTROYED();
-    CHECK_LE(column, kMaxColumnIndex);
-    absolute_column_index_ = column;
-  }
-
-  bool HasSetAbsoluteColumnIndex() const {
-    NOT_DESTROYED();
-    return absolute_column_index_ != kUnsetColumnIndex;
-  }
-
-  unsigned AbsoluteColumnIndex() const final {
-    NOT_DESTROYED();
-    DCHECK(HasSetAbsoluteColumnIndex());
-    return absolute_column_index_;
-  }
-
-  LayoutTableRow* Row() const {
-    NOT_DESTROYED();
-    return To<LayoutTableRow>(Parent());
-  }
-  LayoutTableSection* Section() const {
-    NOT_DESTROYED();
-    return To<LayoutTableSection>(Parent()->Parent());
-  }
-  LayoutTable* Table() const {
-    NOT_DESTROYED();
-    return To<LayoutTable>(Parent()->Parent()->Parent());
-  }
-
-  LayoutTableCell* PreviousCell() const;
-  LayoutTableCell* NextCell() const;
-
-  unsigned RowIndex() const final {
-    NOT_DESTROYED();
-    // This function shouldn't be called on a detached cell.
-    DCHECK(Row());
-    return Row()->RowIndex();
-  }
-
-  Length StyleOrColLogicalWidth() const {
-    NOT_DESTROYED();
-    const Length& style_width = StyleRef().LogicalWidth();
-    if (!style_width.IsAuto())
-      return style_width;
-    if (LayoutTableCol* first_column =
-            Table()
-                ->ColElementAtAbsoluteColumn(AbsoluteColumnIndex())
-                .InnermostColOrColGroup())
-      return LogicalWidthFromColumns(first_column, style_width);
-    return style_width;
-  }
-
-  int LogicalHeightFromStyle() const {
-    NOT_DESTROYED();
-    const Length& height = StyleRef().LogicalHeight();
-    int style_logical_height =
-        height.IsSpecified() ? ValueForLength(height, LayoutUnit()).ToInt() : 0;
-
-    // In strict mode, box-sizing: content-box do the right thing and actually
-    // add in the border and padding.
-    // Call computedCSSPadding* directly to avoid including implicitPadding.
-    if (!GetDocument().InQuirksMode() &&
-        StyleRef().BoxSizing() != EBoxSizing::kBorderBox) {
-      style_logical_height +=
-          (ComputedCSSPaddingBefore() + ComputedCSSPaddingAfter()).Floor() +
-          (BorderBefore() + BorderAfter()).Floor();
-    }
-    return style_logical_height;
-  }
-
-  int LogicalHeightForRowSizing() const {
-    NOT_DESTROYED();
-    // FIXME: This function does too much work, and is very hot during table
-    // layout!
-    int adjusted_logical_height =
-        PixelSnappedLogicalHeight() -
-        (IntrinsicPaddingBefore() + IntrinsicPaddingAfter());
-    int style_logical_height = LogicalHeightFromStyle();
-    return max(style_logical_height, adjusted_logical_height);
-  }
-
-  void SetCellLogicalWidth(int constrained_logical_width, SubtreeLayoutScope&);
-
-  // Returns true if a non-column-spanning cell is in a collapsed column, or if
-  // a column-spanning cell starts in a collapsed column.
-  bool IsFirstColumnCollapsed() const;
-
-  LayoutUnit BorderLeft() const override;
-  LayoutUnit BorderRight() const override;
-  LayoutUnit BorderTop() const override;
-  LayoutUnit BorderBottom() const override;
-
-  void UpdateLayout() override;
-
-  LayoutUnit CellBaselinePosition() const;
-  bool IsBaselineAligned() const {
-    NOT_DESTROYED();
-    EVerticalAlign va = StyleRef().VerticalAlign();
-    return va == EVerticalAlign::kBaseline ||
-           va == EVerticalAlign::kTextBottom ||
-           va == EVerticalAlign::kTextTop || va == EVerticalAlign::kSuper ||
-           va == EVerticalAlign::kSub || va == EVerticalAlign::kLength;
-  }
-
-  // Align the cell in the block direction. This is done by calculating an
-  // intrinsic padding before and after the cell contents, so that all cells in
-  // the row get the same logical height.
-  void ComputeIntrinsicPadding(int collapsed_height,
-                               int row_height,
-                               EVerticalAlign,
-                               SubtreeLayoutScope&);
-
-  void ClearIntrinsicPadding() {
-    NOT_DESTROYED();
-    SetIntrinsicPadding(0, 0);
-  }
-
-  int IntrinsicPaddingBefore() const {
-    NOT_DESTROYED();
-    return intrinsic_padding_before_;
-  }
-  int IntrinsicPaddingAfter() const {
-    NOT_DESTROYED();
-    return intrinsic_padding_after_;
-  }
-
-  LayoutUnit PaddingTop() const override;
-  LayoutUnit PaddingBottom() const override;
-  LayoutUnit PaddingLeft() const override;
-  LayoutUnit PaddingRight() const override;
-
-  // TODO(crbug.com/962299): This is incorrect in some cases.
-  gfx::Size PixelSnappedSize() const {
-    NOT_DESTROYED();
-    return FrameRect().PixelSnappedSize();
-  }
-
-  void SetOverrideLogicalHeightFromRowHeight(LayoutUnit);
-
-  void ScrollbarsChanged(bool horizontal_scrollbar_changed,
-                         bool vertical_scrollbar_changed,
-                         ScrollbarChangeContext = kLayout) override;
-
-  bool CellChildrenNeedLayout() const {
-    NOT_DESTROYED();
-    return cell_children_need_layout_;
-  }
-  void SetCellChildrenNeedLayout(bool b = true) {
-    NOT_DESTROYED();
-    cell_children_need_layout_ = b;
-  }
-
-  static LayoutTableCell* CreateAnonymous(Document*,
-                                          scoped_refptr<ComputedStyle>,
-                                          LegacyLayout);
-
-  LayoutBox* CreateAnonymousBoxWithSameTypeAs(
-      const LayoutObject* parent) const override;
-
-  // The table's style determines cell order and cell adjacency in the table.
-  // Collapsed borders also use in table's inline and block directions.
-  const ComputedStyle& TableStyle() const {
-    NOT_DESTROYED();
-    return Table()->StyleRef();
-  }
-
-  BorderValue BorderStartInTableDirection() const {
-    NOT_DESTROYED();
-    return StyleRef().BorderStartUsing(TableStyle());
-  }
-  BorderValue BorderEndInTableDirection() const {
-    NOT_DESTROYED();
-    return StyleRef().BorderEndUsing(TableStyle());
-  }
-  BorderValue BorderBeforeInTableDirection() const {
-    NOT_DESTROYED();
-    return StyleRef().BorderBeforeUsing(TableStyle());
-  }
-  BorderValue BorderAfterInTableDirection() const {
-    NOT_DESTROYED();
-    return StyleRef().BorderAfterUsing(TableStyle());
-  }
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutTableCell";
-  }
-
-  bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const override;
-
-  const CollapsedBorderValues* GetCollapsedBorderValues() const {
-    NOT_DESTROYED();
-    UpdateCollapsedBorderValues();
-    return collapsed_border_values_.get();
-  }
-  void InvalidateCollapsedBorderValues() {
-    NOT_DESTROYED();
-    collapsed_border_values_valid_ = false;
-  }
-
-  // A table cell's location is relative to its containing section.
-  LayoutBox* LocationContainer() const override {
-    NOT_DESTROYED();
-    return Section();
-  }
-
-  bool HasLineIfEmpty() const override;
-
-  static bool CompareInDOMOrder(const LayoutTableCell* cell1,
-                                const LayoutTableCell* cell2) {
-    DCHECK(cell1->Section() == cell2->Section());
-    if (cell1->RowIndex() == cell2->RowIndex())
-      return cell1->absolute_column_index_ < cell2->absolute_column_index_;
-    return cell1->RowIndex() < cell2->RowIndex();
-  }
-
-  // For the following methods, the 'start', 'end', 'before', 'after' directions
-  // are all in the table's inline and block directions.
-  unsigned CollapsedOuterBorderBefore() const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalfBefore(true);
-  }
-  unsigned CollapsedOuterBorderAfter() const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalfAfter(true);
-  }
-  unsigned CollapsedOuterBorderStart() const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalfStart(true);
-  }
-  unsigned CollapsedOuterBorderEnd() const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalfEnd(true);
-  }
-  unsigned CollapsedInnerBorderBefore() const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalfBefore(false);
-  }
-  unsigned CollapsedInnerBorderAfter() const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalfAfter(false);
-  }
-  unsigned CollapsedInnerBorderStart() const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalfStart(false);
-  }
-  unsigned CollapsedInnerBorderEnd() const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalfEnd(false);
-  }
-
-  bool StartsAtSameColumn(const LayoutTableCell* other) const {
-    NOT_DESTROYED();
-    return other && AbsoluteColumnIndex() == other->AbsoluteColumnIndex();
-  }
-  bool EndsAtSameColumn(const LayoutTableCell* other) const {
-    NOT_DESTROYED();
-    return other && AbsoluteColumnIndex() + ColSpan() ==
-                        other->AbsoluteColumnIndex() + other->ColSpan();
-  }
-  bool StartsAtSameRow(const LayoutTableCell* other) const {
-    NOT_DESTROYED();
-    return other && RowIndex() == other->RowIndex();
-  }
-  bool EndsAtSameRow(const LayoutTableCell* other) const {
-    NOT_DESTROYED();
-    return other && RowIndex() + ResolvedRowSpan() ==
-                        other->RowIndex() + other->ResolvedRowSpan();
-  }
-
-  void SetIsSpanningCollapsedRow(bool spanning_collapsed_row);
-
-  bool IsSpanningCollapsedRow() const {
-    NOT_DESTROYED();
-    return is_spanning_collapsed_row_;
-  }
-
-  void SetIsSpanningCollapsedColumn(bool spanningCollapsedColumn);
-
-  bool IsSpanningCollapsedColumn() const {
-    NOT_DESTROYED();
-    return is_spanning_collapsed_column_;
-  }
-
-  void ComputeVisualOverflow(bool recompute_floats) override;
-
-  // LayoutNGTableCellInterface implementation start.
-
-  const LayoutNGTableCellInterface* ToLayoutNGTableCellInterface() const final {
-    NOT_DESTROYED();
-    return this;
-  }
-  const LayoutObject* ToLayoutObject() const final {
-    NOT_DESTROYED();
-    return this;
-  }
-  LayoutObject* ToMutableLayoutObject() final {
-    NOT_DESTROYED();
-    return this;
-  }
-  LayoutNGTableInterface* TableInterface() const final {
-    NOT_DESTROYED();
-    return Table();
-  }
-  LayoutTableCell* NextCellInterface() const final {
-    NOT_DESTROYED();
-    return NextCell();
-  }
-  LayoutTableCell* PreviousCellInterface() const final {
-    NOT_DESTROYED();
-    return PreviousCell();
-  }
-  LayoutNGTableRowInterface* RowInterface() const final {
-    NOT_DESTROYED();
-    return Row();
-  }
-  LayoutNGTableSectionInterface* SectionInterface() const final {
-    NOT_DESTROYED();
-    return Section();
-  }
-
-  // LayoutNGTableCellInterface implementation end.
-
-  MinMaxSizes PreferredLogicalWidths() const override;
-
-  void UpdateStyleWritingModeFromRow(const LayoutObject* row);
-
- protected:
-  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
-
-  void InvalidatePaint(const PaintInvalidatorContext&) const override;
-
-  PhysicalOffset OffsetFromContainerInternal(
-      const LayoutObject*,
-      bool ignore_scroll_offset) const override;
-
-  bool CreatesNewFormattingContext() const final {
-    NOT_DESTROYED();
-    return true;
-  }
-
- protected:
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectTableCell ||
-           type == kLayoutObjectTableCellLegacy ||
-           LayoutBlockFlow::IsOfType(type);
-  }
-
- private:
-  friend class LayoutTableCellTest;
-
-  void WillBeRemovedFromTree() override;
-
-  void UpdateLogicalWidth() override;
-
-  void PaintBoxDecorationBackground(
-      const PaintInfo&,
-      const PhysicalOffset& paint_offset) const override;
-  void PaintMask(const PaintInfo&,
-                 const PhysicalOffset& paint_offset) const override;
-
-  OverflowClipAxes ComputeOverflowClipAxes() const override;
-
-  using CollapsedBorderValuesMethod =
-      const CollapsedBorderValue& (CollapsedBorderValues::*)() const;
-  LogicalToPhysical<CollapsedBorderValuesMethod>
-  CollapsedBorderValuesMethodsPhysical() const {
-    NOT_DESTROYED();
-    return LogicalToPhysical<CollapsedBorderValuesMethod>(
-        // Collapsed border logical directions are in table's directions.
-        TableStyle().GetWritingDirection(), &CollapsedBorderValues::StartBorder,
-        &CollapsedBorderValues::EndBorder, &CollapsedBorderValues::BeforeBorder,
-        &CollapsedBorderValues::AfterBorder);
-  }
-
-  // Give the extra pixel of half collapsed border to top and left.
-  static constexpr bool kInnerHalfPixelAsOneTop = true;
-  static constexpr bool kInnerHalfPixelAsOneRight = false;
-  static constexpr bool kInnerHalfPixelAsOneBottom = false;
-  static constexpr bool kInnerHalfPixelAsOneLeft = true;
-
-  PhysicalToLogical<bool> InnerHalfPixelAsOneLogical() const {
-    NOT_DESTROYED();
-    return PhysicalToLogical<bool>(
-        // Collapsed border logical directions are in table's directions.
-        TableStyle().GetWritingDirection(), kInnerHalfPixelAsOneTop,
-        kInnerHalfPixelAsOneRight, kInnerHalfPixelAsOneBottom,
-        kInnerHalfPixelAsOneLeft);
-  }
-
-  unsigned CollapsedBorderHalfLeft(bool outer) const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalf(kInnerHalfPixelAsOneLeft ^ outer,
-                               CollapsedBorderValuesMethodsPhysical().Left());
-  }
-  unsigned CollapsedBorderHalfRight(bool outer) const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalf(kInnerHalfPixelAsOneRight ^ outer,
-                               CollapsedBorderValuesMethodsPhysical().Right());
-  }
-  unsigned CollapsedBorderHalfTop(bool outer) const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalf(kInnerHalfPixelAsOneTop ^ outer,
-                               CollapsedBorderValuesMethodsPhysical().Top());
-  }
-  unsigned CollapsedBorderHalfBottom(bool outer) const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalf(kInnerHalfPixelAsOneBottom ^ outer,
-                               CollapsedBorderValuesMethodsPhysical().Bottom());
-  }
-
-  // For the following methods, the 'start', 'end', 'before', 'after' directions
-  // are all in the table's inline and block directions.
-  unsigned CollapsedBorderHalfStart(bool outer) const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalf(InnerHalfPixelAsOneLogical().Start() ^ outer,
-                               &CollapsedBorderValues::StartBorder);
-  }
-  unsigned CollapsedBorderHalfEnd(bool outer) const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalf(InnerHalfPixelAsOneLogical().End() ^ outer,
-                               &CollapsedBorderValues::EndBorder);
-  }
-  unsigned CollapsedBorderHalfBefore(bool outer) const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalf(InnerHalfPixelAsOneLogical().Before() ^ outer,
-                               &CollapsedBorderValues::BeforeBorder);
-  }
-  unsigned CollapsedBorderHalfAfter(bool outer) const {
-    NOT_DESTROYED();
-    return CollapsedBorderHalf(InnerHalfPixelAsOneLogical().After() ^ outer,
-                               &CollapsedBorderValues::AfterBorder);
-  }
-
-  unsigned CollapsedBorderHalf(bool half_pixel_as_one,
-                               CollapsedBorderValuesMethod m) const {
-    NOT_DESTROYED();
-    UpdateCollapsedBorderValues();
-    if (const auto* values = GetCollapsedBorderValues())
-      return ((values->*m)().Width() + (half_pixel_as_one ? 1 : 0)) / 2;
-    return 0;
-  }
-
-  LogicalToPhysical<int> LogicalIntrinsicPaddingToPhysical() const {
-    NOT_DESTROYED();
-    return LogicalToPhysical<int>(StyleRef().GetWritingDirection(), 0, 0,
-                                  intrinsic_padding_before_,
-                                  intrinsic_padding_after_);
-  }
-  void SetIntrinsicPaddingBefore(int p) {
-    NOT_DESTROYED();
-    intrinsic_padding_before_ = p;
-  }
-  void SetIntrinsicPaddingAfter(int p) {
-    NOT_DESTROYED();
-    intrinsic_padding_after_ = p;
-  }
-  void SetIntrinsicPadding(int before, int after) {
-    NOT_DESTROYED();
-    SetIntrinsicPaddingBefore(before);
-    SetIntrinsicPaddingAfter(after);
-  }
-
-  bool IsInStartColumn() const {
-    NOT_DESTROYED();
-    return AbsoluteColumnIndex() == 0;
-  }
-  bool IsInEndColumn() const;
-
-  // These functions implement the CSS collapsing border conflict resolution
-  // algorithm http://www.w3.org/TR/CSS2/tables.html#border-conflict-resolution.
-  // They are called during UpdateCollapsedBorderValues(). The 'start', 'end',
-  // 'before', 'after' directions are all in the table's inline and block
-  // directions.
-  inline const CSSProperty& ResolveBorderProperty(const CSSProperty&) const;
-  CollapsedBorderValue ComputeCollapsedStartBorder() const;
-  CollapsedBorderValue ComputeCollapsedEndBorder() const;
-  CollapsedBorderValue ComputeCollapsedBeforeBorder() const;
-  CollapsedBorderValue ComputeCollapsedAfterBorder() const;
-
-  void UpdateCollapsedBorderValues() const;
-
-  Length LogicalWidthFromColumns(LayoutTableCol* first_col_for_this_cell,
-                                 const Length& width_from_style) const;
-
-  void UpdateColAndRowSpanFlags();
-
-  unsigned ParseRowSpanFromDOM() const;
-  unsigned ParseColSpanFromDOM() const;
-
-  void NextSibling() const = delete;
-  void PreviousSibling() const = delete;
-
-  unsigned absolute_column_index_ : BITS_OF_ABSOLUTE_COLUMN_INDEX;
-
-  // When adding or removing bits here, we should also adjust
-  // BITS_OF_ABSOLUTE_COLUMN_INDEX to use remaining bits of a 32-bit word.
-  // Note MSVC will only pack members if they have identical types, hence we use
-  // unsigned instead of bool here.
-  unsigned cell_children_need_layout_ : 1;
-  unsigned has_col_span_ : 1;
-  unsigned has_row_span_ : 1;
-  unsigned is_spanning_collapsed_row_ : 1;
-  unsigned is_spanning_collapsed_column_ : 1;
-
-  // This is set to false when |collapsed_border_values_| needs update.
-  mutable unsigned collapsed_border_values_valid_ : 1;
-  mutable unsigned collapsed_borders_need_paint_invalidation_ : 1;
-  mutable std::unique_ptr<CollapsedBorderValues> collapsed_border_values_;
-
-  // The intrinsic padding.
-  // See class comment for what they are.
-  //
-  // Note: Those fields are using non-subpixel units (int)
-  // because we don't do fractional arithmetic on tables.
-  int intrinsic_padding_before_;
-  int intrinsic_padding_after_;
-};
-
-inline LayoutTableCell* LayoutTableCell::PreviousCell() const {
-  return To<LayoutTableCell>(LayoutObject::PreviousSibling());
-}
-
-inline LayoutTableCell* LayoutTableCell::NextCell() const {
-  return To<LayoutTableCell>(LayoutObject::NextSibling());
-}
-
-inline LayoutTableCell* LayoutTableRow::FirstCell() const {
-  return To<LayoutTableCell>(FirstChild());
-}
-
-inline LayoutTableCell* LayoutTableRow::LastCell() const {
-  return To<LayoutTableCell>(LastChild());
-}
-
-// To<LayoutTableCell>() helper.
-template <>
-struct DowncastTraits<LayoutTableCell> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsTableCellLegacy();
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_CELL_H_
diff --git a/third_party/blink/renderer/core/layout/layout_table_col.cc b/third_party/blink/renderer/core/layout/layout_table_col.cc
deleted file mode 100644
index b78f54a..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_col.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-
-#include "third_party/blink/renderer/core/html/html_table_col_element.h"
-#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-
-namespace blink {
-
-LayoutTableCol::LayoutTableCol(Element* element)
-    : LayoutTableBoxComponent(element), span_(1) {
-  // init LayoutObject attributes
-  SetInline(true);  // our object is not Inline
-  UpdateFromElement();
-}
-
-void LayoutTableCol::StyleDidChange(StyleDifference diff,
-                                    const ComputedStyle* old_style) {
-  NOT_DESTROYED();
-  DCHECK(StyleRef().Display() == EDisplay::kTableColumn ||
-         StyleRef().Display() == EDisplay::kTableColumnGroup);
-
-  LayoutTableBoxComponent::StyleDidChange(diff, old_style);
-
-  if (!old_style)
-    return;
-
-  LayoutTable* table = Table();
-  if (!table)
-    return;
-
-  LayoutTableBoxComponent::InvalidateCollapsedBordersOnStyleChange(
-      *this, *table, diff, *old_style);
-
-  if ((old_style->LogicalWidth() != StyleRef().LogicalWidth()) ||
-      LayoutTableBoxComponent::DoCellsHaveDirtyWidth(*this, *table, diff,
-                                                     *old_style)) {
-    // TODO(dgrogan): Optimization opportunities:
-    // (1) Only mark cells which are affected by this col, not every cell in the
-    //     table.
-    // (2) If only the col width changes and its border width doesn't, do the
-    //     cells need to be marked as needing layout or just given dirty
-    //     widths?
-    table->MarkAllCellsWidthsDirtyAndOrNeedsLayout(
-        LayoutTable::kMarkDirtyAndNeedsLayout);
-  }
-}
-
-void LayoutTableCol::UpdateFromElement() {
-  NOT_DESTROYED();
-  unsigned old_span = span_;
-
-  if (auto* tc = DynamicTo<HTMLTableColElement>(GetNode())) {
-    span_ = tc->span();
-  } else {
-    span_ = 1;
-  }
-  if (span_ != old_span && Style() && Parent()) {
-    SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
-        layout_invalidation_reason::kAttributeChanged);
-  }
-}
-
-void LayoutTableCol::InsertedIntoTree() {
-  NOT_DESTROYED();
-  LayoutTableBoxComponent::InsertedIntoTree();
-  Table()->AddColumn(this);
-}
-
-void LayoutTableCol::WillBeRemovedFromTree() {
-  NOT_DESTROYED();
-  LayoutTableBoxComponent::WillBeRemovedFromTree();
-  Table()->RemoveColumn(this);
-}
-
-bool LayoutTableCol::IsChildAllowed(LayoutObject* child,
-                                    const ComputedStyle& style) const {
-  NOT_DESTROYED();
-  // We cannot use isTableColumn here as style() may return 0.
-  return child->IsLayoutTableCol() && style.Display() == EDisplay::kTableColumn;
-}
-
-bool LayoutTableCol::CanHaveChildren() const {
-  NOT_DESTROYED();
-  // Cols cannot have children. This is actually necessary to fix a bug
-  // with libraries.uc.edu, which makes a <p> be a table-column.
-  return IsTableColumnGroup();
-}
-
-void LayoutTableCol::ClearIntrinsicLogicalWidthsDirtyBits() {
-  NOT_DESTROYED();
-  ClearIntrinsicLogicalWidthsDirty();
-
-  for (LayoutObject* child = FirstChild(); child; child = child->NextSibling())
-    child->ClearIntrinsicLogicalWidthsDirty();
-}
-
-LayoutTable* LayoutTableCol::Table() const {
-  NOT_DESTROYED();
-  LayoutObject* table = Parent();
-  if (table && !table->IsTable())
-    table = table->Parent();
-  return table && table->IsTable() ? To<LayoutTable>(table) : nullptr;
-}
-
-LayoutTableCol* LayoutTableCol::EnclosingColumnGroup() const {
-  NOT_DESTROYED();
-  if (!Parent()->IsLayoutTableCol())
-    return nullptr;
-
-  auto* parent_column_group = To<LayoutTableCol>(Parent());
-  DCHECK(parent_column_group->IsTableColumnGroup());
-  DCHECK(IsTableColumn());
-  return parent_column_group;
-}
-
-LayoutTableCol* LayoutTableCol::NextColumn() const {
-  NOT_DESTROYED();
-  // If |this| is a column-group, the next column is the colgroup's first child
-  // column.
-  if (LayoutObject* first_child = FirstChild())
-    return To<LayoutTableCol>(first_child);
-
-  // Otherwise it's the next column along.
-  LayoutObject* next = NextSibling();
-
-  // Failing that, the child is the last column in a column-group, so the next
-  // column is the next column/column-group after its column-group.
-  if (!next && Parent()->IsLayoutTableCol())
-    next = Parent()->NextSibling();
-
-  for (; next && !next->IsLayoutTableCol(); next = next->NextSibling()) {
-  }
-
-  return To<LayoutTableCol>(next);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_table_col.h b/third_party/blink/renderer/core/layout/layout_table_col.h
deleted file mode 100644
index 9b4023d..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_col.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_COL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_COL_H_
-
-#include "base/notreached.h"
-#include "third_party/blink/renderer/core/layout/layout_table_box_component.h"
-
-namespace blink {
-
-class LayoutTable;
-
-// LayoutTableCol is used to represent table column or column groups
-// (display: table-column and display: table-column-group).
-//
-// The reason to use the same LayoutObject is that both objects behave in a very
-// similar way. The main difference between the 2 is that table-column-group
-// allows table-column children, when table-column don't.
-// Note that this matches how <col> and <colgroup> map to the same class:
-// HTMLTableColElement.
-//
-// In HTML and CSS, table columns and colgroups don't own the cells, they are
-// descendants of the rows.
-// As such table columns and colgroups have a very limited scope in the table:
-// - column / cell sizing (the 'width' property)
-// - background painting (the 'background' property).
-// - border collapse resolution
-//   (http://www.w3.org/TR/CSS21/tables.html#border-conflict-resolution)
-//
-// See http://www.w3.org/TR/CSS21/tables.html#columns for the standard.
-// Note that we don't implement the "visibility: collapse" inheritance to the
-// cells.
-//
-// Because table columns and column groups are placeholder elements (see
-// previous paragraph), they are never laid out and layout() should not be
-// called on them.
-class LayoutTableCol final : public LayoutTableBoxComponent {
- public:
-  explicit LayoutTableCol(Element*);
-
-  void ClearIntrinsicLogicalWidthsDirtyBits();
-
-  // The 'span' attribute in HTML.
-  // For CSS table columns or colgroups, this is always 1.
-  unsigned Span() const {
-    NOT_DESTROYED();
-    return span_;
-  }
-
-  bool IsTableColumnGroupWithColumnChildren() {
-    NOT_DESTROYED();
-    return FirstChild();
-  }
-  bool IsTableColumn() const {
-    NOT_DESTROYED();
-    return StyleRef().Display() == EDisplay::kTableColumn;
-  }
-  bool IsTableColumnGroup() const {
-    NOT_DESTROYED();
-    return StyleRef().Display() == EDisplay::kTableColumnGroup;
-  }
-
-  LayoutTableCol* EnclosingColumnGroup() const;
-
-  // Returns the next column or column-group.
-  LayoutTableCol* NextColumn() const;
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutTableCol";
-  }
-
- private:
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectTableCol || LayoutBox::IsOfType(type);
-  }
-  void UpdateFromElement() override;
-
-  MinMaxSizes PreferredLogicalWidths() const override {
-    NOT_DESTROYED();
-    NOTREACHED();
-    return MinMaxSizes();
-  }
-  MinMaxSizes ComputeIntrinsicLogicalWidths() const final {
-    NOT_DESTROYED();
-    NOTREACHED();
-    return MinMaxSizes();
-  }
-
-  void InsertedIntoTree() override;
-  void WillBeRemovedFromTree() override;
-
-  bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
-  bool CanHaveChildren() const override;
-  PaintLayerType LayerTypeRequired() const override {
-    NOT_DESTROYED();
-    return kNoPaintLayer;
-  }
-
-  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
-
-  LayoutTable* Table() const final;
-
-  unsigned span_;
-};
-
-template <>
-struct DowncastTraits<LayoutTableCol> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsLayoutTableCol() && !object.IsLayoutNGObject();
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_COL_H_
diff --git a/third_party/blink/renderer/core/layout/layout_table_col_test.cc b/third_party/blink/renderer/core/layout/layout_table_col_test.cc
index 0e40effb..f815b1b 100644
--- a/third_party/blink/renderer/core/layout/layout_table_col_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_table_col_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
 
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 
diff --git a/third_party/blink/renderer/core/layout/layout_table_row.cc b/third_party/blink/renderer/core/layout/layout_table_row.cc
deleted file mode 100644
index 14aba72..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_row.cc
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013
-*                Apple Inc.
- *               All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-
-#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/hit_test_result.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
-#include "third_party/blink/renderer/core/layout/layout_state.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
-#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/table_row_painter.h"
-
-namespace blink {
-
-LayoutTableRow::LayoutTableRow(Element* element)
-    : LayoutTableBoxComponent(element), row_index_(kUnsetRowIndex) {
-  // init LayoutObject attributes
-  SetInline(false);  // our object is not Inline
-}
-
-void LayoutTableRow::WillBeRemovedFromTree() {
-  NOT_DESTROYED();
-  LayoutTableBoxComponent::WillBeRemovedFromTree();
-
-  Section()->SetNeedsCellRecalc();
-}
-
-LayoutNGTableCellInterface* LayoutTableRow::FirstCellInterface() const {
-  NOT_DESTROYED();
-  return FirstCell();
-}
-
-LayoutNGTableCellInterface* LayoutTableRow::LastCellInterface() const {
-  NOT_DESTROYED();
-  return LastCell();
-}
-
-void LayoutTableRow::StyleDidChange(StyleDifference diff,
-                                    const ComputedStyle* old_style) {
-  NOT_DESTROYED();
-  DCHECK_EQ(StyleRef().Display(), EDisplay::kTableRow);
-
-  // Legacy tables cannont handle relative/fixed rows.
-  if (StyleRef().HasInFlowPosition()) {
-    ComputedStyleBuilder builder(StyleRef());
-    builder.SetPosition(EPosition::kStatic);
-    SetStyle(builder.TakeStyle(), LayoutObject::ApplyStyleChanges::kNo);
-  }
-
-  LayoutTableBoxComponent::StyleDidChange(diff, old_style);
-  PropagateStyleToAnonymousChildren();
-
-  if (!old_style)
-    return;
-
-  if (Section() && StyleRef().LogicalHeight() != old_style->LogicalHeight())
-    Section()->RowLogicalHeightChanged(this);
-
-  if (!Parent())
-    return;
-  LayoutTable* table = Table();
-  if (!table)
-    return;
-
-  LayoutTableBoxComponent::InvalidateCollapsedBordersOnStyleChange(
-      *this, *table, diff, *old_style);
-
-  if (LayoutTableBoxComponent::DoCellsHaveDirtyWidth(*this, *table, diff,
-                                                     *old_style)) {
-    // If the border width changes on a row, we need to make sure the cells in
-    // the row know to lay out again.
-    // This only happens when borders are collapsed, since they end up affecting
-    // the border sides of the cell itself.
-    for (LayoutBox* child_box = FirstChildBox(); child_box;
-         child_box = child_box->NextSiblingBox()) {
-      if (!child_box->IsTableCell())
-        continue;
-      // TODO(dgrogan) Add a web test showing that SetChildNeedsLayout is
-      // needed instead of SetNeedsLayout.
-      child_box->SetChildNeedsLayout();
-      child_box->SetIntrinsicLogicalWidthsDirty(kMarkOnlyThis);
-    }
-    // Most table componenents can rely on LayoutObject::styleDidChange
-    // to mark the container chain dirty. But LayoutTableSection seems
-    // to never clear its dirty bit, which stops the propagation. So
-    // anything under LayoutTableSection has to restart the propagation
-    // at the table.
-    // TODO(dgrogan): Make LayoutTableSection clear its dirty bit.
-    table->SetIntrinsicLogicalWidthsDirty();
-  }
-
-  // When a row gets collapsed or uncollapsed, it's necessary to check all the
-  // rows to find any cell that may span the current row.
-  if ((old_style->Visibility() == EVisibility::kCollapse) !=
-      (StyleRef().Visibility() == EVisibility::kCollapse)) {
-    for (LayoutTableRow* row = Section()->FirstRow(); row;
-         row = row->NextRow()) {
-      for (LayoutTableCell* cell = row->FirstCell(); cell;
-           cell = cell->NextCell()) {
-        if (!cell->IsSpanningCollapsedRow())
-          continue;
-        unsigned rowIndex = RowIndex();
-        unsigned spanStart = cell->RowIndex();
-        unsigned spanEnd = spanStart + cell->ResolvedRowSpan();
-        if (spanStart <= rowIndex && rowIndex <= spanEnd)
-          cell->SetCellChildrenNeedLayout();
-      }
-    }
-  }
-}
-
-void LayoutTableRow::InvalidatePaint(
-    const PaintInvalidatorContext& context) const {
-  NOT_DESTROYED();
-  LayoutTableBoxComponent::InvalidatePaint(context);
-  if (Table()->HasCollapsedBorders()) {
-    // Repaint the painting layer of the table. The table's composited backing
-    // always paints collapsed borders (even though it uses the row as a
-    // DisplayItemClient).
-    context.ParentContext()->ParentContext()->painting_layer->SetNeedsRepaint();
-  }
-}
-
-void LayoutTableRow::AddChild(LayoutObject* child, LayoutObject* before_child) {
-  NOT_DESTROYED();
-  if (!child->IsTableCell()) {
-    LayoutObject* last = before_child;
-    if (!last)
-      last = LastCell();
-    if (last && last->IsAnonymous() && last->IsTableCell() &&
-        !last->IsBeforeOrAfterContent()) {
-      LayoutTableCell* last_cell = To<LayoutTableCell>(last);
-      if (before_child == last_cell)
-        before_child = last_cell->FirstChild();
-      last_cell->AddChild(child, before_child);
-      return;
-    }
-
-    if (before_child && !before_child->IsAnonymous() &&
-        before_child->Parent() == this) {
-      LayoutObject* cell = before_child->PreviousSibling();
-      if (cell && cell->IsTableCell() && cell->IsAnonymous()) {
-        cell->AddChild(child);
-        return;
-      }
-    }
-
-    // If beforeChild is inside an anonymous cell, insert into the cell.
-    if (last && !last->IsTableCell() && last->Parent() &&
-        last->Parent()->IsAnonymous() &&
-        !last->Parent()->IsBeforeOrAfterContent()) {
-      last->Parent()->AddChild(child, before_child);
-      return;
-    }
-
-    LayoutBlockFlow* cell =
-        LayoutObjectFactory::CreateAnonymousTableCellWithParent(*this);
-    AddChild(cell, before_child);
-    cell->AddChild(child);
-    return;
-  }
-
-  if (before_child && before_child->Parent() != this)
-    before_child = SplitAnonymousBoxesAroundChild(before_child);
-
-  // TODO(crbug.com/1341619): See the TODO in |LayoutTable::AddChild|.
-  // |LayoutNGTableCell| is not a subclass of |LayoutTableCell|.
-  CHECK(IsA<LayoutTableCell>(child));
-  LayoutTableCell* cell = To<LayoutTableCell>(child);
-
-  // In Legacy tables, cell writing mode must match row writing mode.
-  // This adjustment is performed here because is LayoutObject type is
-  // unknown in style_adjuster.cc::AdjustStyleForDisplay
-  if (cell->StyleRef().GetWritingMode() != StyleRef().GetWritingMode()) {
-    cell->UpdateStyleWritingModeFromRow(this);
-  }
-  DCHECK(!before_child || before_child->IsTableCell());
-  LayoutTableBoxComponent::AddChild(cell, before_child);
-
-  // Generated content can result in us having a null section so make sure to
-  // null check our parent.
-  if (Parent()) {
-    Section()->AddCell(cell, this);
-    // When borders collapse, adding a cell can affect the the width of
-    // neighboring cells.
-    LayoutTable* enclosing_table = Table();
-    if (enclosing_table && enclosing_table->ShouldCollapseBorders()) {
-      enclosing_table->InvalidateCollapsedBorders();
-      if (LayoutTableCell* previous_cell = cell->PreviousCell()) {
-        previous_cell->SetNeedsLayoutAndIntrinsicWidthsRecalc(
-            layout_invalidation_reason::kTableChanged);
-      }
-      if (LayoutTableCell* next_cell = cell->NextCell()) {
-        next_cell->SetNeedsLayoutAndIntrinsicWidthsRecalc(
-            layout_invalidation_reason::kTableChanged);
-      }
-    }
-  }
-
-  if (before_child || NextRow() || !cell->ParsedRowSpan())
-    Section()->SetNeedsCellRecalc();
-}
-
-void LayoutTableRow::UpdateLayout() {
-  NOT_DESTROYED();
-  DCHECK(NeedsLayout());
-  bool paginated = View()->GetLayoutState()->IsPaginated();
-
-  for (LayoutTableCell* cell = FirstCell(); cell; cell = cell->NextCell()) {
-    SubtreeLayoutScope layouter(*cell);
-    cell->SetLogicalTop(LogicalTop());
-    if (!cell->NeedsLayout())
-      Section()->MarkChildForPaginationRelayoutIfNeeded(*cell, layouter);
-    if (cell->NeedsLayout()) {
-      // If we are laying out the cell's children clear its intrinsic
-      // padding so it doesn't skew the position of the content.
-      if (cell->CellChildrenNeedLayout())
-        cell->ClearIntrinsicPadding();
-      cell->UpdateLayout();
-    }
-    if (paginated)
-      Section()->UpdateFragmentationInfoForChild(*cell);
-  }
-
-  ClearLayoutOverflow();
-  // We do not call addOverflowFromCell here. The cell are laid out to be
-  // measured above and will be sized correctly in a follow-up phase.
-
-  // We only ever need to issue paint invalidations if our cells didn't, which
-  // means that they didn't need layout, so we know that our bounds didn't
-  // change. This code is just making up for the fact that we did not invalidate
-  // paints in setStyle() because we had a layout hint.
-  if (SelfNeedsLayout()) {
-    for (LayoutTableCell* cell = FirstCell(); cell; cell = cell->NextCell()) {
-      // FIXME: Is this needed when issuing paint invalidations after layout?
-      cell->SetShouldDoFullPaintInvalidation();
-    }
-  }
-
-  // LayoutTableSection::layoutRows will set our logical height and width later,
-  // so it calls updateLayerTransform().
-  ClearNeedsLayout();
-}
-
-// Hit Testing
-bool LayoutTableRow::NodeAtPoint(HitTestResult& result,
-                                 const HitTestLocation& hit_test_location,
-                                 const PhysicalOffset& accumulated_offset,
-                                 HitTestPhase phase) {
-  NOT_DESTROYED();
-  // The row and the cells are all located in the section.
-  const auto* section = Section();
-  PhysicalOffset section_accumulated_offset =
-      accumulated_offset - PhysicalLocation(section);
-
-  // Table rows cannot ever be hit tested.  Effectively they do not exist.
-  // Just forward to our children always.
-  for (LayoutTableCell* cell = LastCell(); cell; cell = cell->PreviousCell()) {
-    if (cell->HasSelfPaintingLayer())
-      continue;
-    PhysicalOffset cell_accumulated_offset =
-        section_accumulated_offset + cell->PhysicalLocation(section);
-    if (cell->NodeAtPoint(result, hit_test_location, cell_accumulated_offset,
-                          phase)) {
-      UpdateHitTestResult(
-          result, hit_test_location.Point() - section_accumulated_offset);
-      return true;
-    }
-  }
-
-  return false;
-}
-
-LayoutBox::PaginationBreakability LayoutTableRow::GetPaginationBreakability(
-    FragmentationEngine engine) const {
-  NOT_DESTROYED();
-  PaginationBreakability breakability =
-      LayoutTableBoxComponent::GetPaginationBreakability(engine);
-  if (breakability == kAllowAnyBreaks) {
-    // Even if the row allows us to break inside, we will want to prevent that
-    // if we have a header group that wants to appear at the top of each page.
-    if (const LayoutTableSection* header = Table()->Header())
-      breakability = header->GetPaginationBreakability(engine);
-  }
-  return breakability;
-}
-
-void LayoutTableRow::Paint(const PaintInfo& paint_info) const {
-  NOT_DESTROYED();
-  TableRowPainter(*this).Paint(paint_info);
-}
-
-LayoutTableRow* LayoutTableRow::CreateAnonymous(Document* document) {
-  LayoutTableRow* layout_object = MakeGarbageCollected<LayoutTableRow>(nullptr);
-  layout_object->SetDocumentForAnonymous(document);
-  return layout_object;
-}
-
-LayoutBox* LayoutTableRow::CreateAnonymousBoxWithSameTypeAs(
-    const LayoutObject* parent) const {
-  NOT_DESTROYED();
-  return LayoutObjectFactory::CreateAnonymousTableRowWithParent(*parent);
-}
-
-void LayoutTableRow::ComputeLayoutOverflow() {
-  NOT_DESTROYED();
-  ClearLayoutOverflow();
-  for (LayoutTableCell* cell = FirstCell(); cell; cell = cell->NextCell())
-    AddLayoutOverflowFromCell(cell);
-}
-
-void LayoutTableRow::RecalcVisualOverflow() {
-  NOT_DESTROYED();
-  unsigned n_cols = Section()->NumCols(RowIndex());
-  for (unsigned c = 0; c < n_cols; c++) {
-    auto* cell = Section()->OriginatingCellAt(RowIndex(), c);
-    if (!cell)
-      continue;
-    if (!cell->HasSelfPaintingLayer())
-      cell->RecalcVisualOverflow();
-  }
-
-  ComputeVisualOverflow();
-}
-
-void LayoutTableRow::ComputeVisualOverflow() {
-  NOT_DESTROYED();
-  const auto& old_visual_rect = VisualOverflowRect();
-  ClearVisualOverflow();
-  AddVisualEffectOverflow();
-
-  for (LayoutTableCell* cell = FirstCell(); cell; cell = cell->NextCell())
-    AddVisualOverflowFromCell(cell);
-  if (old_visual_rect != VisualOverflowRect()) {
-    SetShouldCheckForPaintInvalidation();
-  }
-}
-
-void LayoutTableRow::AddLayoutOverflowFromCell(const LayoutTableCell* cell) {
-  NOT_DESTROYED();
-  LayoutRect cell_layout_overflow_rect =
-      cell->LayoutOverflowRectForPropagation(this);
-
-  // The cell and the row share the section's coordinate system. However
-  // the visual overflow should be determined in the coordinate system of
-  // the row, that's why we shift the rects by cell_row_offset below.
-  LayoutSize cell_row_offset = cell->Location() - Location();
-
-  cell_layout_overflow_rect.Move(cell_row_offset);
-  AddLayoutOverflow(cell_layout_overflow_rect);
-}
-
-void LayoutTableRow::AddVisualOverflowFromCell(const LayoutTableCell* cell) {
-  NOT_DESTROYED();
-  // Note: we include visual overflow of even self-painting cells,
-  // because the row needs to expand to contain their area in order to paint
-  // background and collapsed borders. This is different than any other
-  // LayoutObject subtype.
-
-  // Table row paints its background behind cells. If the cell spans multiple
-  // rows, the row's visual rect should be expanded to cover the cell.
-  // Here don't check background existence to avoid requirement to invalidate
-  // overflow on change of background existence.
-  if (cell->ResolvedRowSpan() > 1) {
-    LayoutRect cell_background_rect = cell->FrameRect();
-    cell_background_rect.MoveBy(-Location());
-    AddSelfVisualOverflow(cell_background_rect);
-  }
-
-  // The cell and the row share the section's coordinate system. However
-  // the visual overflow should be determined in the coordinate system of
-  // the row, that's why we shift the rects by cell_row_offset below.
-  LayoutSize cell_row_offset = cell->Location() - Location();
-
-  // Let the row's self visual overflow cover the cell's whole collapsed
-  // borders. This ensures correct raster invalidation on row border style
-  // change.
-  if (const auto* collapsed_borders = cell->GetCollapsedBorderValues()) {
-    LayoutRect collapsed_border_rect =
-        cell->RectForOverflowPropagation(collapsed_borders->LocalVisualRect());
-    collapsed_border_rect.Move(cell_row_offset);
-    AddSelfVisualOverflow(collapsed_border_rect);
-  }
-
-  LayoutRect cell_visual_overflow_rect =
-      cell->VisualOverflowRectForPropagation();
-  cell_visual_overflow_rect.Move(cell_row_offset);
-  AddContentsVisualOverflow(cell_visual_overflow_rect);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_table_row.h b/third_party/blink/renderer/core/layout/layout_table_row.h
deleted file mode 100644
index b4f2215..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_row.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2009, 2013 Apple Inc.
- *               All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_ROW_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_ROW_H_
-
-#include "base/notreached.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h"
-
-namespace blink {
-
-// There is a window of opportunity to read |m_rowIndex| before it is set when
-// inserting the LayoutTableRow or during LayoutTableSection::recalcCells.
-// This value is used to detect that case.
-static const unsigned kUnsetRowIndex = 0x7FFFFFFF;
-static const unsigned kMaxRowIndex = 0x7FFFFFFE;  // 2,147,483,646
-
-// LayoutTableRow is used to represent a table row (display: table-row).
-//
-// LayoutTableRow is a simple object. The reason is that most operations
-// have to be coordinated at the LayoutTableSection level and thus are
-// handled in LayoutTableSection (see e.g. layoutRows).
-//
-// The table model prevents any layout overflow on rows (but allow visual
-// overflow). For row height, it is defined as "the maximum of the row's
-// computed 'height', the computed 'height' of each cell in the row, and
-// the minimum height (MIN) required by  the cells" (CSS 2.1 - section 17.5.3).
-// Note that this means that rows and cells differ from other LayoutObject as
-// they will ignore 'height' in some situation (when other LayoutObject just
-// allow some layout overflow to occur).
-//
-// LayoutTableRow doesn't establish a containing block for the underlying
-// LayoutTableCells. That's why it inherits from LayoutTableBoxComponent and not
-// LayoutBlock.
-// One oddity is that LayoutTableRow doesn't establish a new coordinate system
-// for its children. LayoutTableCells are positioned with respect to the
-// enclosing LayoutTableSection (this object's parent()). This particularity is
-// why functions accumulating offset while walking the tree have to special case
-// LayoutTableRow (see e.g. PaintInvalidatorContext or
-// LayoutBox::PositionFromPoint()).
-//
-// LayoutTableRow is also positioned with respect to the enclosing
-// LayoutTableSection. See LayoutTableSection::layoutRows() for the placement
-// logic.
-class CORE_EXPORT LayoutTableRow final : public LayoutTableBoxComponent,
-                                         public LayoutNGTableRowInterface {
- public:
-  explicit LayoutTableRow(Element*);
-
-  LayoutTableCell* FirstCell() const;
-  LayoutTableCell* LastCell() const;
-
-  LayoutTableRow* PreviousRow() const;
-  LayoutTableRow* NextRow() const;
-
-  LayoutTableSection* Section() const {
-    NOT_DESTROYED();
-    return To<LayoutTableSection>(Parent());
-  }
-  LayoutTable* Table() const final {
-    NOT_DESTROYED();
-    return To<LayoutTable>(Parent()->Parent());
-  }
-
-  static LayoutTableRow* CreateAnonymous(Document*);
-  LayoutBox* CreateAnonymousBoxWithSameTypeAs(
-      const LayoutObject* parent) const override;
-
-  void SetRowIndex(unsigned row_index) {
-    NOT_DESTROYED();
-    CHECK_LE(row_index, kMaxRowIndex);
-    row_index_ = row_index;
-  }
-
-  bool RowIndexWasSet() const {
-    NOT_DESTROYED();
-    return row_index_ != kUnsetRowIndex;
-  }
-  unsigned RowIndex() const final {
-    NOT_DESTROYED();
-    DCHECK(RowIndexWasSet());
-    DCHECK(
-        !Section() ||
-        !Section()
-             ->NeedsCellRecalc());  // index may be bogus if cells need recalc.
-    return row_index_;
-  }
-
-  bool NodeAtPoint(HitTestResult&,
-                   const HitTestLocation&,
-                   const PhysicalOffset& accumulated_offset,
-                   HitTestPhase) override;
-
-  PaginationBreakability GetPaginationBreakability(
-      FragmentationEngine) const final;
-
-  void ComputeLayoutOverflow();
-
-  void RecalcVisualOverflow() override;
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutTableRow";
-  }
-
-  // Whether a row has opaque background depends on many factors, e.g. border
-  // spacing, border collapsing, missing cells, etc.
-  // For simplicity, just conservatively assume all table rows are not opaque.
-  bool ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect&,
-                                         unsigned) const override {
-    NOT_DESTROYED();
-    return false;
-  }
-  bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const override {
-    NOT_DESTROYED();
-    return false;
-  }
-
-  void InvalidatePaint(const PaintInvalidatorContext&) const final;
-
-  // LayoutNGTableRowInterface methods start.
-
-  const LayoutNGTableRowInterface* ToLayoutNGTableRowInterface() const final {
-    NOT_DESTROYED();
-    return this;
-  }
-  const LayoutObject* ToLayoutObject() const final {
-    NOT_DESTROYED();
-    return this;
-  }
-  LayoutNGTableInterface* TableInterface() const final {
-    NOT_DESTROYED();
-    return Table();
-  }
-  LayoutNGTableSectionInterface* SectionInterface() const final {
-    NOT_DESTROYED();
-    return Section();
-  }
-  LayoutNGTableRowInterface* NextRowInterface() const final {
-    NOT_DESTROYED();
-    return NextRow();
-  }
-  LayoutNGTableRowInterface* PreviousRowInterface() const final {
-    NOT_DESTROYED();
-    return PreviousRow();
-  }
-  LayoutNGTableCellInterface* FirstCellInterface() const final;
-  LayoutNGTableCellInterface* LastCellInterface() const final;
-
-  // LayoutNGTableRowInterface methods end.
-
- private:
-  MinMaxSizes ComputeIntrinsicLogicalWidths() const final {
-    NOT_DESTROYED();
-    NOTREACHED();
-    return MinMaxSizes();
-  }
-
-  void ComputeVisualOverflow();
-  void AddLayoutOverflowFromCell(const LayoutTableCell*);
-  void AddVisualOverflowFromCell(const LayoutTableCell*);
-
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectTableRow ||
-           LayoutTableBoxComponent::IsOfType(type);
-  }
-
-  void WillBeRemovedFromTree() override;
-
-  void AddChild(LayoutObject* child,
-                LayoutObject* before_child = nullptr) override;
-  void UpdateLayout() override;
-
-  PaintLayerType LayerTypeRequired() const override {
-    NOT_DESTROYED();
-    if (HasTransformRelatedProperty() || HasHiddenBackface() ||
-        CreatesGroup() || StyleRef().ShouldCompositeForCurrentAnimations() ||
-        IsStickyPositioned())
-      return kNormalPaintLayer;
-
-    if (HasNonVisibleOverflow())
-      return kOverflowClipPaintLayer;
-
-    return kNoPaintLayer;
-  }
-
-  void Paint(const PaintInfo&) const override;
-
-  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
-
-  void NextSibling() const = delete;
-  void PreviousSibling() const = delete;
-
-  // This field should never be read directly. It should be read through
-  // rowIndex() above instead. This is to ensure that we never read this
-  // value before it is set.
-  unsigned row_index_ : 31;
-};
-
-template <>
-struct DowncastTraits<LayoutTableRow> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsTableRow() && !object.IsLayoutNGObject();
-  }
-};
-
-inline LayoutTableRow* LayoutTableRow::PreviousRow() const {
-  return To<LayoutTableRow>(LayoutObject::PreviousSibling());
-}
-
-inline LayoutTableRow* LayoutTableRow::NextRow() const {
-  return To<LayoutTableRow>(LayoutObject::NextSibling());
-}
-
-inline LayoutTableRow* LayoutTableSection::FirstRow() const {
-  return To<LayoutTableRow>(FirstChild());
-}
-
-inline LayoutTableRow* LayoutTableSection::LastRow() const {
-  return To<LayoutTableRow>(LastChild());
-}
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_ROW_H_
diff --git a/third_party/blink/renderer/core/layout/layout_table_row_test.cc b/third_party/blink/renderer/core/layout/layout_table_row_test.cc
deleted file mode 100644
index 2e1582dd..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_row_test.cc
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-
-#include "build/build_config.h"
-#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
-
-namespace blink {
-
-namespace {
-
-class LayoutTableRowDeathTest : public RenderingTest {
- protected:
-  void SetUp() override {
-    RenderingTest::SetUp();
-    row_ = LayoutTableRow::CreateAnonymous(&GetDocument());
-  }
-
-  void TearDown() override { row_->Destroy(); }
-
-  Persistent<LayoutTableRow> row_;
-};
-
-TEST_F(LayoutTableRowDeathTest, CanSetRow) {
-  static const unsigned kRowIndex = 10;
-  row_->SetRowIndex(kRowIndex);
-  EXPECT_EQ(kRowIndex, row_->RowIndex());
-}
-
-TEST_F(LayoutTableRowDeathTest, CanSetRowToMaxRowIndex) {
-  row_->SetRowIndex(kMaxRowIndex);
-  EXPECT_EQ(kMaxRowIndex, row_->RowIndex());
-}
-
-// Death tests don't work properly on Android.
-#if defined(GTEST_HAS_DEATH_TEST) && !BUILDFLAG(IS_ANDROID)
-
-TEST_F(LayoutTableRowDeathTest, CrashIfRowOverflowOnSetting) {
-  ASSERT_DEATH(row_->SetRowIndex(kMaxRowIndex + 1), "");
-}
-
-TEST_F(LayoutTableRowDeathTest, CrashIfSettingUnsetRowIndex) {
-  ASSERT_DEATH(row_->SetRowIndex(kUnsetRowIndex), "");
-}
-
-#endif
-
-class LayoutTableRowTest : public RenderingTest {
- protected:
-  LayoutBox* GetRowByElementId(const char* id) {
-    return GetLayoutBoxByElementId(id);
-  }
-};
-
-TEST_F(LayoutTableRowTest,
-       BackgroundIsKnownToBeOpaqueWithLayerAndCollapsedBorder) {
-  SetBodyInnerHTML(R"HTML(
-    <table style='border-collapse: collapse'>
-      <tr id='row' style='will-change: transform;
-          background-color: blue'>
-        <td>Cell</td>
-      </tr>
-    </table>
-  )HTML");
-
-  EXPECT_FALSE(GetRowByElementId("row")->BackgroundIsKnownToBeOpaqueInRect(
-      PhysicalRect(0, 0, 1, 1)));
-}
-
-TEST_F(LayoutTableRowTest, BackgroundIsKnownToBeOpaqueWithBorderSpacing) {
-  SetBodyInnerHTML(R"HTML(
-    <table style='border-spacing: 10px'>
-      <tr id='row' style='background-color: blue'><td>Cell</td></tr>
-    </table>
-  )HTML");
-
-  EXPECT_FALSE(GetRowByElementId("row")->BackgroundIsKnownToBeOpaqueInRect(
-      PhysicalRect(0, 0, 1, 1)));
-}
-
-TEST_F(LayoutTableRowTest, BackgroundIsKnownToBeOpaqueWithEmptyCell) {
-  SetBodyInnerHTML(R"HTML(
-    <table style='border-spacing: 10px'>
-      <tr id='row' style='background-color: blue'><td>Cell</td></tr>
-      <tr style='background-color: blue'><td>Cell</td><td>Cell</td></tr>
-    </table>
-  )HTML");
-
-  EXPECT_FALSE(GetRowByElementId("row")->BackgroundIsKnownToBeOpaqueInRect(
-      PhysicalRect(0, 0, 1, 1)));
-}
-
-TEST_F(LayoutTableRowTest, VisualOverflow) {
-  // +---+---+---+
-  // | A |   |   |      row1
-  // |---| B |   |---+
-  // | D |   | C |   |  row2
-  // |---|---|   | E |
-  // | F |   |   |   |  row3
-  // +---+   +---+---+
-  // Cell D has an outline which creates overflow.
-  SetBodyInnerHTML(R"HTML(
-    <style>
-      td { width: 100px; height: 100px; padding: 0 }
-    </style>
-    <table style='border-spacing: 10px'>
-      <tr id='row1'>
-        <td>A</td>
-        <td rowspan='2'>B</td>
-        <td rowspan='3'>C</td>
-      </tr>
-      <tr id='row2'>
-        <td style='outline: 10px solid blue'>D</td>
-        <td rowspan='2'>E</td>
-      </tr>
-      <tr id='row3'>
-        <td>F</td>
-      </tr>
-    </table>
-  )HTML");
-
-  auto* row1 = GetRowByElementId("row1");
-  // TablesNG row geometry does not include border spacing. Legacy does.
-  // All row geometry expectations are different.
-  EXPECT_EQ(LayoutRect(0, 0, 320, 320), row1->ContentsVisualOverflowRect());
-  EXPECT_EQ(LayoutRect(0, 0, 430, 320), row1->SelfVisualOverflowRect());
-  auto* row2 = GetRowByElementId("row2");
-  EXPECT_EQ(LayoutRect(-10, -10, 440, 220), row2->ContentsVisualOverflowRect());
-  EXPECT_EQ(LayoutRect(0, 0, 430, 210), row2->SelfVisualOverflowRect());
-  auto* row3 = GetRowByElementId("row3");
-  EXPECT_EQ(LayoutRect(), row3->ContentsVisualOverflowRect());
-  EXPECT_EQ(LayoutRect(0, 0, 430, 100), row3->SelfVisualOverflowRect());
-}
-
-TEST_F(LayoutTableRowTest, VisualOverflowWithCollapsedBorders) {
-  SetBodyInnerHTML(R"HTML(
-    <style>
-      table { border-collapse: collapse }
-      td { border: 0px solid blue; padding: 0 }
-      div { width: 100px; height: 100px }
-    </style>
-    <table>
-      <tr id='row'>
-        <td style='border-bottom-width: 10px;
-            outline: 3px solid blue'><div></div></td>
-        <td style='border-width: 3px 15px'><div></div></td>
-      </tr>
-    </table>
-  )HTML");
-
-  auto* row = GetRowByElementId("row");
-
-  LayoutRect expected_self_visual_overflow = row->BorderBoxRect();
-  // Row's visual overflow does not include collapsed borders.
-  // They are painted by the table.
-  EXPECT_EQ(expected_self_visual_overflow, row->SelfVisualOverflowRect());
-
-  LayoutRect expected_visual_overflow = row->BorderBoxRect();
-  // Row's visual overflow does not include collapsed borders.
-  // It does include visual overflow of all cells.
-  expected_visual_overflow.ExpandEdges(LayoutUnit(3), LayoutUnit(0),
-                                       LayoutUnit(3), LayoutUnit(3));
-  EXPECT_EQ(expected_visual_overflow, row->VisualOverflowRect());
-}
-
-TEST_F(LayoutTableRowTest, LayoutOverflow) {
-  SetBodyInnerHTML(R"HTML(
-    <table style='border-spacing: 0'>
-      <tr id='row'>
-        <td style='100px; height: 100px; padding: 0'>
-          <div style='position: relative; top: 50px; left: 50px;
-              width: 100px; height: 100px'></div>
-        </td>
-      </tr>
-    </table>
-  )HTML");
-
-  EXPECT_EQ(LayoutRect(0, 0, 150, 150),
-            GetRowByElementId("row")->LayoutOverflowRect());
-}
-
-}  // anonymous namespace
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_table_section.cc b/third_party/blink/renderer/core/layout/layout_table_section.cc
deleted file mode 100644
index 9bf9637..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_section.cc
+++ /dev/null
@@ -1,2187 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc.
- *               All rights reserved.
- * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-
-#include <algorithm>
-#include <limits>
-#include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/core/layout/hit_test_result.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/table_section_painter.h"
-#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-
-namespace blink {
-
-void LayoutTableSection::TableGridRow::Trace(Visitor* visitor) const {
-  visitor->Trace(grid_cells);
-  visitor->Trace(row);
-}
-
-void LayoutTableSection::TableGridRow::
-    SetRowLogicalHeightToRowStyleLogicalHeight() {
-  DCHECK(row);
-  logical_height = row->StyleRef().LogicalHeight();
-}
-
-void LayoutTableSection::TableGridRow::UpdateLogicalHeightForCell(
-    const LayoutTableCell* cell) {
-  // We ignore height settings on rowspan cells.
-  if (cell->ResolvedRowSpan() != 1)
-    return;
-
-  const Length& cell_logical_height = cell->StyleRef().LogicalHeight();
-  if (cell_logical_height.IsPositive()) {
-    switch (cell_logical_height.GetType()) {
-      case Length::kPercent:
-        // TODO(alancutter): Make this work correctly for calc lengths.
-        if (!(logical_height.IsPercentOrCalc()) ||
-            (logical_height.IsPercent() &&
-             logical_height.Percent() < cell_logical_height.Percent()))
-          logical_height = cell_logical_height;
-        break;
-      case Length::kFixed:
-        if (logical_height.IsAuto() ||
-            (logical_height.IsFixed() &&
-             logical_height.Value() < cell_logical_height.Value()))
-          logical_height = cell_logical_height;
-        break;
-      default:
-        break;
-    }
-  }
-}
-
-void CellSpan::EnsureConsistency(const unsigned maximum_span_size) {
-  static_assert(std::is_same<decltype(start_), unsigned>::value,
-                "Asserts below assume start_ is unsigned");
-  static_assert(std::is_same<decltype(end_), unsigned>::value,
-                "Asserts below assume end_ is unsigned");
-  CHECK_LE(start_, maximum_span_size);
-  CHECK_LE(end_, maximum_span_size);
-  CHECK_LE(start_, end_);
-}
-
-LayoutTableSection::LayoutTableSection(Element* element)
-    : LayoutTableBoxComponent(element),
-      c_col_(0),
-      c_row_(0),
-      needs_cell_recalc_(false),
-      force_full_paint_(false),
-      has_multiple_cell_levels_(false),
-      has_spanning_cells_(false),
-      is_repeating_header_group_(false),
-      is_repeating_footer_group_(false) {
-  // init LayoutObject attributes
-  SetInline(false);  // our object is not Inline
-}
-
-LayoutTableSection::~LayoutTableSection() = default;
-
-void LayoutTableSection::Trace(Visitor* visitor) const {
-  visitor->Trace(grid_);
-  visitor->Trace(visually_overflowing_cells_);
-  LayoutTableBoxComponent::Trace(visitor);
-}
-
-void LayoutTableSection::StyleDidChange(StyleDifference diff,
-                                        const ComputedStyle* old_style) {
-  NOT_DESTROYED();
-  DCHECK(StyleRef().Display() == EDisplay::kTableFooterGroup ||
-         StyleRef().Display() == EDisplay::kTableRowGroup ||
-         StyleRef().Display() == EDisplay::kTableHeaderGroup);
-
-  // Legacy tables cannot handle relative/sticky sections.
-  if (StyleRef().HasInFlowPosition()) {
-    ComputedStyleBuilder builder(StyleRef());
-    builder.SetPosition(EPosition::kStatic);
-    SetStyle(builder.TakeStyle(), LayoutObject::ApplyStyleChanges::kNo);
-  }
-
-  LayoutTableBoxComponent::StyleDidChange(diff, old_style);
-  PropagateStyleToAnonymousChildren();
-
-  if (!old_style)
-    return;
-
-  LayoutTable* table = Table();
-  if (!table)
-    return;
-
-  LayoutTableBoxComponent::InvalidateCollapsedBordersOnStyleChange(
-      *this, *table, diff, *old_style);
-
-  if (LayoutTableBoxComponent::DoCellsHaveDirtyWidth(*this, *table, diff,
-                                                     *old_style)) {
-    MarkAllCellsWidthsDirtyAndOrNeedsLayout(
-        LayoutTable::kMarkDirtyAndNeedsLayout);
-  }
-}
-
-void LayoutTableSection::WillBeRemovedFromTree() {
-  NOT_DESTROYED();
-  LayoutTableBoxComponent::WillBeRemovedFromTree();
-
-  // Preventively invalidate our cells as we may be re-inserted into
-  // a new table which would require us to rebuild our structure.
-  SetNeedsCellRecalc();
-}
-
-void LayoutTableSection::EnsureCols(unsigned row_index, unsigned num_cols) {
-  NOT_DESTROYED();
-  if (num_cols > NumCols(row_index))
-    grid_[row_index].grid_cells.Grow(num_cols);
-}
-
-void LayoutTableSection::AddChild(LayoutObject* child,
-                                  LayoutObject* before_child) {
-  NOT_DESTROYED();
-  if (!child->IsTableRow()) {
-    LayoutObject* last = before_child;
-    if (!last)
-      last = LastRow();
-    if (last && last->IsAnonymous() && last->IsTablePart() &&
-        !last->IsBeforeOrAfterContent()) {
-      if (before_child == last)
-        before_child = last->SlowFirstChild();
-      last->AddChild(child, before_child);
-      return;
-    }
-
-    if (before_child && !before_child->IsAnonymous() &&
-        before_child->Parent() == this) {
-      LayoutObject* row = before_child->PreviousSibling();
-      if (row && row->IsTableRow() && row->IsAnonymous()) {
-        row->AddChild(child);
-        return;
-      }
-    }
-
-    // If beforeChild is inside an anonymous cell/row, insert into the cell or
-    // into the anonymous row containing it, if there is one.
-    LayoutObject* last_box = last;
-    while (last_box && last_box->Parent()->IsAnonymous() &&
-           !last_box->IsTableRow())
-      last_box = last_box->Parent();
-    if (last_box && last_box->IsAnonymous() &&
-        !last_box->IsBeforeOrAfterContent()) {
-      last_box->AddChild(child, before_child);
-      return;
-    }
-
-    LayoutObject* row =
-        LayoutObjectFactory::CreateAnonymousTableRowWithParent(*this);
-    AddChild(row, before_child);
-    row->AddChild(child);
-    return;
-  }
-
-  if (before_child)
-    SetNeedsCellRecalc();
-
-  unsigned insertion_row = c_row_;
-  ++c_row_;
-  c_col_ = 0;
-
-  EnsureRows(c_row_);
-
-  // TODO(crbug.com/1345894): See the TODO in |LayoutTable::AddChild|.
-  // |LayoutNGTableRow| is not a subclass of |LayoutTableRow|.
-  CHECK(IsA<LayoutTableRow>(child));
-  LayoutTableRow* row = To<LayoutTableRow>(child);
-  grid_[insertion_row].row = row;
-  row->SetRowIndex(insertion_row);
-
-  if (!before_child)
-    grid_[insertion_row].SetRowLogicalHeightToRowStyleLogicalHeight();
-
-  if (before_child && before_child->Parent() != this)
-    before_child = SplitAnonymousBoxesAroundChild(before_child);
-
-  DCHECK(!before_child || before_child->IsTableRow());
-  LayoutTableBoxComponent::AddChild(child, before_child);
-}
-
-static inline void CheckThatVectorIsDOMOrdered(
-    const HeapVector<Member<LayoutTableCell>, 1>& cells) {
-#ifndef NDEBUG
-  // This function should be called on a non-empty vector.
-  DCHECK_GT(cells.size(), 0u);
-
-  const LayoutTableCell* previous_cell = cells[0];
-  for (wtf_size_t i = 1; i < cells.size(); ++i) {
-    const LayoutTableCell* current_cell = cells[i];
-    // The check assumes that all cells belong to the same row group.
-    DCHECK_EQ(previous_cell->Section(), current_cell->Section());
-
-    // 2 overlapping cells can't be on the same row.
-    DCHECK_NE(current_cell->Row(), previous_cell->Row());
-
-    // Look backwards in the tree for the previousCell's row. If we are
-    // DOM ordered, we should find it.
-    const LayoutTableRow* row = current_cell->Row();
-    for (; row && row != previous_cell->Row(); row = row->PreviousRow()) {
-    }
-    DCHECK_EQ(row, previous_cell->Row());
-
-    previous_cell = current_cell;
-  }
-#endif  // NDEBUG
-}
-
-void LayoutTableSection::AddCell(LayoutTableCell* cell, LayoutTableRow* row) {
-  NOT_DESTROYED();
-  // We don't insert the cell if we need cell recalc as our internal columns'
-  // representation will have drifted from the table's representation. Also
-  // recalcCells will call addCell at a later time after sync'ing our columns'
-  // with the table's.
-  if (NeedsCellRecalc())
-    return;
-
-  DCHECK(cell);
-  unsigned r_span = cell->ResolvedRowSpan();
-  unsigned c_span = cell->ColSpan();
-  if (r_span > 1 || c_span > 1)
-    has_spanning_cells_ = true;
-
-  const Vector<LayoutTable::ColumnStruct>& columns =
-      Table()->EffectiveColumns();
-  unsigned insertion_row = row->RowIndex();
-
-  // ### mozilla still seems to do the old HTML way, even for strict DTD
-  // (see the annotation on table cell layouting in the CSS specs and the
-  // testcase below:
-  // <TABLE border>
-  // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
-  // <TR><TD colspan="2">5
-  // </TABLE>
-  unsigned n_cols = NumCols(insertion_row);
-  while (c_col_ < n_cols && (GridCellAt(insertion_row, c_col_).HasCells() ||
-                             GridCellAt(insertion_row, c_col_).InColSpan()))
-    c_col_++;
-
-  grid_[insertion_row].UpdateLogicalHeightForCell(cell);
-
-  EnsureRows(insertion_row + r_span);
-
-  grid_[insertion_row].row = row;
-
-  unsigned col = c_col_;
-  // tell the cell where it is
-  bool in_col_span = false;
-  unsigned col_size = columns.size();
-  while (c_span) {
-    unsigned current_span;
-    if (c_col_ >= col_size) {
-      Table()->AppendEffectiveColumn(c_span);
-      current_span = c_span;
-    } else {
-      if (c_span < columns[c_col_].span)
-        Table()->SplitEffectiveColumn(c_col_, c_span);
-      current_span = columns[c_col_].span;
-    }
-    for (unsigned r = 0; r < r_span; r++) {
-      EnsureCols(insertion_row + r, c_col_ + 1);
-      auto& grid_cell = GridCellAt(insertion_row + r, c_col_);
-      grid_cell.Cells().push_back(cell);
-      CheckThatVectorIsDOMOrdered(grid_cell.Cells());
-      // If cells overlap then we take the special paint path for them.
-      if (grid_cell.Cells().size() > 1)
-        has_multiple_cell_levels_ = true;
-      if (in_col_span)
-        grid_cell.SetInColSpan(true);
-    }
-    c_col_++;
-    c_span -= current_span;
-    in_col_span = true;
-  }
-  cell->SetAbsoluteColumnIndex(Table()->EffectiveColumnToAbsoluteColumn(col));
-}
-
-bool LayoutTableSection::RowHasOnlySpanningCells(unsigned row) {
-  NOT_DESTROYED();
-  if (grid_[row].grid_cells.empty())
-    return false;
-
-  for (const auto& grid_cell : grid_[row].grid_cells) {
-    // Empty cell is not a valid cell so it is not a rowspan cell.
-    if (!grid_cell.HasCells())
-      return false;
-
-    if (grid_cell.Cells()[0]->ResolvedRowSpan() == 1)
-      return false;
-  }
-
-  return true;
-}
-
-void LayoutTableSection::PopulateSpanningRowsHeightFromCell(
-    LayoutTableCell* cell,
-    struct SpanningRowsHeight& spanning_rows_height) {
-  NOT_DESTROYED();
-  const unsigned row_span = cell->ResolvedRowSpan();
-  const unsigned row_index = cell->RowIndex();
-
-  spanning_rows_height.spanning_cell_height_ignoring_border_spacing =
-      cell->LogicalHeightForRowSizing();
-
-  spanning_rows_height.row_height.resize(row_span);
-  spanning_rows_height.total_rows_height = 0;
-  for (unsigned row = 0; row < row_span; row++) {
-    unsigned actual_row = row + row_index;
-
-    spanning_rows_height.row_height[row] = row_pos_[actual_row + 1] -
-                                           row_pos_[actual_row] -
-                                           BorderSpacingForRow(actual_row);
-    if (!spanning_rows_height.row_height[row])
-      spanning_rows_height.is_any_row_with_only_spanning_cells |=
-          RowHasOnlySpanningCells(actual_row);
-
-    spanning_rows_height.total_rows_height +=
-        spanning_rows_height.row_height[row];
-    spanning_rows_height.spanning_cell_height_ignoring_border_spacing -=
-        BorderSpacingForRow(actual_row);
-  }
-  // We don't span the following row so its border-spacing (if any) should be
-  // included.
-  spanning_rows_height.spanning_cell_height_ignoring_border_spacing +=
-      BorderSpacingForRow(row_index + row_span - 1);
-}
-
-void LayoutTableSection::DistributeExtraRowSpanHeightToPercentRows(
-    LayoutTableCell* cell,
-    float total_percent,
-    int& extra_row_spanning_height,
-    Vector<int>& rows_height) {
-  NOT_DESTROYED();
-  if (!extra_row_spanning_height || !total_percent)
-    return;
-
-  const unsigned row_span = cell->ResolvedRowSpan();
-  const unsigned row_index = cell->RowIndex();
-  float percent = std::min(total_percent, 100.0f);
-  const int table_height = row_pos_[grid_.size()] + extra_row_spanning_height;
-
-  // Our algorithm matches Firefox. Extra spanning height would be distributed
-  // Only in first percent height rows those total percent is 100. Other percent
-  // rows would be uneffected even extra spanning height is remain.
-  int accumulated_position_increase = 0;
-  for (unsigned row = row_index; row < (row_index + row_span); row++) {
-    if (percent > 0 && extra_row_spanning_height > 0) {
-      // TODO(alancutter): Make this work correctly for calc lengths.
-      if (grid_[row].logical_height.IsPercent()) {
-        int to_add =
-            (table_height *
-             std::min(grid_[row].logical_height.Percent(), percent) / 100) -
-            rows_height[row - row_index];
-
-        to_add = std::max(std::min(to_add, extra_row_spanning_height), 0);
-        accumulated_position_increase += to_add;
-        extra_row_spanning_height -= to_add;
-        percent -= grid_[row].logical_height.Percent();
-      }
-    }
-    row_pos_[row + 1] += accumulated_position_increase;
-  }
-}
-
-static void UpdatePositionIncreasedWithRowHeight(
-    int extra_height,
-    float row_height,
-    float total_height,
-    int& accumulated_position_increase,
-    double& remainder) {
-  // Without the cast we lose enough precision to cause heights to miss pixels
-  // (and trigger asserts) in some web tests.
-  double proportional_position_increase =
-      remainder + (extra_height * double(row_height)) / total_height;
-  // The epsilon is to push any values that are close to a whole number but
-  // aren't due to floating point imprecision. The epsilons are not accumulated,
-  // any that aren't necessary are lost in the cast to int.
-  int position_increase_int = proportional_position_increase + 0.000001;
-  accumulated_position_increase += position_increase_int;
-  remainder = proportional_position_increase - position_increase_int;
-}
-
-// This is mainly used to distribute whole extra rowspanning height in percent
-// rows when all spanning rows are percent rows.
-// Distributing whole extra rowspanning height in percent rows based on the
-// ratios of percent because this method works same as percent distribution when
-// only percent rows are present and percent is 100. Also works perfectly fine
-// when percent is not equal to 100.
-void LayoutTableSection::DistributeWholeExtraRowSpanHeightToPercentRows(
-    LayoutTableCell* cell,
-    float total_percent,
-    int& extra_row_spanning_height,
-    Vector<int>& rows_height) {
-  NOT_DESTROYED();
-  if (!extra_row_spanning_height || !total_percent)
-    return;
-
-  const unsigned row_span = cell->ResolvedRowSpan();
-  const unsigned row_index = cell->RowIndex();
-  double remainder = 0;
-
-  int accumulated_position_increase = 0;
-  for (unsigned row = row_index; row < (row_index + row_span); row++) {
-    // TODO(alancutter): Make this work correctly for calc lengths.
-    if (grid_[row].logical_height.IsPercent()) {
-      UpdatePositionIncreasedWithRowHeight(
-          extra_row_spanning_height, grid_[row].logical_height.Percent(),
-          total_percent, accumulated_position_increase, remainder);
-    }
-    row_pos_[row + 1] += accumulated_position_increase;
-  }
-
-  DCHECK_LT(remainder, 2.0) << "remainder was " << remainder;
-
-  extra_row_spanning_height -= accumulated_position_increase;
-}
-
-void LayoutTableSection::DistributeExtraRowSpanHeightToAutoRows(
-    LayoutTableCell* cell,
-    int total_auto_rows_height,
-    int& extra_row_spanning_height,
-    Vector<int>& rows_height) {
-  NOT_DESTROYED();
-  if (!extra_row_spanning_height || !total_auto_rows_height)
-    return;
-
-  const unsigned row_span = cell->ResolvedRowSpan();
-  const unsigned row_index = cell->RowIndex();
-  int accumulated_position_increase = 0;
-  double remainder = 0;
-
-  // Aspect ratios of auto rows should not change otherwise table may look
-  // different than user expected. So extra height distributed in auto spanning
-  // rows based on their weight in spanning cell.
-  for (unsigned row = row_index; row < (row_index + row_span); row++) {
-    if (grid_[row].logical_height.IsAuto()) {
-      UpdatePositionIncreasedWithRowHeight(
-          extra_row_spanning_height, rows_height[row - row_index],
-          total_auto_rows_height, accumulated_position_increase, remainder);
-    }
-    row_pos_[row + 1] += accumulated_position_increase;
-  }
-
-  DCHECK_LT(remainder, 2.0) << "remainder was " << remainder;
-
-  extra_row_spanning_height -= accumulated_position_increase;
-}
-
-void LayoutTableSection::DistributeExtraRowSpanHeightToRemainingRows(
-    LayoutTableCell* cell,
-    int total_remaining_rows_height,
-    int& extra_row_spanning_height,
-    Vector<int>& rows_height) {
-  NOT_DESTROYED();
-  if (!extra_row_spanning_height || !total_remaining_rows_height)
-    return;
-
-  const unsigned row_span = cell->ResolvedRowSpan();
-  const unsigned row_index = cell->RowIndex();
-  int accumulated_position_increase = 0;
-  double remainder = 0;
-
-  // Aspect ratios of the rows should not change otherwise table may look
-  // different than user expected. So extra height distribution in remaining
-  // spanning rows based on their weight in spanning cell.
-  for (unsigned row = row_index; row < (row_index + row_span); row++) {
-    if (!grid_[row].logical_height.IsPercentOrCalc()) {
-      UpdatePositionIncreasedWithRowHeight(
-          extra_row_spanning_height, rows_height[row - row_index],
-          total_remaining_rows_height, accumulated_position_increase,
-          remainder);
-    }
-    row_pos_[row + 1] += accumulated_position_increase;
-  }
-
-  DCHECK_LT(remainder, 2.0) << "remainder was " << remainder;
-
-  extra_row_spanning_height -= accumulated_position_increase;
-}
-
-static bool CellIsFullyIncludedInOtherCell(const LayoutTableCell* cell1,
-                                           const LayoutTableCell* cell2) {
-  return (cell1->RowIndex() >= cell2->RowIndex() &&
-          (cell1->RowIndex() + cell1->ResolvedRowSpan()) <=
-              (cell2->RowIndex() + cell2->ResolvedRowSpan()));
-}
-
-// To avoid unneeded extra height distributions, we apply the following sorting
-// algorithm:
-static bool CompareRowSpanCellsInHeightDistributionOrder(
-    const LayoutTableCell* cell1,
-    const LayoutTableCell* cell2) {
-  // Sorting bigger height cell first if cells are at same index with same span
-  // because we will skip smaller height cell to distribute it's extra height.
-  if (cell1->RowIndex() == cell2->RowIndex() &&
-      cell1->ResolvedRowSpan() == cell2->ResolvedRowSpan())
-    return (cell1->LogicalHeightForRowSizing() >
-            cell2->LogicalHeightForRowSizing());
-  // Sorting inner most cell first because if inner spanning cell'e extra height
-  // is distributed then outer spanning cell's extra height will adjust
-  // accordingly. In reverse order, there is more chances that outer spanning
-  // cell's height will exceed than defined by user.
-  if (CellIsFullyIncludedInOtherCell(cell1, cell2))
-    return true;
-  // Sorting lower row index first because first we need to apply the extra
-  // height of spanning cell which comes first in the table so lower rows's
-  // position would increment in sequence.
-  if (!CellIsFullyIncludedInOtherCell(cell2, cell1))
-    return (cell1->RowIndex() < cell2->RowIndex());
-
-  return false;
-}
-
-unsigned LayoutTableSection::CalcRowHeightHavingOnlySpanningCells(
-    unsigned row,
-    int& accumulated_cell_position_increase,
-    unsigned row_to_apply_extra_height,
-    unsigned& extra_table_height_to_propgate,
-    Vector<int>& rows_count_with_only_spanning_cells) {
-  NOT_DESTROYED();
-  DCHECK(RowHasOnlySpanningCells(row));
-
-  unsigned row_height = 0;
-
-  for (const auto& row_span_cell : grid_[row].grid_cells) {
-    DCHECK(row_span_cell.HasCells());
-    LayoutTableCell* cell = row_span_cell.Cells()[0];
-    DCHECK_GE(cell->ResolvedRowSpan(), 2u);
-
-    const unsigned cell_row_index = cell->RowIndex();
-    const unsigned cell_row_span = cell->ResolvedRowSpan();
-
-    // As we are going from the top of the table to the bottom to calculate the
-    // row heights for rows that only contain spanning cells and all previous
-    // rows are processed we only need to find the number of rows with spanning
-    // cells from the current cell to the end of the current cells spanning
-    // height.
-    unsigned start_row_for_spanning_cell_count = std::max(cell_row_index, row);
-    unsigned end_row = cell_row_index + cell_row_span;
-    unsigned spanning_cells_rows_count_having_zero_height =
-        rows_count_with_only_spanning_cells[end_row - 1];
-
-    if (start_row_for_spanning_cell_count)
-      spanning_cells_rows_count_having_zero_height -=
-          rows_count_with_only_spanning_cells
-              [start_row_for_spanning_cell_count - 1];
-
-    int total_rowspan_cell_height =
-        (row_pos_[end_row] - row_pos_[cell_row_index]) -
-        BorderSpacingForRow(end_row - 1);
-
-    total_rowspan_cell_height += accumulated_cell_position_increase;
-    if (row_to_apply_extra_height >= cell_row_index &&
-        row_to_apply_extra_height < end_row)
-      total_rowspan_cell_height += extra_table_height_to_propgate;
-
-    if (total_rowspan_cell_height < cell->LogicalHeightForRowSizing()) {
-      unsigned extra_height_required =
-          cell->LogicalHeightForRowSizing() - total_rowspan_cell_height;
-
-      row_height = std::max(
-          row_height,
-          extra_height_required / spanning_cells_rows_count_having_zero_height);
-    }
-  }
-
-  return row_height;
-}
-
-void LayoutTableSection::UpdateRowsHeightHavingOnlySpanningCells(
-    LayoutTableCell* cell,
-    struct SpanningRowsHeight& spanning_rows_height,
-    unsigned& extra_height_to_propagate,
-    Vector<int>& rows_count_with_only_spanning_cells) {
-  NOT_DESTROYED();
-  DCHECK(spanning_rows_height.row_height.size());
-
-  int accumulated_position_increase = 0;
-  const unsigned row_span = cell->ResolvedRowSpan();
-  const unsigned row_index = cell->RowIndex();
-
-  DCHECK_EQ(row_span, spanning_rows_height.row_height.size());
-
-  for (unsigned row = 0; row < spanning_rows_height.row_height.size(); row++) {
-    unsigned actual_row = row + row_index;
-    if (!spanning_rows_height.row_height[row] &&
-        RowHasOnlySpanningCells(actual_row)) {
-      spanning_rows_height.row_height[row] =
-          CalcRowHeightHavingOnlySpanningCells(
-              actual_row, accumulated_position_increase, row_index + row_span,
-              extra_height_to_propagate, rows_count_with_only_spanning_cells);
-      accumulated_position_increase += spanning_rows_height.row_height[row];
-    }
-    row_pos_[actual_row + 1] += accumulated_position_increase;
-  }
-
-  spanning_rows_height.total_rows_height += accumulated_position_increase;
-}
-
-// Distribute rowSpan cell height in rows those comes in rowSpan cell based on
-// the ratio of row's height if 1 RowSpan cell height is greater than the total
-// height of rows in rowSpan cell.
-void LayoutTableSection::DistributeRowSpanHeightToRows(
-    SpanningLayoutTableCells& row_span_cells) {
-  NOT_DESTROYED();
-  DCHECK(row_span_cells.size());
-
-  // 'rowSpanCells' list is already sorted based on the cells rowIndex in
-  // ascending order
-  // Arrange row spanning cell in the order in which we need to process first.
-  std::sort(row_span_cells.begin(), row_span_cells.end(),
-            CompareRowSpanCellsInHeightDistributionOrder);
-
-  unsigned extra_height_to_propagate = 0;
-  unsigned last_row_index = 0;
-  unsigned last_row_span = 0;
-
-  Vector<int> rows_count_with_only_spanning_cells;
-
-  // At this stage, Height of the rows are zero for the one containing only
-  // spanning cells.
-  int count = 0;
-  for (unsigned row = 0; row < grid_.size(); row++) {
-    if (RowHasOnlySpanningCells(row))
-      count++;
-    rows_count_with_only_spanning_cells.push_back(count);
-  }
-
-  for (unsigned i = 0; i < row_span_cells.size(); i++) {
-    LayoutTableCell* cell = row_span_cells[i];
-
-    unsigned row_index = cell->RowIndex();
-
-    unsigned row_span = cell->ResolvedRowSpan();
-
-    unsigned spanning_cell_end_index = row_index + row_span;
-    unsigned last_spanning_cell_end_index = last_row_index + last_row_span;
-
-    // Only the highest spanning cell will distribute its extra height in a row
-    // if more than one spanning cell is present at the same level.
-    if (row_index == last_row_index && row_span == last_row_span)
-      continue;
-
-    int original_before_position = row_pos_[spanning_cell_end_index];
-
-    // When 2 spanning cells are ending at same row index then while extra
-    // height distribution of first spanning cell updates position of the last
-    // row so getting the original position of the last row in second spanning
-    // cell need to reduce the height changed by first spanning cell.
-    if (spanning_cell_end_index == last_spanning_cell_end_index)
-      original_before_position -= extra_height_to_propagate;
-
-    if (extra_height_to_propagate) {
-      for (unsigned row = last_spanning_cell_end_index + 1;
-           row <= spanning_cell_end_index; row++)
-        row_pos_[row] += extra_height_to_propagate;
-    }
-
-    last_row_index = row_index;
-    last_row_span = row_span;
-
-    struct SpanningRowsHeight spanning_rows_height;
-
-    PopulateSpanningRowsHeightFromCell(cell, spanning_rows_height);
-
-    // Here we are handling only row(s) who have only rowspanning cells and do
-    // not have any empty cell.
-    if (spanning_rows_height.is_any_row_with_only_spanning_cells)
-      UpdateRowsHeightHavingOnlySpanningCells(
-          cell, spanning_rows_height, extra_height_to_propagate,
-          rows_count_with_only_spanning_cells);
-
-    // This code handle row(s) that have rowspanning cell(s) and at least one
-    // empty cell. Such rows are not handled below and end up having a height of
-    // 0. That would mean content overlapping if one of their cells has any
-    // content. To avoid the problem, we add all the remaining spanning cells'
-    // height to the last spanned row. This means that we could grow a row past
-    // its 'height' or break percentage spreading however this is better than
-    // overlapping content.
-    // FIXME: Is there a better algorithm?
-    if (!spanning_rows_height.total_rows_height) {
-      if (spanning_rows_height.spanning_cell_height_ignoring_border_spacing)
-        row_pos_[spanning_cell_end_index] +=
-            spanning_rows_height.spanning_cell_height_ignoring_border_spacing +
-            BorderSpacingForRow(spanning_cell_end_index - 1);
-
-      extra_height_to_propagate =
-          row_pos_[spanning_cell_end_index] - original_before_position;
-      continue;
-    }
-
-    if (spanning_rows_height.spanning_cell_height_ignoring_border_spacing <=
-        spanning_rows_height.total_rows_height) {
-      extra_height_to_propagate =
-          row_pos_[row_index + row_span] - original_before_position;
-      continue;
-    }
-
-    // Below we are handling only row(s) who have at least one visible cell
-    // without rowspan value.
-    float total_percent = 0;
-    int total_auto_rows_height = 0;
-    int total_remaining_rows_height = spanning_rows_height.total_rows_height;
-
-    // FIXME: Inner spanning cell height should not change if it have fixed
-    // height when it's parent spanning cell is distributing it's extra height
-    // in rows.
-
-    // Calculate total percentage, total auto rows height and total rows height
-    // except percent rows.
-    for (unsigned row = row_index; row < spanning_cell_end_index; row++) {
-      // TODO(alancutter): Make this work correctly for calc lengths.
-      if (grid_[row].logical_height.IsPercent()) {
-        total_percent += grid_[row].logical_height.Percent();
-        total_remaining_rows_height -=
-            spanning_rows_height.row_height[row - row_index];
-      } else if (grid_[row].logical_height.IsAuto()) {
-        total_auto_rows_height +=
-            spanning_rows_height.row_height[row - row_index];
-      }
-    }
-
-    int extra_row_spanning_height =
-        spanning_rows_height.spanning_cell_height_ignoring_border_spacing -
-        spanning_rows_height.total_rows_height;
-
-    if (total_percent < 100 && !total_auto_rows_height &&
-        !total_remaining_rows_height) {
-      // Distributing whole extra rowspanning height in percent row when only
-      // non-percent rows height is 0.
-      DistributeWholeExtraRowSpanHeightToPercentRows(
-          cell, total_percent, extra_row_spanning_height,
-          spanning_rows_height.row_height);
-    } else {
-      DistributeExtraRowSpanHeightToPercentRows(
-          cell, total_percent, extra_row_spanning_height,
-          spanning_rows_height.row_height);
-      DistributeExtraRowSpanHeightToAutoRows(cell, total_auto_rows_height,
-                                             extra_row_spanning_height,
-                                             spanning_rows_height.row_height);
-      DistributeExtraRowSpanHeightToRemainingRows(
-          cell, total_remaining_rows_height, extra_row_spanning_height,
-          spanning_rows_height.row_height);
-    }
-
-    DCHECK_LT(abs(extra_row_spanning_height), 2);
-
-    // Getting total changed height in the table
-    extra_height_to_propagate =
-        row_pos_[spanning_cell_end_index] - original_before_position;
-  }
-
-  if (extra_height_to_propagate) {
-    // Apply changed height by rowSpan cells to rows present at the end of the
-    // table
-    for (unsigned row = last_row_index + last_row_span + 1; row <= grid_.size();
-         row++)
-      row_pos_[row] += extra_height_to_propagate;
-  }
-}
-
-bool LayoutTableSection::RowHasVisibilityCollapse(unsigned row) const {
-  NOT_DESTROYED();
-  return ((grid_[row].row &&
-           grid_[row].row->StyleRef().Visibility() == EVisibility::kCollapse) ||
-          StyleRef().Visibility() == EVisibility::kCollapse);
-}
-
-// Find out the baseline of the cell
-// If the cell's baseline is more than the row's baseline then the cell's
-// baseline become the row's baseline and if the row's baseline goes out of the
-// row's boundaries then adjust row height accordingly.
-void LayoutTableSection::UpdateBaselineForCell(LayoutTableCell* cell,
-                                               unsigned row,
-                                               LayoutUnit& baseline_descent) {
-  NOT_DESTROYED();
-  if (!cell->IsBaselineAligned())
-    return;
-
-  // Ignoring the intrinsic padding as it depends on knowing the row's baseline,
-  // which won't be accurate until the end of this function.
-  LayoutUnit baseline_position =
-      cell->CellBaselinePosition() - cell->IntrinsicPaddingBefore();
-  if (baseline_position >
-      cell->BorderBefore() +
-          (cell->PaddingBefore() - cell->IntrinsicPaddingBefore())) {
-    grid_[row].baseline = std::max(grid_[row].baseline, baseline_position);
-
-    LayoutUnit cell_start_row_baseline_descent;
-    if (cell->ResolvedRowSpan() == 1) {
-      baseline_descent =
-          std::max(baseline_descent,
-                   cell->LogicalHeightForRowSizing() - baseline_position);
-      cell_start_row_baseline_descent = baseline_descent;
-    }
-    row_pos_[row + 1] = std::max(
-        row_pos_[row + 1],
-        (row_pos_[row] + grid_[row].baseline + cell_start_row_baseline_descent)
-            .ToInt());
-  }
-}
-
-int16_t LayoutTableSection::VBorderSpacingBeforeFirstRow() const {
-  NOT_DESTROYED();
-  // We ignore the border-spacing on any non-top section, as it is already
-  // included in the previous section's last row position.
-  if (this != Table()->TopSection())
-    return 0;
-  return Table()->VBorderSpacing();
-}
-
-int LayoutTableSection::CalcRowLogicalHeight() {
-  NOT_DESTROYED();
-#if DCHECK_IS_ON()
-  SetLayoutNeededForbiddenScope layout_forbidden_scope(*this);
-#endif
-
-  DCHECK(!NeedsLayout());
-
-  // We may have to forcefully lay out cells here, in which case we need a
-  // layout state.
-  LayoutState state(*this);
-
-  row_pos_.resize(grid_.size() + 1);
-  row_pos_[0] = VBorderSpacingBeforeFirstRow();
-
-  SpanningLayoutTableCells row_span_cells;
-
-  // At fragmentainer breaks we need to prevent rowspanned cells (and whatever
-  // else) from distributing their extra height requirements over the rows that
-  // it spans. Otherwise we'd need to refragment afterwards.
-  unsigned index_of_first_stretchable_row = 0;
-
-  is_any_row_collapsed_ = false;
-
-  for (unsigned r = 0; r < grid_.size(); r++) {
-    grid_[r].baseline = LayoutUnit(-1);
-    LayoutUnit baseline_descent;
-
-    if (!is_any_row_collapsed_)
-      is_any_row_collapsed_ = RowHasVisibilityCollapse(r);
-
-    if (state.IsPaginated() && grid_[r].row)
-      row_pos_[r] += grid_[r].row->PaginationStrut().Ceil();
-
-    if (grid_[r].logical_height.IsSpecified()) {
-      // Our base size is the biggest logical height from our cells' styles
-      // (excluding row spanning cells).
-      row_pos_[r + 1] =
-          std::max(row_pos_[r] + MinimumValueForLength(grid_[r].logical_height,
-                                                       LayoutUnit())
-                                     .Round(),
-                   0);
-    } else {
-      // Non-specified lengths are ignored because the row already accounts for
-      // the cells intrinsic logical height.
-      row_pos_[r + 1] = std::max(row_pos_[r], 0);
-    }
-
-    for (auto& grid_cell : grid_[r].grid_cells) {
-      if (grid_cell.InColSpan())
-        continue;
-      for (const auto& cell : grid_cell.Cells()) {
-        // For row spanning cells, we only handle them for the first row they
-        // span. This ensures we take their baseline into account.
-        if (cell->RowIndex() != r)
-          continue;
-
-        if (r < index_of_first_stretchable_row ||
-            (state.IsPaginated() &&
-             CrossesPageBoundary(
-                 LayoutUnit(row_pos_[r]),
-                 LayoutUnit(cell->LogicalHeightForRowSizing())))) {
-          // Entering or extending a range of unstretchable rows. We enter this
-          // mode when a cell in a row crosses a fragmentainer boundary, and
-          // we'll stay in this mode until we get to a row where we're past all
-          // rowspanned cells that we encountered while in this mode.
-          DCHECK(state.IsPaginated());
-          unsigned row_index_below_cell = r + cell->ResolvedRowSpan();
-          index_of_first_stretchable_row =
-              std::max(index_of_first_stretchable_row, row_index_below_cell);
-        } else if (cell->ResolvedRowSpan() > 1) {
-          DCHECK(!row_span_cells.Contains(cell));
-
-          cell->SetIsSpanningCollapsedRow(false);
-          unsigned end_row = cell->ResolvedRowSpan() + r;
-          for (unsigned spanning = r; spanning < end_row; spanning++) {
-            if (RowHasVisibilityCollapse(spanning)) {
-              cell->SetIsSpanningCollapsedRow(true);
-              break;
-            }
-          }
-
-          row_span_cells.push_back(cell);
-        }
-
-        if (cell->HasOverrideLogicalHeight()) {
-          cell->ClearIntrinsicPadding();
-          cell->ClearOverrideSize();
-          cell->ForceLayout();
-        }
-
-        if (cell->ResolvedRowSpan() == 1)
-          row_pos_[r + 1] = std::max(
-              row_pos_[r + 1], row_pos_[r] + cell->LogicalHeightForRowSizing());
-
-        // Find out the baseline. The baseline is set on the first row in a
-        // rowSpan.
-        UpdateBaselineForCell(cell, r, baseline_descent);
-      }
-    }
-
-    if (r < index_of_first_stretchable_row && grid_[r].row) {
-      // We're not allowed to resize this row. Just scratch what we've
-      // calculated so far, and use the height that we got during initial
-      // layout instead.
-      row_pos_[r + 1] = row_pos_[r] + grid_[r].row->LogicalHeight().ToInt();
-    }
-
-    // Add the border-spacing to our final position.
-    row_pos_[r + 1] += BorderSpacingForRow(r);
-    row_pos_[r + 1] = std::max(row_pos_[r + 1], row_pos_[r]);
-  }
-
-  if (!row_span_cells.empty())
-    DistributeRowSpanHeightToRows(row_span_cells);
-
-  DCHECK(!NeedsLayout());
-
-  // Collapsed rows are dealt with after distributing row span height to rows.
-  // This is because the distribution calculations should be as if the row were
-  // not collapsed. First, all rows' collapsed heights are set. After, row
-  // positions are adjusted accordingly.
-  if (is_any_row_collapsed_) {
-    row_collapsed_height_.resize(grid_.size());
-    for (unsigned r = 0; r < grid_.size(); r++) {
-      if (RowHasVisibilityCollapse(r)) {
-        // Update vector that keeps track of collapsed height of each row.
-        row_collapsed_height_[r] = row_pos_[r + 1] - row_pos_[r];
-      } else {
-        // Reset rows that are no longer collapsed.
-        row_collapsed_height_[r] = 0;
-      }
-    }
-
-    int total_collapsed_height = 0;
-    for (unsigned r = 0; r < grid_.size(); r++) {
-      total_collapsed_height += row_collapsed_height_[r];
-      // Adjust row position according to the height collapsed so far.
-      row_pos_[r + 1] -= total_collapsed_height;
-      DCHECK_GE(row_pos_[r + 1], row_pos_[r]);
-    }
-  }
-
-  return row_pos_[grid_.size()];
-}
-
-void LayoutTableSection::UpdateLayout() {
-  NOT_DESTROYED();
-  DCHECK(NeedsLayout());
-  CHECK(!NeedsCellRecalc());
-  DCHECK(!Table()->NeedsSectionRecalc());
-
-  // addChild may over-grow grid_ but we don't want to throw away the memory
-  // too early as addChild can be called in a loop (e.g during parsing). Doing
-  // it now ensures we have a stable-enough structure.
-  grid_.shrink_to_fit();
-
-  LayoutState state(*this);
-
-  const Vector<int>& column_pos = Table()->EffectiveColumnPositions();
-  LayoutUnit row_logical_top(VBorderSpacingBeforeFirstRow());
-
-  SubtreeLayoutScope layouter(*this);
-  for (unsigned r = 0; r < grid_.size(); ++r) {
-    auto& grid_cells = grid_[r].grid_cells;
-    unsigned cols = grid_cells.size();
-    // First, propagate our table layout's information to the cells. This will
-    // mark the row as needing layout if there was a column logical width
-    // change.
-    for (unsigned start_column = 0; start_column < cols; ++start_column) {
-      auto& grid_cell = grid_cells[start_column];
-      LayoutTableCell* cell = grid_cell.PrimaryCell();
-      if (!cell || grid_cell.InColSpan())
-        continue;
-
-      unsigned end_col = start_column;
-      unsigned cspan = cell->ColSpan();
-      while (cspan && end_col < cols) {
-        DCHECK_LT(end_col, Table()->EffectiveColumns().size());
-        cspan -= Table()->EffectiveColumns()[end_col].span;
-        end_col++;
-      }
-      int table_layout_logical_width = column_pos[end_col] -
-                                       column_pos[start_column] -
-                                       Table()->HBorderSpacing();
-      cell->SetCellLogicalWidth(table_layout_logical_width, layouter);
-    }
-
-    if (LayoutTableRow* row = grid_[r].row) {
-      if (state.IsPaginated())
-        row->SetLogicalTop(row_logical_top);
-      if (!row->NeedsLayout())
-        MarkChildForPaginationRelayoutIfNeeded(*row, layouter);
-      row->LayoutIfNeeded();
-      if (state.IsPaginated()) {
-        AdjustRowForPagination(*row, layouter);
-        UpdateFragmentationInfoForChild(*row);
-        row_logical_top = row->LogicalBottom();
-        row_logical_top += LayoutUnit(Table()->VBorderSpacing());
-      }
-
-      if (!Table()->HasSameDirectionAs(row)) {
-        UseCounter::Count(GetDocument(),
-                          WebFeature::kTableRowDirectionDifferentFromTable);
-      }
-    }
-  }
-
-  if (!Table()->HasSameDirectionAs(this)) {
-    UseCounter::Count(GetDocument(),
-                      WebFeature::kTableSectionDirectionDifferentFromTable);
-  }
-
-  ClearNeedsLayout();
-}
-
-void LayoutTableSection::DistributeExtraLogicalHeightToPercentRows(
-    int& extra_logical_height,
-    int total_percent) {
-  NOT_DESTROYED();
-  if (!total_percent)
-    return;
-
-  unsigned total_rows = grid_.size();
-  int total_height = row_pos_[total_rows] + extra_logical_height;
-  int total_logical_height_added = 0;
-  total_percent = std::min(total_percent, 100);
-  int row_height = row_pos_[1] - row_pos_[0];
-  for (unsigned r = 0; r < total_rows; ++r) {
-    // TODO(alancutter): Make this work correctly for calc lengths.
-    if (total_percent > 0 && grid_[r].logical_height.IsPercent()) {
-      int to_add = std::min<int>(
-          extra_logical_height,
-          (total_height * grid_[r].logical_height.Percent() / 100) -
-              row_height);
-      // If toAdd is negative, then we don't want to shrink the row (this bug
-      // affected Outlook Web Access).
-      to_add = std::max(0, to_add);
-      total_logical_height_added += to_add;
-      extra_logical_height -= to_add;
-      total_percent -= grid_[r].logical_height.Percent();
-    }
-    DCHECK_GE(total_rows, 1u);
-    if (r < total_rows - 1)
-      row_height = row_pos_[r + 2] - row_pos_[r + 1];
-    row_pos_[r + 1] += total_logical_height_added;
-  }
-}
-
-void LayoutTableSection::DistributeExtraLogicalHeightToAutoRows(
-    int& extra_logical_height,
-    unsigned auto_rows_count) {
-  NOT_DESTROYED();
-  if (!auto_rows_count)
-    return;
-
-  int total_logical_height_added = 0;
-  for (unsigned r = 0; r < grid_.size(); ++r) {
-    if (auto_rows_count > 0 && grid_[r].logical_height.IsAuto()) {
-      // Recomputing |extraLogicalHeightForRow| guarantees that we properly
-      // ditribute round |extraLogicalHeight|.
-      int extra_logical_height_for_row = extra_logical_height / auto_rows_count;
-      total_logical_height_added += extra_logical_height_for_row;
-      extra_logical_height -= extra_logical_height_for_row;
-      --auto_rows_count;
-    }
-    row_pos_[r + 1] += total_logical_height_added;
-  }
-}
-
-void LayoutTableSection::DistributeRemainingExtraLogicalHeight(
-    int& extra_logical_height) {
-  NOT_DESTROYED();
-  unsigned total_rows = grid_.size();
-
-  if (extra_logical_height <= 0 || !row_pos_[total_rows])
-    return;
-
-  int total_logical_height_added = 0;
-  int previous_row_position = row_pos_[0];
-  float total_row_size = row_pos_[total_rows] - previous_row_position;
-  if (total_row_size == 0) {
-    // crbug.com/1074722 prevents division by 0.
-    extra_logical_height = 0;
-    return;
-  }
-  for (unsigned r = 0; r < total_rows; r++) {
-    // weight with the original height
-    float height_to_add = extra_logical_height *
-                          (row_pos_[r + 1] - previous_row_position) /
-                          total_row_size;
-    total_logical_height_added =
-        std::min<int>(total_logical_height_added + std::ceil(height_to_add),
-                      extra_logical_height);
-    previous_row_position = row_pos_[r + 1];
-    row_pos_[r + 1] += total_logical_height_added;
-  }
-
-  extra_logical_height -= total_logical_height_added;
-}
-
-int LayoutTableSection::DistributeExtraLogicalHeightToRows(
-    int extra_logical_height) {
-  NOT_DESTROYED();
-  if (!extra_logical_height)
-    return extra_logical_height;
-
-  unsigned total_rows = grid_.size();
-  if (!total_rows)
-    return extra_logical_height;
-
-  if (!row_pos_[total_rows] && NextSibling())
-    return extra_logical_height;
-
-  unsigned auto_rows_count = 0;
-  int total_percent = 0;
-  for (unsigned r = 0; r < total_rows; r++) {
-    if (grid_[r].logical_height.IsAuto())
-      ++auto_rows_count;
-    else if (grid_[r].logical_height.IsPercent())
-      total_percent += grid_[r].logical_height.Percent();
-  }
-
-  int remaining_extra_logical_height = extra_logical_height;
-  DistributeExtraLogicalHeightToPercentRows(remaining_extra_logical_height,
-                                            total_percent);
-  DistributeExtraLogicalHeightToAutoRows(remaining_extra_logical_height,
-                                         auto_rows_count);
-  DistributeRemainingExtraLogicalHeight(remaining_extra_logical_height);
-  return extra_logical_height - remaining_extra_logical_height;
-}
-
-static bool CellHasExplicitlySpecifiedHeight(const LayoutTableCell& cell) {
-  if (cell.StyleRef().LogicalHeight().IsFixed())
-    return true;
-  LayoutBlock* cb = cell.ContainingBlock();
-  if (cb->AvailableLogicalHeightForPercentageComputation() == -1)
-    return false;
-  return true;
-}
-
-void LayoutTableSection::LayoutRows() {
-  NOT_DESTROYED();
-#if DCHECK_IS_ON()
-  SetLayoutNeededForbiddenScope layout_forbidden_scope(*this);
-#endif
-
-  DCHECK(!NeedsLayout());
-
-  // FIXME: Changing the height without a layout can change the overflow so it
-  // seems wrong.
-
-  unsigned total_rows = grid_.size();
-
-  // Set the width of our section now.  The rows will also be this width.
-  SetLogicalWidth(Table()->ContentLogicalWidth());
-
-  int16_t vspacing = Table()->VBorderSpacing();
-  LayoutState state(*this);
-
-  // Set the rows' location and size.
-  for (unsigned r = 0; r < total_rows; r++) {
-    if (LayoutTableRow* row = grid_[r].row) {
-      row->SetLogicalLocation(LayoutPoint(0, row_pos_[r]));
-      row->SetLogicalWidth(LogicalWidth());
-      LayoutUnit row_logical_height;
-      // If the row is collapsed then it has 0 height. vspacing was implicitly
-      // removed earlier, when row_pos_[r+1] was set to row_pos[r].
-      if (!RowHasVisibilityCollapse(r)) {
-        row_logical_height =
-            LayoutUnit(row_pos_[r + 1] - row_pos_[r] - vspacing);
-      }
-      DCHECK_GE(row_logical_height, 0);
-      if (state.IsPaginated() && r + 1 < total_rows) {
-        // If the next row has a pagination strut, we need to subtract it. It
-        // should not be included in this row's height.
-        if (LayoutTableRow* next_row_object = grid_[r + 1].row)
-          row_logical_height -= next_row_object->PaginationStrut();
-      }
-      // crbug.com/1175700
-      row_logical_height = std::max(row_logical_height, LayoutUnit());
-      row->SetLogicalHeight(row_logical_height);
-      row->UpdateAfterLayout();
-    }
-  }
-
-  // Vertically align and flex the cells in each row.
-  for (unsigned r = 0; r < total_rows; r++) {
-    LayoutTableRow* row = grid_[r].row;
-
-    unsigned n_cols = NumCols(r);
-    for (unsigned c = 0; c < n_cols; c++) {
-      LayoutTableCell* cell = OriginatingCellAt(r, c);
-      if (!cell)
-        continue;
-
-      int r_height;
-      int row_logical_top;
-      unsigned row_span = std::max(1U, cell->ResolvedRowSpan());
-      unsigned end_row_index = std::min(r + row_span, total_rows) - 1;
-      LayoutTableRow* last_row_object = grid_[end_row_index].row;
-      if (last_row_object && row) {
-        row_logical_top = row->LogicalTop().ToInt();
-        r_height = last_row_object->LogicalBottom().ToInt() - row_logical_top;
-      } else {
-        r_height = row_pos_[end_row_index + 1] - row_pos_[r] - vspacing;
-        row_logical_top = row_pos_[r];
-      }
-
-      RelayoutCellIfFlexed(*cell, r, r_height);
-
-      SubtreeLayoutScope layouter(*cell);
-      EVerticalAlign cell_vertical_align;
-      // If the cell crosses a fragmentainer boundary, just align it at the
-      // top. That's how it was laid out initially, before we knew the final
-      // row height, and re-aligning it now could result in the cell being
-      // fragmented differently, which could change its height and thus violate
-      // the requested alignment. Give up instead of risking circular
-      // dependencies and unstable layout.
-      if (state.IsPaginated() &&
-          CrossesPageBoundary(LayoutUnit(row_logical_top),
-                              LayoutUnit(r_height)))
-        cell_vertical_align = EVerticalAlign::kTop;
-      else
-        cell_vertical_align = cell->StyleRef().VerticalAlign();
-
-      // Calculate total collapsed height affecting one cell.
-      int collapsed_height = 0;
-      if (is_any_row_collapsed_) {
-        unsigned end_row = cell->ResolvedRowSpan() + r;
-        for (unsigned spanning = r; spanning < end_row; spanning++) {
-          collapsed_height += row_collapsed_height_[spanning];
-        }
-      }
-
-      cell->ComputeIntrinsicPadding(collapsed_height, r_height,
-                                    cell_vertical_align, layouter);
-
-      LayoutRect old_cell_rect = cell->FrameRect();
-
-      SetLogicalPositionForCell(cell, c);
-
-      cell->LayoutIfNeeded();
-
-      LayoutSize child_offset(cell->Location() - old_cell_rect.Location());
-      if (child_offset.Width() || child_offset.Height()) {
-        // If the child moved, we have to issue paint invalidations to it as
-        // well as any floating/positioned descendants. An exception is if we
-        // need a layout. In this case, we know we're going to issue paint
-        // invalidations ourselves (and the child) anyway.
-        if (!Table()->SelfNeedsLayout())
-          cell->SetShouldCheckForPaintInvalidation();
-      }
-    }
-    if (row)
-      row->ComputeLayoutOverflow();
-  }
-
-  DCHECK(!NeedsLayout());
-
-  SetLogicalHeight(LayoutUnit(row_pos_[total_rows]));
-
-  ComputeLayoutOverflowFromDescendants();
-}
-
-void LayoutTableSection::UpdateLogicalWidthForCollapsedCells(
-    const Vector<int>& col_collapsed_width) {
-  NOT_DESTROYED();
-  if (!RuntimeEnabledFeatures::VisibilityCollapseColumnEnabled())
-    return;
-  unsigned total_rows = grid_.size();
-  for (unsigned r = 0; r < total_rows; r++) {
-    unsigned n_cols = NumCols(r);
-    for (unsigned c = 0; c < n_cols; c++) {
-      LayoutTableCell* cell = OriginatingCellAt(r, c);
-      if (!cell)
-        continue;
-      if (!col_collapsed_width.size()) {
-        cell->SetIsSpanningCollapsedColumn(false);
-        continue;
-      }
-      // TODO(joysyu): Current behavior assumes that collapsing the first column
-      // in a col-spanning cell makes the cell width zero. This is consistent
-      // with collapsing row-spanning cells, but still needs to be specified.
-      if (cell->IsFirstColumnCollapsed()) {
-        // Collapsed cells have zero width.
-        cell->SetLogicalWidth(LayoutUnit());
-      } else if (cell->ColSpan() > 1) {
-        // A column-spanning cell may be affected by collapsed columns, so its
-        // width needs to be adjusted accordingly
-        int collapsed_width = 0;
-        cell->SetIsSpanningCollapsedColumn(false);
-        unsigned end_col = std::min(cell->ColSpan() + c, n_cols);
-        for (unsigned spanning = c; spanning < end_col; spanning++)
-          collapsed_width += col_collapsed_width[spanning];
-        cell->SetLogicalWidth(cell->LogicalWidth() - collapsed_width);
-        if (collapsed_width != 0)
-          cell->SetIsSpanningCollapsedColumn(true);
-        // Recompute overflow in case overflow clipping is necessary.
-        cell->ComputeLayoutOverflow(cell->ClientLogicalBottom(), false);
-        DCHECK_GE(cell->LogicalWidth(), 0);
-      }
-    }
-  }
-}
-
-int LayoutTableSection::PaginationStrutForRow(LayoutTableRow* row,
-                                              LayoutUnit logical_offset) const {
-  NOT_DESTROYED();
-  DCHECK(row);
-  const LayoutTableSection* footer = Table()->Footer();
-  bool make_room_for_repeating_footer =
-      footer && footer->IsRepeatingFooterGroup() && row->RowIndex();
-  if (!make_room_for_repeating_footer &&
-      row->GetLegacyPaginationBreakability() == kAllowAnyBreaks)
-    return 0;
-  if (!IsPageLogicalHeightKnown())
-    return 0;
-  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
-  // If the row is too tall for the page don't insert a strut.
-  LayoutUnit row_logical_height = row->LogicalHeight();
-  if (row_logical_height > page_logical_height)
-    return 0;
-
-  LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
-      logical_offset, LayoutBlock::kAssociateWithLatterPage);
-  if (remaining_logical_height >= row_logical_height)
-    return 0;  // It fits fine where it is. No need to break.
-  LayoutUnit pagination_strut =
-      CalculatePaginationStrutToFitContent(logical_offset, row_logical_height);
-  if (pagination_strut == remaining_logical_height &&
-      remaining_logical_height == page_logical_height) {
-    // Don't break if we were at the top of a page, and we failed to fit the
-    // content completely. No point in leaving a page completely blank.
-    return 0;
-  }
-  // Table layout parts only work on integers, so we have to round. Round up, to
-  // make sure that no fraction ever gets left behind in the previous
-  // fragmentainer.
-  return pagination_strut.Ceil();
-}
-
-void LayoutTableSection::ComputeVisualOverflowFromDescendants() {
-  NOT_DESTROYED();
-  auto old_self_visual_overflow_rect = SelfVisualOverflowRect();
-  ClearVisualOverflow();
-
-  visually_overflowing_cells_.clear();
-  force_full_paint_ = false;
-
-  // These 2 variables are used to balance the memory consumption vs the paint
-  // time on big sections with overflowing cells:
-  // 1. For small sections, don't track overflowing cells because for them the
-  //    full paint path is actually faster than the partial paint path.
-  // 2. For big sections, if overflowing cells are scarce, track overflowing
-  //    cells to enable the partial paint path.
-  // 3. Otherwise don't track overflowing cells to avoid adding a lot of cells
-  //    to the HashSet, and force the full paint path.
-  // See TableSectionPainter::PaintObject() for the full paint path and the
-  // partial paint path.
-  static const unsigned kMinCellCountToUsePartialPaint = 75 * 75;
-  static const float kMaxOverflowingCellRatioForPartialPaint = 0.1f;
-
-  unsigned total_cell_count = NumRows() * Table()->NumEffectiveColumns();
-  unsigned max_overflowing_cell_count =
-      total_cell_count < kMinCellCountToUsePartialPaint
-          ? 0
-          : kMaxOverflowingCellRatioForPartialPaint * total_cell_count;
-
-#if DCHECK_IS_ON()
-  bool has_overflowing_cell = false;
-#endif
-  for (auto* row = FirstRow(); row; row = row->NextRow()) {
-    AddVisualOverflowFromChild(*row);
-
-    for (auto* cell = row->FirstCell(); cell; cell = cell->NextCell()) {
-      if (cell->HasSelfPaintingLayer())
-        continue;
-      if (force_full_paint_ || !cell->HasVisualOverflow())
-        continue;
-
-#if DCHECK_IS_ON()
-      has_overflowing_cell = true;
-#endif
-      if (visually_overflowing_cells_.size() >= max_overflowing_cell_count) {
-        force_full_paint_ = true;
-        // The full paint path does not make any use of the overflowing cells
-        // info, so don't hold on to the memory.
-        visually_overflowing_cells_.clear();
-        continue;
-      }
-
-      visually_overflowing_cells_.insert(cell);
-    }
-  }
-
-#if DCHECK_IS_ON()
-  DCHECK_EQ(has_overflowing_cell, HasVisuallyOverflowingCell());
-#endif
-
-  // Overflow rect contributes to the visual rect, so if it has changed then we
-  // need to signal a possible paint invalidation.
-  if (old_self_visual_overflow_rect != SelfVisualOverflowRect())
-    SetShouldCheckForPaintInvalidation();
-}
-
-void LayoutTableSection::ComputeLayoutOverflowFromDescendants() {
-  NOT_DESTROYED();
-  ClearLayoutOverflow();
-  for (auto* row = FirstRow(); row; row = row->NextRow())
-    AddLayoutOverflowFromChild(*row);
-}
-
-LayoutNGTableRowInterface* LayoutTableSection::FirstRowInterface() const {
-  NOT_DESTROYED();
-  return FirstRow();
-}
-LayoutNGTableRowInterface* LayoutTableSection::LastRowInterface() const {
-  NOT_DESTROYED();
-  return LastRow();
-}
-
-RecalcLayoutOverflowResult LayoutTableSection::RecalcLayoutOverflow() {
-  NOT_DESTROYED();
-  if (!ChildNeedsLayoutOverflowRecalc())
-    return RecalcLayoutOverflowResult();
-
-  ClearChildNeedsLayoutOverflowRecalc();
-  unsigned total_rows = grid_.size();
-  bool children_layout_overflow_changed = false;
-  for (unsigned r = 0; r < total_rows; r++) {
-    LayoutTableRow* row_layouter = RowLayoutObjectAt(r);
-    if (!row_layouter || !row_layouter->ChildNeedsLayoutOverflowRecalc())
-      continue;
-    row_layouter->ClearChildNeedsLayoutOverflowRecalc();
-    bool row_children_layout_overflow_changed = false;
-    unsigned n_cols = NumCols(r);
-    for (unsigned c = 0; c < n_cols; c++) {
-      auto* cell = OriginatingCellAt(r, c);
-      if (!cell)
-        continue;
-      row_children_layout_overflow_changed |=
-          cell->RecalcLayoutOverflow().layout_overflow_changed;
-    }
-    if (row_children_layout_overflow_changed)
-      row_layouter->ComputeLayoutOverflow();
-    children_layout_overflow_changed |= row_children_layout_overflow_changed;
-  }
-  if (children_layout_overflow_changed)
-    ComputeLayoutOverflowFromDescendants();
-
-  return {children_layout_overflow_changed, /* rebuild_fragment_tree */ false};
-}
-
-void LayoutTableSection::RecalcVisualOverflow() {
-  NOT_DESTROYED();
-  SECURITY_CHECK(!needs_cell_recalc_);
-  unsigned total_rows = grid_.size();
-  for (unsigned r = 0; r < total_rows; r++) {
-    LayoutTableRow* row_layouter = RowLayoutObjectAt(r);
-    if (!row_layouter || (row_layouter->HasLayer() &&
-                          row_layouter->Layer()->IsSelfPaintingLayer()))
-      continue;
-    row_layouter->RecalcVisualOverflow();
-  }
-  ComputeVisualOverflowFromDescendants();
-  AddVisualEffectOverflow();
-}
-
-void LayoutTableSection::MarkAllCellsWidthsDirtyAndOrNeedsLayout(
-    LayoutTable::WhatToMarkAllCells what_to_mark) {
-  NOT_DESTROYED();
-  for (LayoutTableRow* row = FirstRow(); row; row = row->NextRow()) {
-    for (LayoutTableCell* cell = row->FirstCell(); cell;
-         cell = cell->NextCell()) {
-      cell->SetIntrinsicLogicalWidthsDirty();
-      if (what_to_mark == LayoutTable::kMarkDirtyAndNeedsLayout)
-        cell->SetChildNeedsLayout();
-    }
-  }
-}
-
-LayoutUnit LayoutTableSection::FirstLineBoxBaseline() const {
-  NOT_DESTROYED();
-  DCHECK(!NeedsCellRecalc());
-  if (!grid_.size())
-    return LayoutUnit(-1);
-
-  LayoutUnit first_line_baseline(grid_[0].baseline);
-  if (first_line_baseline >= 0)
-    return first_line_baseline + row_pos_[0];
-
-  for (const auto& grid_cell : grid_[0].grid_cells) {
-    if (const auto* cell = grid_cell.PrimaryCell()) {
-      first_line_baseline = std::max<LayoutUnit>(
-          first_line_baseline, cell->LogicalTop() + cell->BorderBefore() +
-                                   cell->PaddingBefore() +
-                                   cell->ContentLogicalHeight());
-    }
-  }
-
-  return first_line_baseline;
-}
-
-void LayoutTableSection::Paint(const PaintInfo& paint_info) const {
-  NOT_DESTROYED();
-  TableSectionPainter(*this).Paint(paint_info);
-}
-
-LayoutRect LayoutTableSection::LogicalRectForWritingModeAndDirection(
-    const PhysicalRect& rect) const {
-  NOT_DESTROYED();
-  LayoutRect table_aligned_rect = FlipForWritingMode(rect);
-
-  if (!TableStyle().IsHorizontalWritingMode())
-    table_aligned_rect = table_aligned_rect.TransposedRect();
-
-  const Vector<int>& column_pos = Table()->EffectiveColumnPositions();
-  if (!TableStyle().IsLeftToRightDirection()) {
-    table_aligned_rect.SetX(column_pos[column_pos.size() - 1] -
-                            table_aligned_rect.MaxX());
-  }
-
-  return table_aligned_rect;
-}
-
-void LayoutTableSection::DirtiedRowsAndEffectiveColumns(
-    const LayoutRect& damage_rect,
-    CellSpan& rows,
-    CellSpan& columns) const {
-  NOT_DESTROYED();
-  DCHECK(!NeedsCellRecalc());
-  if (!grid_.size()) {
-    rows = CellSpan();
-    columns = CellSpan(1, 1);
-    return;
-  }
-
-  if (force_full_paint_) {
-    rows = FullSectionRowSpan();
-    columns = FullTableEffectiveColumnSpan();
-    return;
-  }
-
-  rows = SpannedRows(damage_rect);
-  columns = SpannedEffectiveColumns(damage_rect);
-
-  // Expand by one cell in each direction to cover any collapsed borders.
-  if (Table()->ShouldCollapseBorders()) {
-    if (rows.Start() > 0)
-      rows.DecreaseStart();
-    if (rows.End() < grid_.size())
-      rows.IncreaseEnd();
-    if (columns.Start() > 0)
-      columns.DecreaseStart();
-    if (columns.End() < Table()->NumEffectiveColumns())
-      columns.IncreaseEnd();
-  }
-
-  rows.EnsureConsistency(grid_.size());
-  columns.EnsureConsistency(Table()->NumEffectiveColumns());
-
-  if (!has_spanning_cells_)
-    return;
-
-  if (rows.Start() > 0 && rows.Start() < grid_.size()) {
-    // If there are any cells spanning into the first row, expand |rows| to
-    // cover the cells.
-    unsigned n_cols = NumCols(rows.Start());
-    unsigned smallest_row = rows.Start();
-    for (unsigned c = columns.Start(); c < std::min(columns.End(), n_cols);
-         ++c) {
-      for (const auto& cell : GridCellAt(rows.Start(), c).Cells()) {
-        smallest_row = std::min(smallest_row, cell->RowIndex());
-        if (!smallest_row)
-          break;
-      }
-    }
-    rows = CellSpan(smallest_row, rows.End());
-  }
-
-  if (columns.Start() > 0 && columns.Start() < Table()->NumEffectiveColumns()) {
-    // If there are any cells spanning into the first column, expand |columns|
-    // to cover the cells.
-    unsigned smallest_column = columns.Start();
-    for (unsigned r = rows.Start(); r < rows.End(); ++r) {
-      const auto& grid_cells = grid_[r].grid_cells;
-      if (columns.Start() < grid_cells.size()) {
-        unsigned c = columns.Start();
-        while (c && grid_cells[c].InColSpan())
-          --c;
-        smallest_column = std::min(c, smallest_column);
-        if (!smallest_column)
-          break;
-      }
-    }
-    columns = CellSpan(smallest_column, columns.End());
-  }
-}
-
-CellSpan LayoutTableSection::SpannedRows(const LayoutRect& flipped_rect) const {
-  NOT_DESTROYED();
-  // Find the first row that starts after rect top.
-  unsigned next_row = static_cast<unsigned>(
-      std::upper_bound(row_pos_.begin(), row_pos_.end(), flipped_rect.Y()) -
-      row_pos_.begin());
-
-  // After all rows.
-  if (next_row == row_pos_.size())
-    return CellSpan(row_pos_.size() - 1, row_pos_.size() - 1);
-
-  unsigned start_row = next_row > 0 ? next_row - 1 : 0;
-
-  // Find the first row that starts after rect bottom.
-  unsigned end_row;
-  if (row_pos_[next_row] >= flipped_rect.MaxY()) {
-    end_row = next_row;
-  } else {
-    end_row = static_cast<unsigned>(
-        std::upper_bound(row_pos_.begin() + next_row, row_pos_.end(),
-                         flipped_rect.MaxY()) -
-        row_pos_.begin());
-    if (end_row == row_pos_.size())
-      end_row = row_pos_.size() - 1;
-  }
-
-  return CellSpan(start_row, end_row);
-}
-
-CellSpan LayoutTableSection::SpannedEffectiveColumns(
-    const LayoutRect& flipped_rect) const {
-  NOT_DESTROYED();
-  const Vector<int>& column_pos = Table()->EffectiveColumnPositions();
-
-  // Find the first column that starts after rect left.
-  // lower_bound doesn't handle the edge between two cells properly as it would
-  // wrongly return the cell on the logical top/left.
-  // upper_bound on the other hand properly returns the cell on the logical
-  // bottom/right, which also matches the behavior of other browsers.
-  unsigned next_column = static_cast<unsigned>(
-      std::upper_bound(column_pos.begin(), column_pos.end(), flipped_rect.X()) -
-      column_pos.begin());
-
-  if (next_column == column_pos.size())
-    return CellSpan(column_pos.size() - 1,
-                    column_pos.size() - 1);  // After all columns.
-
-  unsigned start_column = next_column > 0 ? next_column - 1 : 0;
-
-  // Find the first column that starts after rect right.
-  unsigned end_column;
-  if (column_pos[next_column] >= flipped_rect.MaxX()) {
-    end_column = next_column;
-  } else {
-    end_column = static_cast<unsigned>(
-        std::upper_bound(column_pos.begin() + next_column, column_pos.end(),
-                         flipped_rect.MaxX()) -
-        column_pos.begin());
-    if (end_column == column_pos.size())
-      end_column = column_pos.size() - 1;
-  }
-
-  return CellSpan(start_column, end_column);
-}
-
-void LayoutTableSection::RecalcCells() {
-  NOT_DESTROYED();
-  DCHECK(needs_cell_recalc_);
-  // We reset the flag here to ensure that |addCell| works. This is safe to do
-  // as fillRowsWithDefaultStartingAtPosition makes sure we match the table's
-  // columns representation.
-  needs_cell_recalc_ = false;
-
-  c_col_ = 0;
-  c_row_ = 0;
-  grid_.clear();
-
-  bool resized_grid = false;
-  for (LayoutTableRow* row = FirstRow(); row; row = row->NextRow()) {
-    unsigned insertion_row = c_row_;
-    ++c_row_;
-    c_col_ = 0;
-    EnsureRows(c_row_);
-
-    grid_[insertion_row].row = row;
-    row->SetRowIndex(insertion_row);
-    grid_[insertion_row].SetRowLogicalHeightToRowStyleLogicalHeight();
-
-    for (LayoutTableCell* cell = row->FirstCell(); cell;
-         cell = cell->NextCell()) {
-      // For rowspan, "the value zero means that the cell is to span all the
-      // remaining rows in the row group." Calculate the size of the full
-      // row grid now so that we can use it to count the remaining rows in
-      // ResolvedRowSpan().
-      if (!cell->ParsedRowSpan() && !resized_grid) {
-        unsigned c_row = row->RowIndex() + 1;
-        for (LayoutTableRow* remaining_row = row; remaining_row;
-             remaining_row = remaining_row->NextRow())
-          c_row++;
-        EnsureRows(c_row);
-        resized_grid = true;
-      }
-      AddCell(cell, row);
-    }
-  }
-
-  grid_.shrink_to_fit();
-  SetNeedsLayoutAndFullPaintInvalidation(layout_invalidation_reason::kUnknown);
-}
-
-// FIXME: This function could be made O(1) in certain cases (like for the
-// non-most-constrainive cells' case).
-void LayoutTableSection::RowLogicalHeightChanged(LayoutTableRow* row) {
-  NOT_DESTROYED();
-  if (NeedsCellRecalc())
-    return;
-
-  unsigned row_index = row->RowIndex();
-  grid_[row_index].SetRowLogicalHeightToRowStyleLogicalHeight();
-
-  for (LayoutTableCell* cell = grid_[row_index].row->FirstCell(); cell;
-       cell = cell->NextCell())
-    grid_[row_index].UpdateLogicalHeightForCell(cell);
-}
-
-void LayoutTableSection::SetNeedsCellRecalc() {
-  NOT_DESTROYED();
-  needs_cell_recalc_ = true;
-  SetNeedsOverflowRecalc();
-  if (LayoutTable* t = Table())
-    t->SetNeedsSectionRecalc();
-}
-
-unsigned LayoutTableSection::NumEffectiveColumns() const {
-  NOT_DESTROYED();
-  unsigned result = 0;
-
-  for (unsigned r = 0; r < grid_.size(); ++r) {
-    unsigned n_cols = NumCols(r);
-    for (unsigned c = result; c < n_cols; ++c) {
-      const auto& grid_cell = GridCellAt(r, c);
-      if (grid_cell.HasCells() || grid_cell.InColSpan())
-        result = c;
-    }
-  }
-
-  return result + 1;
-}
-
-LayoutTableCell* LayoutTableSection::OriginatingCellAt(
-    unsigned row,
-    unsigned effective_column) {
-  NOT_DESTROYED();
-  SECURITY_CHECK(!needs_cell_recalc_);
-  if (effective_column >= NumCols(row))
-    return nullptr;
-  auto& grid_cell = GridCellAt(row, effective_column);
-  if (grid_cell.InColSpan())
-    return nullptr;
-  if (auto* cell = grid_cell.PrimaryCell()) {
-    if (cell->RowIndex() == row)
-      return cell;
-  }
-  return nullptr;
-}
-
-void LayoutTableSection::AppendEffectiveColumn(unsigned pos) {
-  NOT_DESTROYED();
-  DCHECK(!needs_cell_recalc_);
-
-  for (auto& row : grid_)
-    row.grid_cells.resize(pos + 1);
-}
-
-void LayoutTableSection::SplitEffectiveColumn(unsigned pos, unsigned first) {
-  NOT_DESTROYED();
-  DCHECK(!needs_cell_recalc_);
-
-  if (c_col_ > pos)
-    c_col_++;
-  for (unsigned row = 0; row < grid_.size(); ++row) {
-    auto& grid_cells = grid_[row].grid_cells;
-    EnsureCols(row, pos + 1);
-    grid_cells.insert(pos + 1, TableGridCell());
-    if (grid_cells[pos].HasCells()) {
-      grid_cells[pos + 1].Cells().AppendVector(grid_cells[pos].Cells());
-      LayoutTableCell* cell = grid_cells[pos].PrimaryCell();
-      DCHECK(cell);
-      DCHECK_GE(cell->ColSpan(), (grid_cells[pos].InColSpan() ? 1u : 0));
-      unsigned colleft = cell->ColSpan() - grid_cells[pos].InColSpan();
-      if (first > colleft)
-        grid_cells[pos + 1].SetInColSpan(false);
-      else
-        grid_cells[pos + 1].SetInColSpan(first || grid_cells[pos].InColSpan());
-    } else {
-      grid_cells[pos + 1].SetInColSpan(false);
-    }
-  }
-}
-
-// Hit Testing
-bool LayoutTableSection::NodeAtPoint(HitTestResult& result,
-                                     const HitTestLocation& hit_test_location,
-                                     const PhysicalOffset& accumulated_offset,
-                                     HitTestPhase phase) {
-  NOT_DESTROYED();
-  // If we have no children then we have nothing to do.
-  if (!FirstRow())
-    return false;
-
-  DCHECK(!HasNonVisibleOverflow());
-
-  // Table sections cannot ever be hit tested.  Effectively they do not exist.
-  // Just forward to our children always.
-  if (HasVisuallyOverflowingCell()) {
-    for (LayoutTableRow* row = LastRow(); row; row = row->PreviousRow()) {
-      if (row->HasSelfPaintingLayer())
-        continue;
-      PhysicalOffset row_accumulated_offset =
-          accumulated_offset + row->PhysicalLocation(this);
-      if (row->NodeAtPoint(result, hit_test_location, row_accumulated_offset,
-                           phase)) {
-        UpdateHitTestResult(result,
-                            hit_test_location.Point() - accumulated_offset);
-        return true;
-      }
-    }
-    return false;
-  }
-
-  RecalcCellsIfNeeded();
-
-  PhysicalRect hit_test_rect = hit_test_location.BoundingBox();
-  hit_test_rect.Move(-accumulated_offset);
-
-  LayoutRect table_aligned_rect =
-      LogicalRectForWritingModeAndDirection(hit_test_rect);
-  CellSpan row_span = SpannedRows(table_aligned_rect);
-  CellSpan column_span = SpannedEffectiveColumns(table_aligned_rect);
-
-  // Now iterate over the spanned rows and columns.
-  for (unsigned hit_row = row_span.Start(); hit_row < row_span.End();
-       ++hit_row) {
-    unsigned n_cols = NumCols(hit_row);
-    for (unsigned hit_column = column_span.Start();
-         hit_column < n_cols && hit_column < column_span.End(); ++hit_column) {
-      auto& grid_cell = GridCellAt(hit_row, hit_column);
-
-      // If the cell is empty, there's nothing to do
-      if (!grid_cell.HasCells())
-        continue;
-
-      for (unsigned i = grid_cell.Cells().size(); i;) {
-        --i;
-        LayoutTableCell* cell = grid_cell.Cells()[i];
-        PhysicalOffset cell_accumulated_offset =
-            accumulated_offset + cell->PhysicalLocation(this);
-        if (static_cast<LayoutObject*>(cell)->NodeAtPoint(
-                result, hit_test_location, cell_accumulated_offset, phase)) {
-          UpdateHitTestResult(result,
-                              hit_test_location.Point() - accumulated_offset);
-          return true;
-        }
-      }
-      if (!result.GetHitTestRequest().ListBased())
-        break;
-    }
-    if (!result.GetHitTestRequest().ListBased())
-      break;
-  }
-
-  return false;
-}
-
-LayoutBox* LayoutTableSection::CreateAnonymousBoxWithSameTypeAs(
-    const LayoutObject* parent) const {
-  NOT_DESTROYED();
-  return LayoutObjectFactory::CreateAnonymousTableSectionWithParent(*parent);
-}
-
-void LayoutTableSection::SetLogicalPositionForCell(
-    LayoutTableCell* cell,
-    unsigned effective_column) const {
-  NOT_DESTROYED();
-  LayoutPoint cell_location(0, row_pos_[cell->RowIndex()]);
-  int16_t horizontal_border_spacing = Table()->HBorderSpacing();
-
-  if (!TableStyle().IsLeftToRightDirection()) {
-    cell_location.SetX(LayoutUnit(
-        Table()->EffectiveColumnPositions()[Table()->NumEffectiveColumns()] -
-        Table()->EffectiveColumnPositions()
-            [Table()->AbsoluteColumnToEffectiveColumn(
-                cell->AbsoluteColumnIndex() + cell->ColSpan())] +
-        horizontal_border_spacing));
-  } else {
-    cell_location.SetX(
-        LayoutUnit(Table()->EffectiveColumnPositions()[effective_column] +
-                   horizontal_border_spacing));
-  }
-
-  cell->SetLogicalLocation(cell_location);
-}
-
-void LayoutTableSection::RelayoutCellIfFlexed(LayoutTableCell& cell,
-                                              int row_index,
-                                              int row_height) {
-  NOT_DESTROYED();
-  // Force percent height children to lay themselves out again now that the
-  // cell's final height is determined.
-  // FIXME: There is still more work to do here to fully match WinIE (should
-  // it become necessary to do so).  In quirks mode, WinIE behaves like we
-  // do, but it will clip the cells that spill out of the table section.
-  // strict mode, Mozilla and WinIE both regrow the table to accommodate the
-  // new height of the cell (thus letting the percentages cause growth one
-  // time only). We may also not be handling row-spanning cells correctly.
-
-  if (!CellHasExplicitlySpecifiedHeight(cell) &&
-      (Table()->StyleRef().LogicalHeight().IsAuto() ||
-       row_height == cell.LogicalHeight()))
-    return;
-
-  bool any_child_needs_relayout = cell.HasPercentHeightDescendants();
-
-  if (!any_child_needs_relayout) {
-    for (LayoutObject* child = cell.FirstChild(); child;
-         child = child->NextSibling()) {
-      if (!child->IsText() &&
-          child->StyleRef().LogicalHeight().IsPercentOrCalc() &&
-          (!child->IsTable() || (!child->IsOutOfFlowPositioned() &&
-                                 To<LayoutTable>(child)->HasSections()))) {
-        any_child_needs_relayout = true;
-        break;
-      }
-    }
-  }
-
-  if (!any_child_needs_relayout)
-    return;
-
-  cell.SetOverrideLogicalHeightFromRowHeight(LayoutUnit(row_height));
-  cell.ForceLayout();
-
-  // If the baseline moved, we may have to update the data for our row. Find
-  // out the new baseline.
-  if (cell.IsBaselineAligned()) {
-    LayoutUnit baseline = cell.CellBaselinePosition();
-    if (baseline > cell.BorderBefore() + cell.PaddingBefore())
-      grid_[row_index].baseline = std::max(grid_[row_index].baseline, baseline);
-  }
-}
-
-int LayoutTableSection::LogicalHeightForRow(
-    const LayoutTableRow& row_object) const {
-  NOT_DESTROYED();
-  unsigned row_index = row_object.RowIndex();
-  DCHECK_LT(row_index, grid_.size());
-  int logical_height = 0;
-  for (auto& grid_cell : grid_[row_index].grid_cells) {
-    const LayoutTableCell* cell = grid_cell.PrimaryCell();
-    if (!cell || grid_cell.InColSpan())
-      continue;
-    unsigned row_span = cell->ResolvedRowSpan();
-    if (row_span == 1) {
-      logical_height =
-          std::max(logical_height, cell->LogicalHeightForRowSizing());
-      continue;
-    }
-    unsigned row_index_for_cell = cell->RowIndex();
-    if (row_index == grid_.size() - 1 ||
-        (row_span > 1 && row_index - row_index_for_cell == row_span - 1)) {
-      // This is the last row of the rowspanned cell. Add extra height if
-      // needed.
-      if (LayoutTableRow* first_row_for_cell = grid_[row_index_for_cell].row) {
-        int min_logical_height = cell->LogicalHeightForRowSizing();
-        // Subtract space provided by previous rows.
-        min_logical_height -= row_object.LogicalTop().ToInt() -
-                              first_row_for_cell->LogicalTop().ToInt();
-
-        logical_height = std::max(logical_height, min_logical_height);
-      }
-    }
-  }
-
-  if (grid_[row_index].logical_height.IsSpecified()) {
-    LayoutUnit specified_logical_height =
-        MinimumValueForLength(grid_[row_index].logical_height, LayoutUnit());
-    // We round here to match computations for row_pos_ in
-    // CalcRowLogicalHeight().
-    logical_height = std::max(logical_height, specified_logical_height.Round());
-  }
-  return logical_height;
-}
-
-int LayoutTableSection::OffsetForRepeatedHeader() const {
-  NOT_DESTROYED();
-  LayoutTableSection* header = Table()->Header();
-  if (header && header != this)
-    return Table()->RowOffsetFromRepeatingHeader().ToInt();
-  LayoutState* layout_state = View()->GetLayoutState();
-  return layout_state->HeightOffsetForTableHeaders().ToInt();
-}
-
-void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object,
-                                                SubtreeLayoutScope& layouter) {
-  NOT_DESTROYED();
-  row_object.SetPaginationStrut(LayoutUnit());
-  row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object)));
-  if (!IsPageLogicalHeightKnown())
-    return;
-  int pagination_strut =
-      PaginationStrutForRow(&row_object, row_object.LogicalTop());
-  bool row_is_at_top_of_column = false;
-  LayoutUnit offset_from_top_of_page;
-  if (!pagination_strut) {
-    LayoutUnit page_logical_height =
-        PageLogicalHeightForOffset(row_object.LogicalTop());
-    if (OffsetForRepeatedHeader()) {
-      offset_from_top_of_page =
-          page_logical_height -
-          PageRemainingLogicalHeightForOffset(row_object.LogicalTop(),
-                                              kAssociateWithLatterPage);
-      row_is_at_top_of_column =
-          !offset_from_top_of_page ||
-          offset_from_top_of_page <= OffsetForRepeatedHeader() ||
-          offset_from_top_of_page <= Table()->VBorderSpacing();
-    }
-
-    if (!row_is_at_top_of_column)
-      return;
-  }
-  // We need to push this row to the next fragmentainer. If there are repeated
-  // table headers, we need to make room for those at the top of the next
-  // fragmentainer, above this row. Otherwise, this row will just go at the top
-  // of the next fragmentainer.
-
-  // Border spacing from the previous row has pushed this row just past the top
-  // of the page, so we must reposition it to the top of the page and avoid any
-  // repeating header.
-  if (row_is_at_top_of_column && offset_from_top_of_page)
-    pagination_strut -= offset_from_top_of_page.ToInt();
-
-  // If we have a header group we will paint it at the top of each page,
-  // move the rows down to accommodate it.
-  int additional_adjustment = OffsetForRepeatedHeader();
-
-  // If the table collapses borders, push the row down by the max height of the
-  // outer half borders to make the whole collapsed borders on the next page.
-  if (Table()->ShouldCollapseBorders()) {
-    for (const auto* cell = row_object.FirstCell(); cell;
-         cell = cell->NextCell()) {
-      additional_adjustment = std::max<int>(additional_adjustment,
-                                            cell->CollapsedOuterBorderBefore());
-    }
-  }
-
-  pagination_strut += additional_adjustment;
-  row_object.SetPaginationStrut(LayoutUnit(pagination_strut));
-
-  // We have inserted a pagination strut before the row. Adjust the logical top
-  // and re-lay out. We no longer want to break inside the row, but rather
-  // *before* it. From the previous layout pass, there are most likely
-  // pagination struts inside some cell in this row that we need to get rid of.
-  row_object.SetLogicalTop(row_object.LogicalTop() + pagination_strut);
-  layouter.SetChildNeedsLayout(&row_object);
-  row_object.LayoutIfNeeded();
-
-  // It's very likely that re-laying out (and nuking pagination struts inside
-  // cells) gave us a new height.
-  row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object)));
-}
-
-bool LayoutTableSection::GroupShouldRepeat() const {
-  NOT_DESTROYED();
-  DCHECK(Table()->Header() == this || Table()->Footer() == this);
-  if (GetLegacyPaginationBreakability() == kAllowAnyBreaks)
-    return false;
-
-  // If we don't know the page height yet, just assume we fit.
-  if (!IsPageLogicalHeightKnown())
-    return true;
-  LayoutUnit page_height = PageLogicalHeightForOffset(LayoutUnit());
-
-  LayoutUnit logical_height = LogicalHeight() - OffsetForRepeatedHeader();
-  if (logical_height > page_height)
-    return false;
-
-  // See https://drafts.csswg.org/css-tables-3/#repeated-headers which says
-  // a header/footer can repeat if it takes up less than a quarter of the page.
-  if (logical_height > 0 && page_height / logical_height < 4)
-    return false;
-
-  return true;
-}
-
-bool LayoutTableSection::MapToVisualRectInAncestorSpaceInternal(
-    const LayoutBoxModelObject* ancestor,
-    TransformState& transform_state,
-    VisualRectFlags flags) const {
-  NOT_DESTROYED();
-  if (ancestor == this)
-    return true;
-  // Repeating table headers and footers are painted once per
-  // page/column. So we need to use the rect for the entire table because
-  // the repeating headers/footers will appear throughout it.
-  // This does not go through the regular fragmentation machinery, so we need
-  // special code to expand the invalidation rect to contain all positions of
-  // the header in all columns.
-  // Note that this is in flow thread coordinates, not visual coordinates. The
-  // enclosing LayoutFlowThread will convert to visual coordinates.
-  if (IsRepeatingHeaderGroup() || IsRepeatingFooterGroup()) {
-    transform_state.Flatten();
-    gfx::RectF rect = transform_state.LastPlanarQuad().BoundingBox();
-    rect.set_height(Table()->LogicalHeight());
-    transform_state.SetQuad(gfx::QuadF(rect));
-    return Table()->MapToVisualRectInAncestorSpaceInternal(
-        ancestor, transform_state, flags);
-  }
-  return LayoutTableBoxComponent::MapToVisualRectInAncestorSpaceInternal(
-      ancestor, transform_state, flags);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_table_section.h b/third_party/blink/renderer/core/layout/layout_table_section.h
deleted file mode 100644
index 71cfe2f..0000000
--- a/third_party/blink/renderer/core/layout/layout_table_section.h
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- *           (C) 1997 Torben Weis (weis@kde.org)
- *           (C) 1998 Waldo Bastian (bastian@kde.org)
- *           (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2009, 2013 Apple Inc. All rights
- * reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_SECTION_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_SECTION_H_
-
-#include "base/notreached.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_box_component.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h"
-#include "third_party/blink/renderer/core/layout/table_grid_cell.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-// Helper class for paintObject.
-class CellSpan {
-  STACK_ALLOCATED();
-
- public:
-  CellSpan() : start_(0), end_(0) {}
-  CellSpan(unsigned start, unsigned end) : start_(start), end_(end) {}
-
-  unsigned Start() const { return start_; }
-  unsigned End() const { return end_; }
-
-  void DecreaseStart() { --start_; }
-  void IncreaseEnd() { ++end_; }
-
-  void EnsureConsistency(const unsigned);
-
- private:
-  unsigned start_;
-  unsigned end_;
-};
-
-inline bool operator==(const CellSpan& s1, const CellSpan& s2) {
-  return s1.Start() == s2.Start() && s1.End() == s2.End();
-}
-inline bool operator!=(const CellSpan& s1, const CellSpan& s2) {
-  return !(s1 == s2);
-}
-
-class LayoutTableCell;
-class LayoutTableRow;
-
-// LayoutTableSection is used to represent table row group (display:
-// table-row-group), header group (display: table-header-group) and footer group
-// (display: table-footer-group).
-//
-// The object holds the internal representation of the rows (m_grid). See
-// recalcCells() below for some extra explanation.
-//
-// A lot of the complexity in this class is related to handling rowspan, colspan
-// or just non-regular tables.
-//
-// Example of rowspan / colspan leading to overlapping cells (rowspan and
-// colspan are overlapping):
-// <table>
-//   <tr>
-//       <td>first row</td>
-//       <td rowspan="2">rowspan</td>
-//     </tr>
-//    <tr>
-//        <td colspan="2">colspan</td>
-//     </tr>
-// </table>
-//
-// Example of non-regular table (missing one cell in the first row):
-// <!DOCTYPE html>
-// <table>
-//   <tr><td>First row only child.</td></tr>
-//   <tr>
-//     <td>Second row first child</td>
-//     <td>Second row second child</td>
-//   </tr>
-// </table>
-//
-// LayoutTableSection is responsible for laying out LayoutTableRows and
-// LayoutTableCells (see layoutRows()). However it is not their containing
-// block, the enclosing LayoutTable (this object's parent()) is. This is why
-// this class inherits from LayoutTableBoxComponent and not LayoutBlock.
-class CORE_EXPORT LayoutTableSection final
-    : public LayoutTableBoxComponent,
-      public LayoutNGTableSectionInterface {
- public:
-  explicit LayoutTableSection(Element*);
-  ~LayoutTableSection() override;
-  void Trace(Visitor*) const override;
-
-  LayoutTableRow* FirstRow() const;
-  LayoutTableRow* LastRow() const;
-
-  void AddChild(LayoutObject* child,
-                LayoutObject* before_child = nullptr) override;
-
-  LayoutUnit FirstLineBoxBaseline() const override;
-
-  void AddCell(LayoutTableCell*, LayoutTableRow*);
-
-  int16_t VBorderSpacingBeforeFirstRow() const;
-  int CalcRowLogicalHeight();
-  void LayoutRows();
-  RecalcLayoutOverflowResult RecalcLayoutOverflow() final;
-  void RecalcVisualOverflow() final;
-
-  void MarkAllCellsWidthsDirtyAndOrNeedsLayout(LayoutTable::WhatToMarkAllCells);
-
-  LayoutTable* Table() const final {
-    NOT_DESTROYED();
-    return To<LayoutTable>(Parent());
-  }
-
-  typedef HeapVector<Member<LayoutTableCell>, 2> SpanningLayoutTableCells;
-
-  struct SpanningRowsHeight {
-    STACK_ALLOCATED();
-
-   public:
-    SpanningRowsHeight()
-        : total_rows_height(0),
-          spanning_cell_height_ignoring_border_spacing(0),
-          is_any_row_with_only_spanning_cells(false) {}
-    SpanningRowsHeight(const SpanningRowsHeight&) = delete;
-    SpanningRowsHeight& operator=(const SpanningRowsHeight&) = delete;
-    Vector<int> row_height;
-    int total_rows_height;
-    int spanning_cell_height_ignoring_border_spacing;
-    bool is_any_row_with_only_spanning_cells;
-  };
-
-  TableGridCell& GridCellAt(unsigned row, unsigned effective_column) {
-    NOT_DESTROYED();
-    SECURITY_DCHECK(!needs_cell_recalc_);
-    return grid_[row].grid_cells[effective_column];
-  }
-  const TableGridCell& GridCellAt(unsigned row,
-                                  unsigned effective_column) const {
-    NOT_DESTROYED();
-    SECURITY_DCHECK(!needs_cell_recalc_);
-    return grid_[row].grid_cells[effective_column];
-  }
-  LayoutTableCell* PrimaryCellAt(unsigned row, unsigned effective_column) {
-    NOT_DESTROYED();
-    SECURITY_DCHECK(!needs_cell_recalc_);
-    auto& grid_cells = grid_[row].grid_cells;
-    if (effective_column >= grid_cells.size())
-      return nullptr;
-    return grid_cells[effective_column].PrimaryCell();
-  }
-  const LayoutTableCell* PrimaryCellAt(unsigned row,
-                                       unsigned effective_column) const {
-    NOT_DESTROYED();
-    return const_cast<LayoutTableSection*>(this)->PrimaryCellAt(
-        row, effective_column);
-  }
-
-  // Returns the primary cell at (row, effectiveColumn) if the cell exists and
-  // originates from (instead of spanning into) the grid slot, or nullptr.
-  LayoutTableCell* OriginatingCellAt(unsigned row, unsigned effective_column);
-  const LayoutTableCell* OriginatingCellAt(unsigned row,
-                                           unsigned effective_column) const {
-    NOT_DESTROYED();
-    return const_cast<LayoutTableSection*>(this)->OriginatingCellAt(
-        row, effective_column);
-  }
-
-  unsigned NumCols(unsigned row) const final {
-    NOT_DESTROYED();
-    DCHECK(!NeedsCellRecalc());
-    return grid_[row].grid_cells.size();
-  }
-
-  // Returns null for cells with a rowspan that exceed the last row. Possibly
-  // others.
-  LayoutTableRow* RowLayoutObjectAt(unsigned row) {
-    NOT_DESTROYED();
-    SECURITY_DCHECK(!needs_cell_recalc_);
-    return grid_[row].row;
-  }
-  const LayoutTableRow* RowLayoutObjectAt(unsigned row) const {
-    NOT_DESTROYED();
-    SECURITY_DCHECK(!needs_cell_recalc_);
-    return grid_[row].row;
-  }
-
-  void AppendEffectiveColumn(unsigned pos);
-  void SplitEffectiveColumn(unsigned pos, unsigned first);
-
-  unsigned NumRows() const final {
-    NOT_DESTROYED();
-    DCHECK(!NeedsCellRecalc());
-    return grid_.size();
-  }
-  unsigned NumEffectiveColumns() const final;
-
-  // recalcCells() is used when we are not sure about the section's structure
-  // and want to do an expensive (but safe) reconstruction of m_grid from
-  // scratch.
-  // An example of this is inserting a new cell in the middle of an existing
-  // row or removing a row.
-  //
-  // Accessing m_grid when m_needsCellRecalc is set is UNSAFE as pointers can
-  // be left dangling. Thus care should be taken in the code to check
-  // m_needsCellRecalc before accessing m_grid.
-  void RecalcCells();
-  void RecalcCellsIfNeeded() {
-    NOT_DESTROYED();
-    if (needs_cell_recalc_)
-      RecalcCells();
-  }
-
-  bool NeedsCellRecalc() const {
-    NOT_DESTROYED();
-    return needs_cell_recalc_;
-  }
-  void SetNeedsCellRecalc() final;
-
-  LayoutUnit RowBaseline(unsigned row) {
-    NOT_DESTROYED();
-    return grid_[row].baseline;
-  }
-
-  void RowLogicalHeightChanged(LayoutTableRow*);
-
-  // distributeExtraLogicalHeightToRows methods return the *consumed* extra
-  // logical height.
-  // FIXME: We may want to introduce a structure holding the in-flux layout
-  // information.
-  int DistributeExtraLogicalHeightToRows(int extra_logical_height);
-
-  LayoutBox* CreateAnonymousBoxWithSameTypeAs(
-      const LayoutObject* parent) const override;
-
-  void Paint(const PaintInfo&) const override;
-
-  // Flip the rect so it aligns with the coordinates used by the rowPos and
-  // columnPos vectors.
-  LayoutRect LogicalRectForWritingModeAndDirection(const PhysicalRect&) const;
-
-  // Sets |rows| and |columns| to cover all cells needing repaint in
-  // |damage_rect|.
-  void DirtiedRowsAndEffectiveColumns(const LayoutRect& damage_rect,
-                                      CellSpan& rows,
-                                      CellSpan& columns) const;
-
-  const HeapHashSet<Member<const LayoutTableCell>>& VisuallyOverflowingCells()
-      const {
-    NOT_DESTROYED();
-    return visually_overflowing_cells_;
-  }
-  bool HasVisuallyOverflowingCell() const {
-    NOT_DESTROYED();
-    return visually_overflowing_cells_.size() || force_full_paint_;
-  }
-  bool HasMultipleCellLevels() const {
-    NOT_DESTROYED();
-    return has_multiple_cell_levels_;
-  }
-
-  const char* GetName() const override {
-    NOT_DESTROYED();
-    return "LayoutTableSection";
-  }
-
-  // Whether a section has opaque background depends on many factors, e.g.
-  // border spacing, border collapsing, missing cells, etc. For simplicity,
-  // just conservatively assume all table sections are not opaque.
-  bool ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect&,
-                                         unsigned) const override {
-    NOT_DESTROYED();
-    return false;
-  }
-  bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const override {
-    NOT_DESTROYED();
-    return false;
-  }
-
-  int PaginationStrutForRow(LayoutTableRow*, LayoutUnit logical_offset) const;
-
-  bool MapToVisualRectInAncestorSpaceInternal(
-      const LayoutBoxModelObject* ancestor,
-      TransformState&,
-      VisualRectFlags = kDefaultVisualRectFlags) const override;
-
-  bool IsRepeatingHeaderGroup() const final {
-    NOT_DESTROYED();
-    return is_repeating_header_group_;
-  }
-  bool IsRepeatingFooterGroup() const final {
-    NOT_DESTROYED();
-    return is_repeating_footer_group_;
-  }
-
-  void UpdateLayout() override;
-
-  CellSpan FullSectionRowSpan() const {
-    NOT_DESTROYED();
-    return CellSpan(0, grid_.size());
-  }
-  CellSpan FullTableEffectiveColumnSpan() const {
-    NOT_DESTROYED();
-    return CellSpan(0, Table()->NumEffectiveColumns());
-  }
-
-  void DetermineIfHeaderGroupShouldRepeat() {
-    NOT_DESTROYED();
-    is_repeating_header_group_ = HeaderGroupShouldRepeat();
-  }
-
-  // Check whether row or row group has visibility:collapse.
-  bool RowHasVisibilityCollapse(unsigned row) const;
-
-  void DetermineIfFooterGroupShouldRepeat() {
-    NOT_DESTROYED();
-    is_repeating_footer_group_ = FooterGroupShouldRepeat();
-  }
-
-  // Update widths of cells affected by collapsed columns and sets whether cells
-  // are spanning any collapsed columns.
-  void UpdateLogicalWidthForCollapsedCells(
-      const Vector<int>& col_collapsed_width);
-
-  void ComputeLayoutOverflowFromDescendants();
-
-  // LayoutNGTableSectionInterface methods start.
-
-  const LayoutNGTableSectionInterface* ToLayoutNGTableSectionInterface()
-      const final {
-    NOT_DESTROYED();
-    return this;
-  }
-  const LayoutObject* ToLayoutObject() const final {
-    NOT_DESTROYED();
-    return this;
-  }
-
-  LayoutNGTableInterface* TableInterface() const final {
-    NOT_DESTROYED();
-    return Table();
-  }
-  LayoutNGTableRowInterface* FirstRowInterface() const final;
-  LayoutNGTableRowInterface* LastRowInterface() const final;
-
-  // LayoutNGTableSectionInterface methods end.
-
-  // This is made public just to set VectorTraits.
-  struct TableGridRow {
-    DISALLOW_NEW();
-
-   public:
-    void Trace(Visitor*) const;
-
-    inline void SetRowLogicalHeightToRowStyleLogicalHeight();
-    inline void UpdateLogicalHeightForCell(const LayoutTableCell*);
-
-    // The index is effective column index.
-    HeapVector<TableGridCell> grid_cells;
-    Member<LayoutTableRow> row;
-    LayoutUnit baseline = LayoutUnit(-1);
-    Length logical_height;
-  };
-
- protected:
-  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
-  bool NodeAtPoint(HitTestResult&,
-                   const HitTestLocation&,
-                   const PhysicalOffset& accumulated_offset,
-                   HitTestPhase) override;
-
- private:
-  MinMaxSizes ComputeIntrinsicLogicalWidths() const final {
-    NOT_DESTROYED();
-    NOTREACHED();
-    return MinMaxSizes();
-  }
-
-  void ComputeVisualOverflowFromDescendants();
-
-  bool IsOfType(LayoutObjectType type) const override {
-    NOT_DESTROYED();
-    return type == kLayoutObjectTableSection || LayoutBox::IsOfType(type);
-  }
-
-  void WillBeRemovedFromTree() override;
-
-  int BorderSpacingForRow(unsigned row) const {
-    NOT_DESTROYED();
-    return grid_[row].row ? Table()->VBorderSpacing() : 0;
-  }
-
-  void EnsureRows(unsigned num_rows) {
-    NOT_DESTROYED();
-    if (num_rows > grid_.size())
-      grid_.Grow(num_rows);
-  }
-
-  void EnsureCols(unsigned row_index, unsigned num_cols);
-
-  bool RowHasOnlySpanningCells(unsigned);
-  unsigned CalcRowHeightHavingOnlySpanningCells(unsigned,
-                                                int&,
-                                                unsigned,
-                                                unsigned&,
-                                                Vector<int>&);
-  void UpdateRowsHeightHavingOnlySpanningCells(LayoutTableCell*,
-                                               struct SpanningRowsHeight&,
-                                               unsigned&,
-                                               Vector<int>&);
-
-  void PopulateSpanningRowsHeightFromCell(LayoutTableCell*,
-                                          struct SpanningRowsHeight&);
-  void DistributeExtraRowSpanHeightToPercentRows(LayoutTableCell*,
-                                                 float,
-                                                 int&,
-                                                 Vector<int>&);
-  void DistributeWholeExtraRowSpanHeightToPercentRows(LayoutTableCell*,
-                                                      float,
-                                                      int&,
-                                                      Vector<int>&);
-  void DistributeExtraRowSpanHeightToAutoRows(LayoutTableCell*,
-                                              int,
-                                              int&,
-                                              Vector<int>&);
-  void DistributeExtraRowSpanHeightToRemainingRows(LayoutTableCell*,
-                                                   int,
-                                                   int&,
-                                                   Vector<int>&);
-  void DistributeRowSpanHeightToRows(SpanningLayoutTableCells& row_span_cells);
-
-  void DistributeExtraLogicalHeightToPercentRows(int& extra_logical_height,
-                                                 int total_percent);
-  void DistributeExtraLogicalHeightToAutoRows(int& extra_logical_height,
-                                              unsigned auto_rows_count);
-  void DistributeRemainingExtraLogicalHeight(int& extra_logical_height);
-
-  void UpdateBaselineForCell(LayoutTableCell*,
-                             unsigned row,
-                             LayoutUnit& baseline_descent);
-
-  // These two functions take a rectangle as input that has been flipped by
-  // logicalRectForWritingModeAndDirection.
-  // The returned span of rows or columns is end-exclusive, and empty if
-  // start==end.
-  CellSpan SpannedRows(const LayoutRect& flipped_rect) const;
-  CellSpan SpannedEffectiveColumns(const LayoutRect& flipped_rect) const;
-
-  void SetLogicalPositionForCell(LayoutTableCell*,
-                                 unsigned effective_column) const;
-
-  void RelayoutCellIfFlexed(LayoutTableCell&, int row_index, int row_height);
-
-  int LogicalHeightForRow(const LayoutTableRow&) const;
-
-  // Honor breaking restrictions inside the table row, and adjust position and
-  // size accordingly.
-  void AdjustRowForPagination(LayoutTableRow&, SubtreeLayoutScope&);
-
-  // The offset at which the first row in the section will get positioned to
-  // avoid any repeating headers in its table or ancestor tables.
-  int OffsetForRepeatedHeader() const;
-
-  bool HeaderGroupShouldRepeat() const {
-    NOT_DESTROYED();
-    return Table()->Header() == this && GroupShouldRepeat();
-  }
-
-  bool FooterGroupShouldRepeat() const {
-    NOT_DESTROYED();
-    return Table()->Footer() == this && GroupShouldRepeat();
-  }
-
-  bool GroupShouldRepeat() const;
-
-  // The representation of the rows and their grid cells.
-  HeapVector<TableGridRow> grid_;
-
-  // The logical offset of each row from the top of the section.
-  //
-  // Note that this Vector has one more entry than the number of rows so that
-  // we can keep track of the final size of the section. That is,
-  // m_rowPos[m_grid.size()] is a valid entry.
-  //
-  // To know a row's height at |rowIndex|, use the formula:
-  // m_rowPos[rowIndex + 1] - m_rowPos[rowIndex]
-  Vector<int> row_pos_;
-
-  // The amount of height collapsed in each row.
-  //
-  // This is used to adjust the padding of row-spanning cells. The padding
-  // should stay the same as if the row were not collapsed.
-  Vector<int> row_collapsed_height_;
-
-  // Whether any row in the table section is or has been collapsed.
-  bool is_any_row_collapsed_;
-
-  // The current insertion position in the grid.
-  // The position is used when inserting a new cell into the section to
-  // know where it should be inserted and expand our internal structure.
-  //
-  // The reason for them is that we process cells as we discover them
-  // during parsing or during recalcCells (ie in DOM order). This means
-  // that we can discover changes in the structure later (e.g. due to
-  // colspans, extra cells, ...).
-  //
-  // Do not use outside of recalcCells and addChild.
-  unsigned c_col_;
-  unsigned c_row_;
-
-  bool needs_cell_recalc_;
-
-  // This HashSet holds the overflowing cells for the partial paint path. If we
-  // have too many overflowing cells, it will be empty and force_full_paint_
-  // will be set to save memory. See ComputeVisualOverflowFromDescendants().
-  HeapHashSet<Member<const LayoutTableCell>> visually_overflowing_cells_;
-  bool force_full_paint_;
-
-  // This boolean tracks if we have cells overlapping due to rowspan / colspan
-  // (see class comment above about when it could appear).
-  //
-  // The use is to disable a painting optimization where we just paint the
-  // invalidated cells.
-  bool has_multiple_cell_levels_;
-
-  // Whether any cell spans multiple rows or cols.
-  bool has_spanning_cells_;
-
-  // Header group should be painted on every page.
-  bool is_repeating_header_group_;
-
-  // Footer group should be painted on every page.
-  bool is_repeating_footer_group_;
-};
-
-// To<LayoutTableSection>() helper.
-template <>
-struct DowncastTraits<LayoutTableSection> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsTableSection() && !object.IsLayoutNGObject();
-  }
-};
-
-}  // namespace blink
-
-namespace WTF {
-
-template <>
-struct VectorTraits<blink::LayoutTableSection::TableGridRow>
-    : VectorTraitsBase<blink::LayoutTableSection::TableGridRow> {
-  STATIC_ONLY(VectorTraits);
-  static constexpr bool kCanClearUnusedSlotsWithMemset = true;
-};
-
-}  // namespace WTF
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_TABLE_SECTION_H_
diff --git a/third_party/blink/renderer/core/layout/layout_table_section_test.cc b/third_party/blink/renderer/core/layout/layout_table_section_test.cc
index 15f1aa92..34a7f52 100644
--- a/third_party/blink/renderer/core/layout/layout_table_section_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_table_section_test.cc
@@ -2,9 +2,6 @@
 // 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/core/layout/layout_table_section.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 
 namespace blink {
@@ -16,23 +13,6 @@
   LayoutBox* GetSectionByElementIdAsBox(const char* id) {
     return To<LayoutBox>(GetLayoutObjectByElementId(id));
   }
-
-  LayoutTableSection* CreateSection(unsigned rows, unsigned columns) {
-    auto* table = GetDocument().CreateRawElement(html_names::kTableTag);
-    GetDocument().body()->appendChild(table);
-    auto* section = GetDocument().CreateRawElement(html_names::kTbodyTag);
-    table->appendChild(section);
-    for (unsigned i = 0; i < rows; ++i) {
-      auto* row = GetDocument().CreateRawElement(html_names::kTrTag);
-      section->appendChild(row);
-      for (unsigned column = 0; column < columns; ++column)
-        row->appendChild(GetDocument().CreateRawElement(html_names::kTdTag));
-    }
-    UpdateAllLifecyclePhasesForTest();
-    // TODO(958381) Needs to TableNG compatible with
-    // LayoutNGTableSectionInterface.
-    return To<LayoutTableSection>(section->GetLayoutObject());
-  }
 };
 
 TEST_F(LayoutTableSectionTest,
diff --git a/third_party/blink/renderer/core/layout/layout_table_test.cc b/third_party/blink/renderer/core/layout/layout_table_test.cc
index 9edcceb..00270cb 100644
--- a/third_party/blink/renderer/core/layout/layout_table_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_table_test.cc
@@ -2,9 +2,9 @@
 // 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/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
 
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index 4eab464..33d3c349 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -51,7 +51,6 @@
 #include "third_party/blink/renderer/core/layout/layout_block.h"
 #include "third_party/blink/renderer/core/layout/layout_object_factory.h"
 #include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/layout/layout_text_combine.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h"
diff --git a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
index 563ba06..99a6d73 100644
--- a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
@@ -43,7 +43,6 @@
 #include "third_party/blink/renderer/core/layout/layout_inline.h"
 #include "third_party/blink/renderer/core/layout/layout_list_item.h"
 #include "third_party/blink/renderer/core/layout/layout_list_marker.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
 #include "third_party/blink/renderer/core/layout/list_marker.h"
@@ -51,6 +50,7 @@
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_inline.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
@@ -413,10 +413,6 @@
   int y = run.Y().ToInt();
   int logical_width = (run.X() + run.LogicalWidth()).Ceil() - x;
 
-  // FIXME: Table cell adjustment is temporary until results can be updated.
-  if (o.ContainingBlock()->IsTableCellLegacy())
-    y -= To<LayoutTableCell>(o.ContainingBlock())->IntrinsicPaddingBefore();
-
   ts << "text run at (" << x << "," << y << ") width " << logical_width;
   if (!run.IsLeftToRightDirection() || run.DirOverride()) {
     ts << (!run.IsLeftToRightDirection() ? " RTL" : " LTR");
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc
index 2894c3d..3acf3c5 100644
--- a/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -712,8 +712,7 @@
   Document& document = GetDocument();
   if (Node* body = document.body()) {
     // Framesets can't scroll.
-    if (body->GetLayoutObject() &&
-        body->GetLayoutObject()->IsFrameSetIncludingNG()) {
+    if (body->GetLayoutObject() && body->GetLayoutObject()->IsFrameSet()) {
       TRACE_EVENT_INSTANT1(
           TRACE_DISABLED_BY_DEFAULT("blink.debug.layout.scrollbars"),
           "CalculateScrollbarModes", TRACE_EVENT_SCOPE_THREAD, "disable_reason",
diff --git a/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h b/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
index ad721e9..844a6b3 100644
--- a/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
+++ b/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
@@ -28,7 +28,6 @@
 #include "base/check_op.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_box.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_list_marker.h"
-#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_run.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_text.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_text_combine.h"
 #include "third_party/blink/renderer/core/layout/line/inline_iterator.h"
@@ -662,12 +661,8 @@
   if (at_start_)
     width_.UpdateAvailableWidth(replaced_box.LogicalHeight());
 
-  // Break on replaced elements if either has normal white-space,
-  // or if the replaced element is ruby that can break before.
-  if ((auto_wrap_ || ComputedStyle::DeprecatedAutoWrap(last_ws_)) &&
-      (!current_.GetLineLayoutItem().IsRubyRun() ||
-       LineLayoutRubyRun(current_.GetLineLayoutItem())
-           .CanBreakBefore(layout_text_info_.line_break_iterator_))) {
+  // Break on replaced elements if either has normal white-space.
+  if (auto_wrap_ || ComputedStyle::DeprecatedAutoWrap(last_ws_)) {
     width_.Commit();
     line_break_.MoveToStartOf(current_.GetLineLayoutItem());
   }
@@ -704,9 +699,6 @@
   } else {
     width_.AddUncommittedWidth(replaced_logical_width.ToFloat());
   }
-  if (current_.GetLineLayoutItem().IsRubyRun())
-    width_.ApplyOverhang(LineLayoutRubyRun(current_.GetLineLayoutItem()),
-                         last_object_, next_object_);
   // Update prior line break context characters, using U+FFFD (OBJECT
   // REPLACEMENT CHARACTER) for replaced element.
   layout_text_info_.line_break_iterator_.UpdatePriorContext(
diff --git a/third_party/blink/renderer/core/layout/line/inline_flow_box.cc b/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
index b92c0739..2b9fb98 100644
--- a/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
+++ b/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
@@ -25,12 +25,10 @@
 #include "third_party/blink/renderer/core/css/css_property_names.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h"
+#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_box.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_inline.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_list_marker.h"
-#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_base.h"
-#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_text.h"
 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
 #include "third_party/blink/renderer/core/layout/line/glyph_overflow.h"
 #include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
@@ -851,25 +849,6 @@
           has_annotations_before = true;
         else
           has_annotations_after = true;
-
-        LineLayoutRubyRun ruby_run =
-            LineLayoutRubyRun(curr->GetLineLayoutItem());
-        if (LineLayoutRubyBase ruby_base = ruby_run.RubyBase()) {
-          LayoutUnit bottom_ruby_base_leading =
-              (curr->LogicalHeight() - ruby_base.LogicalBottom()) +
-              ruby_base.LogicalHeight() -
-              (ruby_base.LastRootBox() ? ruby_base.LastRootBox()->LineBottom()
-                                       : LayoutUnit());
-          LayoutUnit top_ruby_base_leading =
-              ruby_base.LogicalTop() +
-              (ruby_base.FirstRootBox() ? ruby_base.FirstRootBox()->LineTop()
-                                        : LayoutUnit());
-          new_logical_top +=
-              !GetLineLayoutItem().StyleRef().IsFlippedLinesWritingMode()
-                  ? top_ruby_base_leading
-                  : bottom_ruby_base_leading;
-          box_height -= (top_ruby_base_leading + bottom_ruby_base_leading);
-        }
       }
       if (curr->IsInlineTextBox()) {
         TextEmphasisPosition emphasis_mark_position;
@@ -1597,32 +1576,7 @@
         curr->GetLineLayoutItem().IsRubyRun() &&
         curr->GetLineLayoutItem().StyleRef().GetRubyPosition() ==
             RubyPosition::kBefore) {
-      LineLayoutRubyRun ruby_run = LineLayoutRubyRun(curr->GetLineLayoutItem());
-      LineLayoutRubyText ruby_text = ruby_run.RubyText();
-      if (!ruby_text)
-        continue;
-
-      if (!ruby_run.StyleRef().IsFlippedLinesWritingMode()) {
-        LayoutUnit top_of_first_ruby_text_line =
-            ruby_text.LogicalTop() + (ruby_text.FirstRootBox()
-                                          ? ruby_text.FirstRootBox()->LineTop()
-                                          : LayoutUnit());
-        if (top_of_first_ruby_text_line >= 0)
-          continue;
-        top_of_first_ruby_text_line += curr->LogicalTop();
-        result =
-            std::max(result, allowed_position - top_of_first_ruby_text_line);
-      } else {
-        LayoutUnit bottom_of_last_ruby_text_line =
-            ruby_text.LogicalTop() +
-            (ruby_text.LastRootBox() ? ruby_text.LastRootBox()->LineBottom()
-                                     : ruby_text.LogicalHeight());
-        if (bottom_of_last_ruby_text_line <= curr->LogicalHeight())
-          continue;
-        bottom_of_last_ruby_text_line += curr->LogicalTop();
-        result =
-            std::max(result, bottom_of_last_ruby_text_line - allowed_position);
-      }
+      continue;
     }
 
     if (curr->IsInlineTextBox()) {
@@ -1669,32 +1623,7 @@
         curr->GetLineLayoutItem().IsRubyRun() &&
         curr->GetLineLayoutItem().StyleRef().GetRubyPosition() ==
             RubyPosition::kAfter) {
-      LineLayoutRubyRun ruby_run = LineLayoutRubyRun(curr->GetLineLayoutItem());
-      LineLayoutRubyText ruby_text = ruby_run.RubyText();
-      if (!ruby_text)
-        continue;
-
-      if (ruby_run.StyleRef().IsFlippedLinesWritingMode()) {
-        LayoutUnit top_of_first_ruby_text_line =
-            ruby_text.LogicalTop() + (ruby_text.FirstRootBox()
-                                          ? ruby_text.FirstRootBox()->LineTop()
-                                          : LayoutUnit());
-        if (top_of_first_ruby_text_line >= 0)
-          continue;
-        top_of_first_ruby_text_line += curr->LogicalTop();
-        result =
-            std::max(result, allowed_position - top_of_first_ruby_text_line);
-      } else {
-        LayoutUnit bottom_of_last_ruby_text_line =
-            ruby_text.LogicalTop() +
-            (ruby_text.LastRootBox() ? ruby_text.LastRootBox()->LineBottom()
-                                     : ruby_text.LogicalHeight());
-        if (bottom_of_last_ruby_text_line <= curr->LogicalHeight())
-          continue;
-        bottom_of_last_ruby_text_line += curr->LogicalTop();
-        result =
-            std::max(result, bottom_of_last_ruby_text_line - allowed_position);
-      }
+      continue;
     }
 
     if (curr->IsInlineTextBox()) {
diff --git a/third_party/blink/renderer/core/layout/line/inline_text_box.cc b/third_party/blink/renderer/core/layout/line/inline_text_box.cc
index a6da205..562c499 100644
--- a/third_party/blink/renderer/core/layout/line/inline_text_box.cc
+++ b/third_party/blink/renderer/core/layout/line/inline_text_box.cc
@@ -28,10 +28,9 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_box.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_br.h"
-#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_text.h"
 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
 #include "third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h"
 #include "third_party/blink/renderer/core/layout/line/ellipsis_box.h"
@@ -493,12 +492,7 @@
   if (!containing_block.Parent().IsRubyRun())
     return true;
 
-  LineLayoutRubyText ruby_text =
-      LineLayoutRubyRun(containing_block.Parent()).RubyText();
-
-  // The emphasis marks over are suppressed only if there is a ruby text box and
-  // it not empty.
-  return !ruby_text || !ruby_text.FirstLineBox();
+  return true;
 }
 
 void InlineTextBox::Paint(const PaintInfo& paint_info,
diff --git a/third_party/blink/renderer/core/layout/line/line_width.cc b/third_party/blink/renderer/core/layout/line/line_width.cc
index 0be9101..e65b7075 100644
--- a/third_party/blink/renderer/core/layout/line/line_width.cc
+++ b/third_party/blink/renderer/core/layout/line/line_width.cc
@@ -29,7 +29,6 @@
 
 #include "third_party/blink/renderer/core/layout/line/line_width.h"
 
-#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_run.h"
 #include "third_party/blink/renderer/core/layout/shapes/shape_outside_info.h"
 
 namespace blink {
@@ -116,23 +115,6 @@
   uncommitted_width_ = 0;
 }
 
-void LineWidth::ApplyOverhang(LineLayoutRubyRun ruby_run,
-                              LineLayoutItem start_layout_item,
-                              LineLayoutItem end_layout_item) {
-  int start_overhang;
-  int end_overhang;
-  ruby_run.GetOverhang(is_first_line_, start_layout_item, end_layout_item,
-                       start_overhang, end_overhang);
-
-  start_overhang = std::min<int>(start_overhang, committed_width_);
-  available_width_ += start_overhang;
-
-  end_overhang = std::max(
-      std::min<int>(end_overhang, available_width_ - CurrentWidth()), 0);
-  available_width_ += end_overhang;
-  overhang_width_ += start_overhang + end_overhang;
-}
-
 inline static LayoutUnit AvailableWidthAtOffset(
     LineLayoutBlockFlow block,
     const LayoutUnit& offset,
diff --git a/third_party/blink/renderer/core/layout/line/line_width.h b/third_party/blink/renderer/core/layout/line/line_width.h
index 83081ea..b4c66ae 100644
--- a/third_party/blink/renderer/core/layout/line/line_width.h
+++ b/third_party/blink/renderer/core/layout/line/line_width.h
@@ -37,7 +37,6 @@
 namespace blink {
 
 class FloatingObject;
-class LineLayoutRubyRun;
 
 enum WhitespaceTreatment { kExcludeWhitespace, kIncludeWhitespace };
 
@@ -80,9 +79,6 @@
   void ShrinkAvailableWidthForNewFloatIfNeeded(const FloatingObject&);
   void AddUncommittedWidth(float delta) { uncommitted_width_ += delta; }
   void Commit();
-  void ApplyOverhang(LineLayoutRubyRun,
-                     LineLayoutItem start_layout_item,
-                     LineLayoutItem end_layout_item);
   void FitBelowFloats(bool is_first_line = false);
   void SetTrailingWhitespaceWidth(float width) {
     trailing_whitespace_width_ = width;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
index 63c41be..1985cc9 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -460,11 +460,10 @@
 namespace {
 
 GridArea SubgriddedAreaInParent(const NGSubgriddedItemData& opt_subgrid_data) {
-  if (!opt_subgrid_data) {
+  if (!opt_subgrid_data.IsSubgrid()) {
     return GridArea();
   }
 
-  DCHECK(opt_subgrid_data->IsSubgrid());
   auto subgridded_area_in_parent = opt_subgrid_data->resolved_position;
 
   if (!opt_subgrid_data->has_subgridded_columns) {
@@ -836,9 +835,14 @@
         *intrinsic_block_size);
   }
 
-  if (grid_available_size_.block_size == kIndefiniteSize) {
-    DCHECK(is_standalone_grid);
+  if (!is_standalone_grid) {
+    DCHECK_NE(grid_available_size_.block_size, kIndefiniteSize)
+        << "The available block size of a subgrid should be resolved by its "
+           "parent grid's sizing algorithm.";
+    return;
+  }
 
+  if (grid_available_size_.block_size == kIndefiniteSize) {
     const auto& container_style = Style();
     const auto block_size = ComputeBlockSizeForFragment(
         constraint_space, container_style, BorderPadding(),
@@ -893,8 +897,6 @@
   }
 
   if (needs_additional_pass) {
-    DCHECK(is_standalone_grid);
-
     InitializeTrackSizes(grid_sizing_tree, kForColumns);
     CompleteTrackSizingAlgorithm(grid_sizing_tree, kForColumns,
                                  SizingConstraint::kLayout);
@@ -905,18 +907,12 @@
   }
 
   // Calculate final alignment baselines for grid item layout.
-  if (layout_data.Columns().IsForSizing() &&
-      layout_data.Columns().HasBaselines()) {
-    CalculateAlignmentBaselines(layout_data, SizingConstraint::kLayout,
-                                &grid_items,
-                                &layout_data.SizingCollection(kForColumns));
-  }
-
-  if (layout_data.Rows().IsForSizing() && layout_data.Rows().HasBaselines()) {
-    CalculateAlignmentBaselines(layout_data, SizingConstraint::kLayout,
-                                &grid_items,
-                                &layout_data.SizingCollection(kForRows));
-  }
+  CalculateAlignmentBaselines(layout_data, SizingConstraint::kLayout,
+                              &grid_items,
+                              &layout_data.SizingCollection(kForColumns));
+  CalculateAlignmentBaselines(layout_data, SizingConstraint::kLayout,
+                              &grid_items,
+                              &layout_data.SizingCollection(kForRows));
 }
 
 LayoutUnit NGGridLayoutAlgorithm::ComputeIntrinsicBlockSizeIgnoringChildren()
@@ -1456,6 +1452,10 @@
     bool* needs_additional_pass) const {
   DCHECK(grid_items && track_collection);
 
+  if (!track_collection->HasBaselines()) {
+    return;
+  }
+
   const auto track_direction = track_collection->Direction();
   track_collection->ResetBaselines();
 
@@ -1527,7 +1527,8 @@
   if (layout_data->HasSubgriddedAxis(track_direction)) {
     // If we don't have a sizing collection for this axis, then we're in a
     // subgrid that must inherit the track collection of its parent grid.
-    DCHECK(opt_subgrid_data && opt_subgrid_data->IsSubgrid());
+    DCHECK(opt_subgrid_data.IsSubgrid());
+
     layout_data->SetTrackCollection(
         opt_subgrid_data.CreateSubgridCollection(track_direction));
     return;
@@ -1694,11 +1695,9 @@
                                       : grid_available_size_.block_size,
                                   GutterSize(track_direction));
 
-  // Cache baselines, as these contributions can influence track sizing.
-  if (track_collection.HasBaselines()) {
-    CalculateAlignmentBaselines(layout_data, sizing_constraint, &grid_items,
-                                &track_collection, opt_needs_additional_pass);
-  }
+  // Cache baselines, as these contributions can influence track sizing
+  CalculateAlignmentBaselines(layout_data, sizing_constraint, &grid_items,
+                              &track_collection, opt_needs_additional_pass);
 
   // 2. Resolve intrinsic track sizing functions to absolute lengths.
   if (track_collection.HasIntrinsicTrack()) {
@@ -1737,47 +1736,81 @@
   auto& [grid_items, layout_data, subtree_size] =
       sizing_subtree.SubtreeRootData();
 
-  if (layout_data.HasSubgriddedAxis(track_direction)) {
-    return;
-  }
-
   const bool is_for_columns = track_direction == kForColumns;
-  auto& track_collection = layout_data.SizingCollection(track_direction);
+  const bool has_non_definite_track =
+      is_for_columns ? !layout_data.Columns().IsSpanningOnlyDefiniteTracks()
+                     : !layout_data.Rows().IsSpanningOnlyDefiniteTracks();
 
-  if (track_collection.IsSpanningOnlyDefiniteTracks()) {
+  if (has_non_definite_track) {
+    if (layout_data.HasSubgriddedAxis(track_direction)) {
+      // If we don't have a sizing collection for this axis, then we're in a
+      // subgrid that must inherit the track collection of its parent grid.
+      DCHECK(opt_subgrid_data.IsSubgrid());
+
+      layout_data.SetTrackCollection(
+          opt_subgrid_data.CreateSubgridCollection(track_direction));
+    } else {
+      ComputeUsedTrackSizes(sizing_subtree, track_direction, sizing_constraint,
+                            opt_needs_additional_pass);
+
+      // After computing row sizes, if we're still trying to determine whether
+      // we need to perform and additional pass, check if there is a grid item
+      // whose contributions may change with the new available block size.
+      const bool needs_to_check_block_size_dependent_grid_items =
+          !is_for_columns && opt_needs_additional_pass &&
+          !(*opt_needs_additional_pass);
+
+      Vector<BlockSizeDependentGridItem> block_size_dependent_grid_items;
+      auto& track_collection = layout_data.SizingCollection(track_direction);
+
+      if (needs_to_check_block_size_dependent_grid_items) {
+        block_size_dependent_grid_items =
+            BlockSizeDependentGridItems(grid_items, track_collection);
+      }
+
+      auto first_set_geometry = ComputeFirstSetGeometry(
+          track_collection, Style(),
+          is_for_columns ? grid_available_size_.inline_size
+                         : grid_available_size_.block_size,
+          is_for_columns ? BorderScrollbarPadding().inline_start
+                         : BorderScrollbarPadding().block_start);
+
+      track_collection.FinalizeSetsGeometry(first_set_geometry.start_offset,
+                                            first_set_geometry.gutter_size);
+
+      if (needs_to_check_block_size_dependent_grid_items) {
+        *opt_needs_additional_pass =
+            MayChangeBlockSizeDependentGridItemContributions(
+                block_size_dependent_grid_items, track_collection);
+      }
+    }
+  }
+
+  if (subtree_size == 1) {
+    // If we know this subtree doesn't have nested subgrids we can exit early
+    // instead of iterating over every grid item looking for them.
     return;
   }
 
-  // After computing row sizes, if we're still trying to determine whether we
-  // need to perform and additional pass, check if there is a grid item whose
-  // contributions relied on the available block size and may be changed.
-  const bool needs_to_check_block_size_dependent_grid_items =
-      !is_for_columns && opt_needs_additional_pass &&
-      !(*opt_needs_additional_pass);
+  auto next_subgrid_subtree = sizing_subtree.FirstChild();
+  for (const auto& grid_item : grid_items) {
+    if (grid_item.is_subgridded_to_parent_grid || !grid_item.IsSubgrid()) {
+      continue;
+    }
 
-  Vector<BlockSizeDependentGridItem> block_size_dependent_grid_items;
-  if (needs_to_check_block_size_dependent_grid_items) {
-    block_size_dependent_grid_items =
-        BlockSizeDependentGridItems(grid_items, track_collection);
-  }
+    DCHECK(next_subgrid_subtree);
+    NGSubgriddedItemData subgrid_data(grid_item, layout_data);
 
-  ComputeUsedTrackSizes(sizing_subtree, track_direction, sizing_constraint,
-                        opt_needs_additional_pass);
+    NGConstraintSpace unused_space;
+    NGFragmentGeometry unused_fragment_geometry;
+    auto subgrid_algorithm = CreateSubgridLayoutAlgorithm(
+        subgrid_data, &unused_space, &unused_fragment_geometry);
 
-  auto first_set_geometry = ComputeFirstSetGeometry(
-      track_collection, Style(),
-      is_for_columns ? grid_available_size_.inline_size
-                     : grid_available_size_.block_size,
-      is_for_columns ? BorderScrollbarPadding().inline_start
-                     : BorderScrollbarPadding().block_start);
+    subgrid_algorithm.CompleteTrackSizingAlgorithm(
+        next_subgrid_subtree, subgrid_data, track_direction, sizing_constraint,
+        opt_needs_additional_pass);
 
-  track_collection.FinalizeSetsGeometry(first_set_geometry.start_offset,
-                                        first_set_geometry.gutter_size);
-
-  if (needs_to_check_block_size_dependent_grid_items) {
-    *opt_needs_additional_pass =
-        MayChangeBlockSizeDependentGridItemContributions(
-            block_size_dependent_grid_items, track_collection);
+    next_subgrid_subtree = next_subgrid_subtree.NextSibling();
   }
 }
 
@@ -2983,8 +3016,8 @@
     const NGSubgriddedItemData& subgrid_data,
     NGConstraintSpace* constraint_space,
     NGFragmentGeometry* fragment_geometry) const {
-  DCHECK(subgrid_data && subgrid_data->IsSubgrid());
   DCHECK(constraint_space && fragment_geometry);
+  DCHECK(subgrid_data.IsSubgrid());
 
   LogicalRect unused_containing_grid_area;
   *constraint_space = CreateConstraintSpaceForLayout(
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.h
index c4f5280..98089bd 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_sizing_tree.h
@@ -29,7 +29,6 @@
       : item_data_in_parent_(&item_data_in_parent),
         parent_layout_data_(&parent_layout_data) {}
 
-  explicit operator bool() const { return item_data_in_parent_ != nullptr; }
   const GridItemData* operator->() const { return item_data_in_parent_; }
 
   const GridItemData& operator*() const {
@@ -37,14 +36,18 @@
     return *item_data_in_parent_;
   }
 
-  std::unique_ptr<NGGridLayoutTrackCollection> CreateSubgridCollection(
-      GridTrackSizingDirection track_direction) const;
+  bool IsSubgrid() const {
+    return item_data_in_parent_ && item_data_in_parent_->IsSubgrid();
+  }
 
   const NGGridLayoutData& ParentLayoutData() const {
     DCHECK(parent_layout_data_);
     return *parent_layout_data_;
   }
 
+  std::unique_ptr<NGGridLayoutTrackCollection> CreateSubgridCollection(
+      GridTrackSizingDirection track_direction) const;
+
  private:
   const GridItemData* item_data_in_parent_{nullptr};
   const NGGridLayoutData* parent_layout_data_{nullptr};
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
index d5361116..f27103f 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
@@ -19,10 +19,6 @@
 #include "third_party/blink/renderer/core/layout/ng/layout_box_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_progress.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
@@ -288,12 +284,7 @@
 
 template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutBlockFlow>;
 template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutProgress>;
-template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutRubyAsBlock>;
-template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutRubyBase>;
-template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutRubyRun>;
-template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutRubyText>;
 template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutSVGBlock>;
-template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutTableCaption>;
 template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutView>;
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.cc
index 27a1a51..ce8631a 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.cc
@@ -27,7 +27,7 @@
 bool LayoutNGFrameSet::IsChildAllowed(LayoutObject* child,
                                       const ComputedStyle&) const {
   NOT_DESTROYED();
-  return child->IsFrame() || child->IsLayoutNGFrameSet();
+  return child->IsFrame() || child->IsFrameSet();
 }
 
 void LayoutNGFrameSet::AddChild(LayoutObject* new_child,
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.h b/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.h
index 5655c0e15..b397ac28 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.h
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set.h
@@ -27,7 +27,7 @@
 template <>
 struct DowncastTraits<LayoutNGFrameSet> {
   static bool AllowFrom(const LayoutObject& object) {
-    return object.IsLayoutNGFrameSet();
+    return object.IsFrameSet();
   }
 };
 
diff --git a/third_party/blink/renderer/core/layout/layout_frame_set_test.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set_test.cc
similarity index 89%
rename from third_party/blink/renderer/core/layout/layout_frame_set_test.cc
rename to third_party/blink/renderer/core/layout/ng/layout_ng_frame_set_test.cc
index f5d58e3..fc7730a4 100644
--- a/third_party/blink/renderer/core/layout/layout_frame_set_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_frame_set_test.cc
@@ -6,9 +6,9 @@
 
 namespace blink {
 
-class LayoutFrameSetTest : public RenderingTest {};
+class LayoutNGFrameSetTest : public RenderingTest {};
 
-TEST_F(LayoutFrameSetTest, GetCursor) {
+TEST_F(LayoutNGFrameSetTest, GetCursor) {
   SetHtmlInnerHTML(R"HTML(
     <frameset id='f' rows='50%,50%' cols='50%,50%' border='20'>
     <frame src=""></frame>
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
index 5dfe062b..cb5b9eb 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -13,10 +13,6 @@
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_block.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_progress.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
@@ -388,12 +384,7 @@
 template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutBlock>;
 template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutBlockFlow>;
 template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutProgress>;
-template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyAsBlock>;
-template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyBase>;
-template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyRun>;
-template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyText>;
 template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutSVGBlock>;
-template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutTableCaption>;
 template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutView>;
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.cc
index d453f2a..6dc72ce4 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.cc
@@ -4,15 +4,94 @@
 
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h"
 
+#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/layout/layout_ruby.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
+
 namespace blink {
 
 LayoutNGRubyAsBlock::LayoutNGRubyAsBlock(Element* element)
-    : LayoutNGBlockFlowMixin<LayoutRubyAsBlock>(element) {}
+    : LayoutNGBlockFlow(element) {
+  UseCounter::Count(GetDocument(), WebFeature::kRenderRuby);
+}
 
 LayoutNGRubyAsBlock::~LayoutNGRubyAsBlock() = default;
 
-void LayoutNGRubyAsBlock::UpdateBlockLayout(bool relayout_children) {
-  UpdateNGBlockLayout();
+bool LayoutNGRubyAsBlock::IsOfType(LayoutObjectType type) const {
+  NOT_DESTROYED();
+  return type == kLayoutObjectRuby || LayoutNGBlockFlow::IsOfType(type);
+}
+
+void LayoutNGRubyAsBlock::AddChild(LayoutObject* child,
+                                   LayoutObject* before_child) {
+  NOT_DESTROYED();
+  // If the child is a ruby run, just add it normally.
+  if (child->IsRubyRun()) {
+    LayoutNGBlockFlow::AddChild(child, before_child);
+    return;
+  }
+
+  if (before_child) {
+    // insert child into run
+    LayoutObject* run = before_child;
+    while (run && !run->IsRubyRun()) {
+      run = run->Parent();
+    }
+    if (run) {
+      if (before_child == run) {
+        before_child = To<LayoutNGRubyRun>(before_child)->FirstChild();
+      }
+      DCHECK(!before_child || before_child->IsDescendantOf(run));
+      run->AddChild(child, before_child);
+      return;
+    }
+    NOTREACHED();  // before_child should always have a run as parent!
+                   // Emergency fallback: fall through and just append.
+  }
+
+  // If the new child would be appended, try to add the child to the previous
+  // run if possible, or create a new run otherwise.
+  // (The LayoutNGRubyRun object will handle the details)
+  auto* last_run = LayoutRubyAsInline::LastRubyRun(*this);
+  if (!last_run || last_run->HasRubyText()) {
+    last_run = &LayoutNGRubyRun::Create(this, *this);
+    LayoutNGBlockFlow::AddChild(last_run, before_child);
+    last_run->EnsureRubyBase();
+  }
+  last_run->AddChild(child);
+}
+
+void LayoutNGRubyAsBlock::RemoveChild(LayoutObject* child) {
+  NOT_DESTROYED();
+  // If the child's parent is *this (must be a ruby run), just use the normal
+  // remove method.
+  if (child->Parent() == this) {
+    DCHECK(child->IsRubyRun());
+    LayoutNGBlockFlow::RemoveChild(child);
+    return;
+  }
+
+  // Otherwise find the containing run and remove it from there.
+  auto* run = LayoutRubyAsInline::FindRubyRunParent(child);
+  DCHECK(run);
+  run->RemoveChild(child);
+}
+
+void LayoutNGRubyAsBlock::StyleDidChange(StyleDifference diff,
+                                         const ComputedStyle* old_style) {
+  NOT_DESTROYED();
+  LayoutNGBlockFlow::StyleDidChange(diff, old_style);
+  PropagateStyleToAnonymousChildren();
+}
+
+bool LayoutNGRubyAsBlock::CreatesAnonymousWrapper() const {
+  NOT_DESTROYED();
+  return true;
+}
+
+void LayoutNGRubyAsBlock::RemoveLeftoverAnonymousBlock(LayoutBlock*) {
+  NOT_DESTROYED();
+  NOTREACHED();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h
index b0e2083e..0f5ba4a9 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h
@@ -6,20 +6,13 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_AS_BLOCK_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 
 namespace blink {
 
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
-    LayoutNGBlockFlowMixin<LayoutRubyAsBlock>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
-    LayoutNGMixin<LayoutRubyAsBlock>;
-
-// A NG version of LayoutRubyAsBlock.
-// This adds anonymous block building to LayoutNGBlockFlow.
-class CORE_EXPORT LayoutNGRubyAsBlock
-    : public LayoutNGBlockFlowMixin<LayoutRubyAsBlock> {
+// Represents <ruby> with "display: block" or "display: inline-block".
+// If we supports "display: block ruby", we can remove this class.
+class CORE_EXPORT LayoutNGRubyAsBlock : public LayoutNGBlockFlow {
  public:
   explicit LayoutNGRubyAsBlock(Element*);
   ~LayoutNGRubyAsBlock() override;
@@ -28,7 +21,13 @@
     NOT_DESTROYED();
     return "LayoutNGRubyAsBlock";
   }
-  void UpdateBlockLayout(bool relayout_children) override;
+  bool IsOfType(LayoutObjectType type) const override;
+  void AddChild(LayoutObject* child,
+                LayoutObject* before_child = nullptr) override;
+  void RemoveChild(LayoutObject* child) override;
+  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
+  bool CreatesAnonymousWrapper() const override;
+  void RemoveLeftoverAnonymousBlock(LayoutBlock*) override;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.cc
index 45098ec..23f9a333 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.cc
@@ -6,13 +6,119 @@
 
 namespace blink {
 
-LayoutNGRubyBase::LayoutNGRubyBase()
-    : LayoutNGBlockFlowMixin<LayoutRubyBase>(nullptr) {}
+LayoutNGRubyBase::LayoutNGRubyBase() : LayoutNGBlockFlow(nullptr) {
+  SetInline(false);
+}
 
 LayoutNGRubyBase::~LayoutNGRubyBase() = default;
 
-void LayoutNGRubyBase::UpdateBlockLayout(bool relayout_children) {
-  UpdateNGBlockLayout();
+bool LayoutNGRubyBase::IsOfType(LayoutObjectType type) const {
+  NOT_DESTROYED();
+  return type == kLayoutObjectRubyBase || LayoutBlockFlow::IsOfType(type);
+}
+
+bool LayoutNGRubyBase::IsChildAllowed(LayoutObject*,
+                                      const ComputedStyle&) const {
+  NOT_DESTROYED();
+  NOTREACHED();  // Because LayoutRubyRun manages child types.
+  return true;
+}
+
+void LayoutNGRubyBase::MoveChildren(LayoutNGRubyBase& to_base,
+                                    LayoutObject* before_child) {
+  NOT_DESTROYED();
+  // Callers should have handled the percent height descendant map.
+  DCHECK(!HasPercentHeightDescendants());
+
+  if (before_child && before_child->Parent() != this) {
+    before_child = SplitAnonymousBoxesAroundChild(before_child);
+  }
+
+  if (ChildrenInline()) {
+    MoveInlineChildrenTo(to_base, before_child);
+  } else {
+    MoveBlockChildrenTo(to_base, before_child);
+  }
+
+  SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+      layout_invalidation_reason::kUnknown);
+  to_base.SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+      layout_invalidation_reason::kUnknown);
+}
+
+void LayoutNGRubyBase::MoveInlineChildrenTo(LayoutNGRubyBase& to_base,
+                                            LayoutObject* before_child) {
+  NOT_DESTROYED();
+  DCHECK(ChildrenInline());
+
+  if (!FirstChild()) {
+    return;
+  }
+
+  LayoutBlock* to_block;
+  if (to_base.ChildrenInline()) {
+    // The standard and easy case: move the children into the target base
+    to_block = &to_base;
+  } else {
+    // We need to wrap the inline objects into an anonymous block.
+    // If toBase has a suitable block, we re-use it, otherwise create a new one.
+    LayoutObject* last_child = to_base.LastChild();
+    if (last_child && last_child->IsAnonymousBlock() &&
+        last_child->ChildrenInline()) {
+      to_block = To<LayoutBlock>(last_child);
+    } else {
+      to_block = to_base.CreateAnonymousBlock();
+      to_base.Children()->AppendChildNode(&to_base, to_block);
+    }
+  }
+  // Move our inline children into the target block we determined above.
+  MoveChildrenTo(to_block, FirstChild(), before_child);
+}
+
+void LayoutNGRubyBase::MoveBlockChildrenTo(LayoutNGRubyBase& to_base,
+                                           LayoutObject* before_child) {
+  NOT_DESTROYED();
+  DCHECK(!ChildrenInline());
+
+  if (!FirstChild()) {
+    return;
+  }
+
+  if (to_base.ChildrenInline()) {
+    to_base.MakeChildrenNonInline();
+  }
+
+  // If an anonymous block would be put next to another such block, then merge
+  // those.
+  LayoutObject* first_child_here = FirstChild();
+  LayoutObject* last_child_there = to_base.LastChild();
+  if (first_child_here->IsAnonymousBlock() &&
+      first_child_here->ChildrenInline() && last_child_there &&
+      last_child_there->IsAnonymousBlock() &&
+      last_child_there->ChildrenInline()) {
+    auto* anon_block_here = To<LayoutBlockFlow>(first_child_here);
+    auto* anon_block_there = To<LayoutBlockFlow>(last_child_there);
+    anon_block_here->MoveAllChildrenTo(anon_block_there,
+                                       anon_block_there->Children());
+    anon_block_here->DeleteLineBoxTree();
+    anon_block_here->Destroy();
+  }
+  // Move all remaining children normally. If moving all children, include our
+  // float list.
+  if (!before_child) {
+    bool full_remove_insert = to_base.HasLayer() || HasLayer();
+    // TODO(kojii): |this| is |!ChildrenInline()| when we enter this function,
+    // but it may turn to |ChildrenInline()| when |anon_block_here| is destroyed
+    // above. Probably the correct fix is to do it earlier and switch to
+    // |MoveInlineChildren()| if this happens. For the short term safe fix,
+    // using |full_remove_insert| can prevent inconsistent LayoutObject tree
+    // that leads to CHECK failures.
+    full_remove_insert |= ChildrenInline();
+    MoveAllChildrenIncludingFloatsTo(&to_base, full_remove_insert);
+  } else {
+    MoveChildrenTo(&to_base, FirstChild(), before_child);
+    RemoveFloatingObjectsFromDescendants();
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h
index 31af740..2071f670 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h
@@ -6,18 +6,13 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_BASE_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_base.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 
 namespace blink {
 
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
-    LayoutNGBlockFlowMixin<LayoutRubyBase>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyBase>;
-
-// A LayoutNG version of LayoutRubyBase.
-class CORE_EXPORT LayoutNGRubyBase final
-    : public LayoutNGBlockFlowMixin<LayoutRubyBase> {
+// Represents a ruby base box.
+// https://drafts.csswg.org/css-ruby-1/#ruby-base-box.
+class CORE_EXPORT LayoutNGRubyBase final : public LayoutNGBlockFlow {
  public:
   explicit LayoutNGRubyBase();
   ~LayoutNGRubyBase() override;
@@ -26,7 +21,26 @@
     NOT_DESTROYED();
     return "LayoutNGRubyBase";
   }
-  void UpdateBlockLayout(bool relayout_children) override;
+  bool IsOfType(LayoutObjectType type) const override;
+  bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
+
+  // This function removes all children that are before (!) `before_child`
+  // and appends them to `to_base`.
+  void MoveChildren(LayoutNGRubyBase& to_base,
+                    LayoutObject* before_child = nullptr);
+
+ private:
+  void MoveInlineChildrenTo(LayoutNGRubyBase& to_base,
+                            LayoutObject* before_child);
+  void MoveBlockChildrenTo(LayoutNGRubyBase& to_base,
+                           LayoutObject* before_child);
+};
+
+template <>
+struct DowncastTraits<LayoutNGRubyBase> {
+  static bool AllowFrom(const LayoutObject& object) {
+    return object.IsRubyBase();
+  }
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.cc
index 7b7aacabc72..e055670 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.cc
@@ -4,16 +4,207 @@
 
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
 
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
+
 namespace blink {
 
-LayoutNGRubyRun::LayoutNGRubyRun()
-    : LayoutNGBlockFlowMixin<LayoutRubyRun>(nullptr) {}
+LayoutNGRubyRun::LayoutNGRubyRun() : LayoutNGBlockFlow(nullptr) {
+  SetInline(true);
+  SetIsAtomicInlineLevel(true);
+}
 
 LayoutNGRubyRun::~LayoutNGRubyRun() = default;
 
-void LayoutNGRubyRun::UpdateBlockLayout(bool relayout_children) {
-  // TODO(crbug.com/1069817): Implement ruby-specific layout.
-  UpdateNGBlockLayout();
+bool LayoutNGRubyRun::IsOfType(LayoutObjectType type) const {
+  NOT_DESTROYED();
+  return type == kLayoutObjectRubyRun || LayoutBlockFlow::IsOfType(type);
+}
+
+bool LayoutNGRubyRun::CreatesAnonymousWrapper() const {
+  NOT_DESTROYED();
+  return true;
+}
+
+void LayoutNGRubyRun::RemoveLeftoverAnonymousBlock(LayoutBlock*) {
+  NOT_DESTROYED();
+}
+
+bool LayoutNGRubyRun::HasRubyText() const {
+  NOT_DESTROYED();
+  // The only place where a ruby text can be is in the first position
+  // Note: As anonymous blocks, ruby runs do not have ':before' or ':after'
+  // content themselves.
+  return FirstChild() && FirstChild()->IsRubyText();
+}
+
+bool LayoutNGRubyRun::HasRubyBase() const {
+  NOT_DESTROYED();
+  // The only place where a ruby base can be is in the last position
+  // Note: As anonymous blocks, ruby runs do not have ':before' or ':after'
+  // content themselves.
+  return LastChild() && LastChild()->IsRubyBase();
+}
+
+LayoutNGRubyText* LayoutNGRubyRun::RubyText() const {
+  NOT_DESTROYED();
+  LayoutObject* child = FirstChild();
+  // If in future it becomes necessary to support floating or positioned ruby
+  // text, layout will have to be changed to handle them properly.
+  DCHECK(!child || !child->IsRubyText() ||
+         !child->IsFloatingOrOutOfFlowPositioned());
+  return DynamicTo<LayoutNGRubyText>(child);
+}
+
+LayoutNGRubyBase* LayoutNGRubyRun::RubyBase() const {
+  NOT_DESTROYED();
+  return DynamicTo<LayoutNGRubyBase>(LastChild());
+}
+
+LayoutNGRubyBase& LayoutNGRubyRun::EnsureRubyBase() {
+  NOT_DESTROYED();
+  if (auto* base = RubyBase()) {
+    return *base;
+  }
+  auto& new_base = CreateRubyBase();
+  LayoutBlockFlow::AddChild(&new_base);
+  return new_base;
+}
+
+bool LayoutNGRubyRun::IsChildAllowed(LayoutObject* child,
+                                     const ComputedStyle&) const {
+  NOT_DESTROYED();
+  return child->IsRubyText() || child->IsInline();
+}
+
+void LayoutNGRubyRun::AddChild(LayoutObject* child,
+                               LayoutObject* before_child) {
+  NOT_DESTROYED();
+  DCHECK(child);
+
+  if (child->IsRubyText()) {
+    if (!before_child) {
+      // LayoutRuby has already ascertained that we can add the child here.
+      DCHECK(!HasRubyText());
+      // prepend ruby texts as first child
+      LayoutBlockFlow::AddChild(child, FirstChild());
+    } else if (before_child->IsRubyText()) {
+      // New text is inserted just before another.
+      // In this case the new text takes the place of the old one, and
+      // the old text goes into a new run that is inserted as next sibling.
+      DCHECK_EQ(before_child->Parent(), this);
+      LayoutObject* ruby = Parent();
+      DCHECK(ruby->IsRuby());
+      auto& new_run = Create(ruby, *ContainingBlock());
+      ruby->AddChild(&new_run, NextSibling());
+      new_run.EnsureRubyBase();
+      // Add the new ruby text and move the old one to the new run
+      // Note: Doing it in this order and not using LayoutNGRubyRun's methods,
+      // in order to avoid automatic removal of the ruby run in case there is no
+      // other child besides the old ruby text.
+      LayoutBlockFlow::AddChild(child, before_child);
+      LayoutBlockFlow::RemoveChild(before_child);
+      new_run.AddChild(before_child);
+    } else if (RubyBase()->FirstChild()) {
+      // Insertion before a ruby base object.
+      // In this case we need insert a new run before the current one and split
+      // the base.
+      LayoutObject* ruby = Parent();
+      LayoutNGRubyRun& new_run = Create(ruby, *ContainingBlock());
+      ruby->AddChild(&new_run, this);
+      auto& new_base = new_run.EnsureRubyBase();
+      new_run.AddChild(child);
+
+      // Make sure we don't leave anything in the percentage descendant
+      // map before moving the children to the new base.
+      auto& base = EnsureRubyBase();
+      if (HasPercentHeightDescendants() || base.HasPercentHeightDescendants()) {
+        ClearPercentHeightDescendants();
+      }
+      base.MoveChildren(new_base, before_child);
+    }
+  } else {
+    // child is not a text -> insert it into the base
+    // (append it instead if beforeChild is the ruby text)
+    auto& base = EnsureRubyBase();
+    if (before_child == &base) {
+      before_child = base.FirstChild();
+    }
+    if (before_child && before_child->IsRubyText()) {
+      before_child = nullptr;
+    }
+    DCHECK(!before_child || before_child->IsDescendantOf(&base));
+    base.AddChild(child, before_child);
+  }
+}
+
+void LayoutNGRubyRun::RemoveChild(LayoutObject* child) {
+  NOT_DESTROYED();
+  // If the child is a ruby text, then merge the ruby base with the base of
+  // the right sibling run, if possible.
+  if (!BeingDestroyed() && !DocumentBeingDestroyed() && child->IsRubyText()) {
+    auto* base = RubyBase();
+    LayoutObject* right_neighbour = NextSibling();
+    if (base->FirstChild() && right_neighbour && right_neighbour->IsRubyRun()) {
+      auto* right_run = To<LayoutNGRubyRun>(right_neighbour);
+      auto& right_base = right_run->EnsureRubyBase();
+      if (right_base.FirstChild()) {
+        // Collect all children in a single base, then swap the bases.
+        if (right_base.HasPercentHeightDescendants()) {
+          right_base.ClearPercentHeightDescendants();
+        }
+        right_base.MoveChildren(*base);
+        MoveChildTo(right_run, base);
+        right_run->MoveChildTo(this, &right_base);
+        DCHECK(!RubyBase()->FirstChild());
+      }
+    }
+  }
+
+  LayoutBlockFlow::RemoveChild(child);
+
+  if (!BeingDestroyed() && !DocumentBeingDestroyed()) {
+    // If this has only an empty LayoutRubyBase, destroy this sub-tree.
+    LayoutBlockFlow* base = RubyBase();
+    if (!HasRubyText() && !base->FirstChild()) {
+      LayoutBlockFlow::RemoveChild(base);
+      base->DeleteLineBoxTree();
+      base->Destroy();
+      DeleteLineBoxTree();
+      Destroy();
+    }
+  }
+}
+
+LayoutNGRubyBase& LayoutNGRubyRun::CreateRubyBase() const {
+  NOT_DESTROYED();
+  auto* layout_object = MakeGarbageCollected<LayoutNGRubyBase>();
+  layout_object->SetDocumentForAnonymous(&GetDocument());
+  ComputedStyleBuilder new_style_builder =
+      GetDocument().GetStyleResolver().CreateAnonymousStyleBuilderWithDisplay(
+          StyleRef(), EDisplay::kBlock);
+  new_style_builder.SetTextAlign(
+      ETextAlign::kCenter);  // FIXME: use WEBKIT_CENTER?
+  new_style_builder.SetHasLineIfEmpty(true);
+  layout_object->SetStyle(new_style_builder.TakeStyle());
+  return *layout_object;
+}
+
+// static
+LayoutNGRubyRun& LayoutNGRubyRun::Create(const LayoutObject* parent_ruby,
+                                         const LayoutBlock& containing_block) {
+  DCHECK(parent_ruby);
+  DCHECK(parent_ruby->IsRuby());
+  LayoutNGRubyRun* rr = MakeGarbageCollected<LayoutNGRubyRun>();
+  rr->SetDocumentForAnonymous(&parent_ruby->GetDocument());
+  scoped_refptr<const ComputedStyle> new_style =
+      parent_ruby->GetDocument()
+          .GetStyleResolver()
+          .CreateAnonymousStyleWithDisplay(parent_ruby->StyleRef(),
+                                           EDisplay::kInlineBlock);
+  rr->SetStyle(std::move(new_style));
+  return *rr;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h
index ec9b035..3408a00 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h
@@ -6,27 +6,52 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_RUN_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 
 namespace blink {
 
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
-    LayoutNGBlockFlowMixin<LayoutRubyRun>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyRun>;
+class LayoutNGRubyBase;
+class LayoutNGRubyText;
 
-// A LayoutNG version of LayoutRubyRun.
-class CORE_EXPORT LayoutNGRubyRun final
-    : public LayoutNGBlockFlowMixin<LayoutRubyRun> {
+// LayoutNGRubyRun are 'inline-block/table' like objects,and wrap a single
+// pairing of a ruby base with its ruby text(s).
+// See layout_ruby.h for further comments on the structure
+class CORE_EXPORT LayoutNGRubyRun final : public LayoutNGBlockFlow {
  public:
   explicit LayoutNGRubyRun();
   ~LayoutNGRubyRun() override;
+  static LayoutNGRubyRun& Create(const LayoutObject* parent_ruby,
+                                 const LayoutBlock& containing_block);
 
   const char* GetName() const override {
     NOT_DESTROYED();
     return "LayoutNGRubyRun";
   }
-  void UpdateBlockLayout(bool relayout_children) override;
+
+  bool HasRubyText() const;
+  bool HasRubyBase() const;
+  LayoutNGRubyText* RubyText() const;
+  LayoutNGRubyBase* RubyBase() const;
+  // Creates the base if it doesn't already exist
+  LayoutNGRubyBase& EnsureRubyBase();
+
+  bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
+  void AddChild(LayoutObject* child,
+                LayoutObject* before_child = nullptr) override;
+  void RemoveChild(LayoutObject* child) override;
+  bool IsOfType(LayoutObjectType type) const override;
+  bool CreatesAnonymousWrapper() const override;
+  void RemoveLeftoverAnonymousBlock(LayoutBlock*) override;
+
+ private:
+  LayoutNGRubyBase& CreateRubyBase() const;
+};
+
+template <>
+struct DowncastTraits<LayoutNGRubyRun> {
+  static bool AllowFrom(const LayoutObject& object) {
+    return object.IsRubyRun();
+  }
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.cc
index c36b0b7a4..4300620 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.cc
@@ -4,15 +4,43 @@
 
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
 
+#include "third_party/blink/renderer/core/frame/web_feature.h"
+
 namespace blink {
 
 LayoutNGRubyText::LayoutNGRubyText(Element* element)
-    : LayoutNGBlockFlowMixin<LayoutRubyText>(element) {}
+    : LayoutNGBlockFlow(element) {}
 
 LayoutNGRubyText::~LayoutNGRubyText() = default;
 
-void LayoutNGRubyText::UpdateBlockLayout(bool relayout_children) {
-  UpdateNGBlockLayout();
+bool LayoutNGRubyText::IsOfType(LayoutObjectType type) const {
+  NOT_DESTROYED();
+  return type == kLayoutObjectRubyText || LayoutNGBlockFlow::IsOfType(type);
+}
+
+bool LayoutNGRubyText::CreatesNewFormattingContext() const {
+  NOT_DESTROYED();
+  // Ruby text objects are pushed around after layout, to become flush with
+  // the associated ruby base. As such, we cannot let floats leak out from
+  // ruby text objects.
+  return true;
+}
+
+bool LayoutNGRubyText::IsChildAllowed(LayoutObject* child,
+                                      const ComputedStyle&) const {
+  NOT_DESTROYED();
+  return child->IsInline();
+}
+
+void LayoutNGRubyText::StyleDidChange(StyleDifference diff,
+                                      const ComputedStyle* old_style) {
+  NOT_DESTROYED();
+  if (StyleRef().GetTextAlign() !=
+      ComputedStyleInitialValues::InitialTextAlign()) {
+    UseCounter::Count(GetDocument(),
+                      WebFeature::kRubyTextWithNonDefaultTextAlign);
+  }
+  LayoutNGBlockFlow::StyleDidChange(diff, old_style);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h
index 0d6d4af2..8b4534b 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h
@@ -6,18 +6,13 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_RUBY_TEXT_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 
 namespace blink {
 
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
-    LayoutNGBlockFlowMixin<LayoutRubyText>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT LayoutNGMixin<LayoutRubyText>;
-
-// A LayoutNG version of LayoutRubyText.
-class CORE_EXPORT LayoutNGRubyText final
-    : public LayoutNGBlockFlowMixin<LayoutRubyText> {
+// LayoutNGRubyText represents a ruby annotation box.
+// https://drafts.csswg.org/css-ruby-1/#ruby-annotation-box
+class CORE_EXPORT LayoutNGRubyText final : public LayoutNGBlockFlow {
  public:
   explicit LayoutNGRubyText(Element* element);
   ~LayoutNGRubyText() override;
@@ -26,7 +21,18 @@
     NOT_DESTROYED();
     return "LayoutNGRubyText";
   }
-  void UpdateBlockLayout(bool relayout_children) override;
+  bool IsOfType(LayoutObjectType type) const override;
+  bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
+  void StyleDidChange(StyleDifference diff,
+                      const ComputedStyle* old_style) override;
+  bool CreatesNewFormattingContext() const override;
+};
+
+template <>
+struct DowncastTraits<LayoutNGRubyText> {
+  static bool AllowFrom(const LayoutObject& object) {
+    return object.IsRubyText();
+  }
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc b/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc
index d2e09503..c128213 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc
@@ -128,6 +128,12 @@
     string_builder.Append("px");
   }
 
+  if (MonolithicOverflow()) {
+    string_builder.Append(" monolithic overflow:");
+    string_builder.Append(MonolithicOverflow().ToString());
+    string_builder.Append("px");
+  }
+
   return string_builder.ToString();
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h b/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h
index 2f540df..6c433de 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h
@@ -107,6 +107,21 @@
     return data_->sequence_number;
   }
 
+  // The amount of monolithic fragmentainer overflow.
+  //
+  // Fragmentainer overflow occurs when there is monolithic content, and when
+  // printing, we record it here, in order to steer clear of it on subsequent
+  // pages.
+  //
+  // This value is only used (and set) when printing.
+  LayoutUnit MonolithicOverflow() const {
+#if DCHECK_IS_ON()
+    DCHECK(!is_repeated_actual_break_);
+#endif
+    DCHECK(data_);
+    return data_->monolithic_overflow;
+  }
+
   const NGBlockBreakTokenData* TokenData() const {
 #if DCHECK_IS_ON()
     DCHECK(!is_repeated_actual_break_);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_break_token_data.h b/third_party/blink/renderer/core/layout/ng/ng_block_break_token_data.h
index e086c3b..7fd53ef1 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_break_token_data.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_break_token_data.h
@@ -34,6 +34,7 @@
       consumed_block_size_legacy_adjustment =
           other_data->consumed_block_size_legacy_adjustment;
       sequence_number = other_data->sequence_number;
+      monolithic_overflow = other_data->monolithic_overflow;
     }
   }
 
@@ -53,6 +54,7 @@
 
   LayoutUnit consumed_block_size;
   LayoutUnit consumed_block_size_legacy_adjustment;
+  LayoutUnit monolithic_overflow;
 
   unsigned sequence_number = 0;
   unsigned type : 3;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 27507ec..353e4a7 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -559,6 +559,19 @@
 
   LayoutUnit content_edge = BorderScrollbarPadding().block_start;
 
+  if (BreakToken() && BreakToken()->MonolithicOverflow()) {
+    // If we have been pushed by monolithic overflow that started on a previous
+    // page, we'll behave as if there's a valid breakpoint before the first
+    // child here, and that it has perfect break appeal. This isn't always
+    // strictly correct (the monolithic content in question may have
+    // break-after:avoid, for instance), but should be a reasonable approach,
+    // unless we want to make a bigger effort.
+    //
+    // So just pretend that we have processed the first child already.
+    // TODO(layout-dev): Consider renaming has_processed_first_child_.
+    has_processed_first_child_ = true;
+  }
+
   NGPreviousInflowPosition previous_inflow_position = {
       LayoutUnit(), ConstraintSpace().MarginStrut(),
       is_resuming_ ? LayoutUnit() : container_builder_.Padding().block_start,
@@ -1242,6 +1255,14 @@
           ? NextBorderEdge(previous_inflow_position)
           : ConstraintSpace().ExpectedBfcBlockOffset()};
 
+  if (child_break_token) {
+    // If there's monolithic content inside the float from a previous page
+    // overflowing into this one, move past it. And subtract any such overflow
+    // from the parent flow, as floats establish a parallel flow.
+    origin_bfc_offset.block_offset += child_break_token->MonolithicOverflow() -
+                                      BreakToken()->MonolithicOverflow();
+  }
+
   if (ConstraintSpace().HasBlockFragmentation()) {
     // Forced breaks cannot be specified directly on floats, but if the
     // preceding block has a forced break after, we need to break before this
@@ -2193,6 +2214,9 @@
   // inside of the child's layout
   NGMarginStrut margin_strut = previous_inflow_position.margin_strut;
 
+  LayoutUnit logical_block_offset =
+      previous_inflow_position.logical_block_offset;
+
   const auto* child_block_break_token =
       DynamicTo<NGBlockBreakToken>(child_break_token);
   if (UNLIKELY(child_block_break_token)) {
@@ -2203,10 +2227,16 @@
       // breaks). Margins after a forced break should be retained.
       margin_strut = NGMarginStrut();
     }
-  }
 
-  LayoutUnit logical_block_offset =
-      previous_inflow_position.logical_block_offset;
+    if (child_block_break_token->MonolithicOverflow() &&
+        !BreakToken()->MonolithicOverflow()) {
+      // Every container that needs to be pushed to steer clear of monolithic
+      // overflow on a previous page will have this stored in its break token.
+      // So we'll only add the additional offset here if the child is the
+      // outermost container with monolithic overflow recorded.
+      logical_block_offset += child_block_break_token->MonolithicOverflow();
+    }
+  }
 
   margin_strut.Append(margins.block_start,
                       child.Style().HasMarginBeforeQuirk());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 7312f8c2..670f0e65 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -19,8 +19,6 @@
 #include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
 #include "third_party/blink/renderer/core/layout/layout_multi_column_set.h"
 #include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/layout/layout_video.h"
 #include "third_party/blink/renderer/core/layout/min_max_sizes.h"
 #include "third_party/blink/renderer/core/layout/ng/custom/layout_ng_custom.h"
@@ -183,7 +181,7 @@
     CreateAlgorithmAndRun<NGReplacedLayoutAlgorithm>(params, callback);
   } else if (box.IsFieldset()) {
     CreateAlgorithmAndRun<NGFieldsetLayoutAlgorithm>(params, callback);
-  } else if (box.IsLayoutNGFrameSet()) {
+  } else if (box.IsFrameSet()) {
     CreateAlgorithmAndRun<NGFrameSetLayoutAlgorithm>(params, callback);
   }
   // If there's a legacy layout box, we can only do block fragmentation if
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
index c1bb208..9d6ffa0 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -134,17 +134,13 @@
   NGBlockNode GetRenderedLegend() const;
   NGBlockNode GetFieldsetContent() const;
 
-  bool IsNGTableCell() const {
-    return box_->IsTableCell() && !box_->IsTableCellLegacy();
-  }
+  bool IsNGTableCell() const { return box_->IsTableCell(); }
 
   bool IsContainingBlockNGGrid() const {
     return box_->ContainingBlock()->IsLayoutNGGrid();
   }
-  bool IsFrameSet() const { return box_->IsLayoutNGFrameSet(); }
-  bool IsParentNGFrameSet() const {
-    return box_->Parent()->IsLayoutNGFrameSet();
-  }
+  bool IsFrameSet() const { return box_->IsFrameSet(); }
+  bool IsParentNGFrameSet() const { return box_->Parent()->IsFrameSet(); }
   bool IsParentNGGrid() const { return box_->Parent()->IsLayoutNGGrid(); }
 
   // Return true if this block node establishes an inline formatting context.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
index 8815bdd1..2a67e67 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -387,22 +387,48 @@
       is_block_size_for_fragmentation_clamped_ = true;
   }
 
+  const NGPhysicalFragment& child_fragment =
+      child_layout_result.PhysicalFragment();
   const auto* child_box_fragment =
-      DynamicTo<NGPhysicalBoxFragment>(&child_layout_result.PhysicalFragment());
+      DynamicTo<NGPhysicalBoxFragment>(child_fragment);
+  const NGBlockBreakToken* token =
+      child_box_fragment ? child_box_fragment->BreakToken() : nullptr;
+
+  // Figure out if this child break is in the same flow as this parent. If it's
+  // an out-of-flow positioned box, it's not. If it's in a parallel flow, it's
+  // also not.
+  bool child_is_in_same_flow =
+      ((!token || !token->IsAtBlockEnd()) &&
+       !child_fragment.IsFloatingOrOutOfFlowPositioned()) ||
+      child_layout_result.ShouldForceSameFragmentationFlow();
+
+  if (ConstraintSpace().IsPaginated() && child_is_in_same_flow &&
+      !IsFragmentainerBoxType()) {
+    DCHECK(ConstraintSpace().HasKnownFragmentainerBlockSize());
+    NGFragment logical_fragment(child_fragment.Style().GetWritingDirection(),
+                                child_fragment);
+    LayoutUnit fragment_block_end =
+        offset.block_offset + logical_fragment.BlockSize();
+    LayoutUnit fragmentainer_overflow =
+        fragment_block_end - FragmentainerSpaceLeft(ConstraintSpace());
+    if (fragmentainer_overflow > LayoutUnit()) {
+      // This child overflows the page, because there's something monolithic
+      // inside. We need to be aware of this when laying out subsequent pages,
+      // so that we can move past it, rather than overlapping with it. This
+      // approach works (kind of) because in our implementation, pages are
+      // stacked in the block direction, so that the block-start offset of the
+      // next page is the same as the block-end offset of the preceding page.
+      ReserveSpaceForMonolithicOverflow(fragmentainer_overflow);
+    }
+  }
+
   if (!child_box_fragment)
     return;
 
-  const NGBlockBreakToken* token = child_box_fragment->BreakToken();
   if (IsBreakInside(token)) {
-    // Figure out if this child break is in the same flow as this parent. If
-    // it's an out-of-flow positioned box, it's not. If it's in a parallel flow,
-    // it's also not.
-    if (!token->IsAtBlockEnd() &&
-        !child_box_fragment->IsFloatingOrOutOfFlowPositioned())
+    if (child_is_in_same_flow) {
       has_inflow_child_break_inside_ = true;
-
-    if (child_layout_result.ShouldForceSameFragmentationFlow())
-      has_inflow_child_break_inside_ = true;
+    }
 
     // Downgrade the appeal of breaking inside this container, if the break
     // inside the child is less appealing than what we've found so far.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
index a198113e..e249f61 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -19,6 +19,7 @@
 #include "third_party/blink/renderer/core/layout/ng/mathml/ng_mathml_paint_info.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_break_token.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
@@ -296,6 +297,13 @@
     EnsureBreakTokenData()->consumed_block_size_legacy_adjustment = adjustment;
   }
 
+  void ReserveSpaceForMonolithicOverflow(LayoutUnit monolithic_overflow) {
+    DCHECK(ConstraintSpace().IsPaginated());
+    auto* data = EnsureBreakTokenData();
+    data->monolithic_overflow =
+        std::max(data->monolithic_overflow, monolithic_overflow);
+  }
+
   // Set how much of the column block-size we've used so far. This will be used
   // to determine the block-size of any new columns added by descendant
   // out-of-flow positioned elements.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
index 61ef6a4..f4fe4b0 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
@@ -32,6 +32,7 @@
 namespace blink {
 
 class NGColumnSpannerPath;
+class NGConstraintSpace;
 class NGExclusionSpace;
 class NGInlineBreakToken;
 class NGPhysicalFragment;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
index 8d7bfb5a..d0d6356d 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -502,21 +502,21 @@
     // already have broken inside). We'll allow this to overflow the
     // fragmentainer.
     //
-    // TODO(mstensho): This is desired behavior for multicol, but not ideal for
-    // printing, where we'd prefer the unbreakable content to be sliced into
-    // different pages, lest it be clipped and lost.
-    //
     // There is a last-resort breakpoint before trailing border and padding, so
     // first check if we can break there and still make progress. Don't allow a
     // break here for table cells, though, as that might disturb the row
     // stretching machinery, causing an infinite loop. We'd add the stretch
     // amount to the block-size to the content box of the table cell, even
-    // though we're past it.
+    // though we're past it. We're always guaranteed progress if there's
+    // incoming monolithic overflow, so in such cases we can always break before
+    // border / padding (and add as many fragments we need in order to get past
+    // the overflow).
     DCHECK_GE(desired_intrinsic_block_size, trailing_border_padding);
     DCHECK_GE(desired_block_size, trailing_border_padding);
 
     LayoutUnit subtractable_border_padding;
-    if (desired_block_size > trailing_border_padding && !node.IsTableCell()) {
+    if ((desired_block_size > trailing_border_padding && !node.IsTableCell()) ||
+        (previous_break_token && previous_break_token->MonolithicOverflow())) {
       subtractable_border_padding = trailing_border_padding;
     }
 
@@ -564,6 +564,19 @@
     return NGBreakStatus::kContinue;
   }
 
+  if (!final_block_size && previous_break_token &&
+      previous_break_token->MonolithicOverflow()) {
+    // See if we've now managed to move past previous fragmentainer overflow, or
+    // if we need to steer clear of at least some of it in the next
+    // fragmentainer as well. This only happens when printing monolithic
+    // content.
+    LayoutUnit remaining_overflow = previous_break_token->MonolithicOverflow() -
+                                    FragmentainerCapacity(space);
+    if (remaining_overflow > LayoutUnit()) {
+      builder->ReserveSpaceForMonolithicOverflow(remaining_overflow);
+    }
+  }
+
   if (builder->ShouldBreakInside()) {
     // We need to break before or inside one of our children (or have already
     // done so). Even if we fit within the remaining space, and even if the
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
index 85d7998b..9dbebfd 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -9,7 +9,6 @@
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index a298562..d20c941 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -2243,7 +2243,12 @@
     NodeToLayout fragmented_descendant = descendant;
     fragmented_descendant.break_token = break_token;
     if (!break_token->IsRepeated()) {
-      fragmented_descendant.offset_info.offset.block_offset = LayoutUnit();
+      // Fragmented nodes usually resume at the block-start of the next
+      // fragmentainer. One exception is if there's fragmentainer overflow
+      // caused by monolithic content in paged media. Then we need to move past
+      // that.
+      fragmented_descendant.offset_info.offset.block_offset =
+          break_token->MonolithicOverflow();
       *has_actual_break_inside = true;
     }
     fragmented_descendants->emplace_back(fragmented_descendant);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
index 31e37ad7..8277d21 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
@@ -184,9 +184,7 @@
   bool IsAnonymousBlock() const {
     return IsCSSBox() && layout_object_->IsAnonymousBlock();
   }
-  bool IsFrameSet() const {
-    return IsCSSBox() && layout_object_->IsLayoutNGFrameSet();
-  }
+  bool IsFrameSet() const { return IsCSSBox() && layout_object_->IsFrameSet(); }
   bool IsListMarker() const {
     return IsCSSBox() && layout_object_->IsLayoutNGOutsideListMarker();
   }
@@ -218,8 +216,7 @@
   }
 
   bool IsTableNGCell() const {
-    return IsTableNGPart() && layout_object_->IsTableCell() &&
-           !layout_object_->IsTableCellLegacy();
+    return IsTableNGPart() && layout_object_->IsTableCell();
   }
 
   bool IsGridNG() const { return layout_object_->IsLayoutNGGrid(); }
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc
index b0c3875..32f99ecd 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.cc
@@ -4,15 +4,17 @@
 
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
 
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_interface.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 #include "third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h"
@@ -41,6 +43,140 @@
 
 LayoutNGTable::~LayoutNGTable() = default;
 
+LayoutNGTable* LayoutNGTable::CreateAnonymousWithParent(
+    const LayoutObject& parent) {
+  scoped_refptr<const ComputedStyle> new_style =
+      parent.GetDocument().GetStyleResolver().CreateAnonymousStyleWithDisplay(
+          parent.StyleRef(),
+          parent.IsLayoutInline() ? EDisplay::kInlineTable : EDisplay::kTable);
+  auto* new_table = MakeGarbageCollected<LayoutNGTable>(nullptr);
+  new_table->SetDocumentForAnonymous(&parent.GetDocument());
+  new_table->SetStyle(std::move(new_style));
+  return new_table;
+}
+
+bool LayoutNGTable::IsFirstCell(const LayoutNGTableCell& cell) const {
+  NOT_DESTROYED();
+  const LayoutNGTableRow* row = cell.Row();
+  if (row->FirstCell() != &cell) {
+    return false;
+  }
+  const LayoutNGTableSection* section = row->Section();
+  if (section->FirstRow() != row) {
+    return false;
+  }
+  NGTableGroupedChildren grouped_children(
+      NGBlockNode(const_cast<LayoutNGTable*>(this)));
+  auto first_section = grouped_children.begin();
+  return first_section != grouped_children.end() &&
+         (*first_section).GetLayoutBox() == section;
+}
+
+LayoutNGTableSection* LayoutNGTable::FirstSection() const {
+  NOT_DESTROYED();
+  NGTableGroupedChildren grouped_children(
+      NGBlockNode(const_cast<LayoutNGTable*>(this)));
+  auto first_section = grouped_children.begin();
+  if (first_section != grouped_children.end()) {
+    return To<LayoutNGTableSection>((*first_section).GetLayoutBox());
+  }
+  return nullptr;
+}
+
+LayoutNGTableSection* LayoutNGTable::LastSection() const {
+  NOT_DESTROYED();
+  NGTableGroupedChildren grouped_children(
+      NGBlockNode(const_cast<LayoutNGTable*>(this)));
+  auto last_section = --grouped_children.end();
+  if (last_section != grouped_children.end()) {
+    return To<LayoutNGTableSection>((*last_section).GetLayoutBox());
+  }
+  return nullptr;
+}
+
+LayoutNGTableSection* LayoutNGTable::FirstNonEmptySection() const {
+  NOT_DESTROYED();
+  NGTableGroupedChildren grouped_children(
+      NGBlockNode(const_cast<LayoutNGTable*>(this)));
+  auto first_section = grouped_children.begin();
+  if (first_section != grouped_children.end()) {
+    auto* section_object =
+        To<LayoutNGTableSection>((*first_section).GetLayoutBox());
+    if ((*first_section).IsEmptyTableSection()) {
+      return NextSection(section_object, kSkipEmptySections);
+    }
+    return section_object;
+  }
+  return nullptr;
+}
+
+LayoutNGTableSection* LayoutNGTable::LastNonEmptySection() const {
+  NOT_DESTROYED();
+  NGTableGroupedChildren grouped_children(
+      NGBlockNode(const_cast<LayoutNGTable*>(this)));
+  auto last_section = --grouped_children.end();
+  if (last_section != grouped_children.end()) {
+    auto* section_object =
+        To<LayoutNGTableSection>((*last_section).GetLayoutBox());
+    if ((*last_section).IsEmptyTableSection()) {
+      return PreviousSection(section_object, kSkipEmptySections);
+    }
+    return section_object;
+  }
+  return nullptr;
+}
+
+LayoutNGTableSection* LayoutNGTable::NextSection(
+    const LayoutNGTableSection* current,
+    SkipEmptySectionsValue skip) const {
+  NOT_DESTROYED();
+  NGTableGroupedChildren grouped_children(
+      NGBlockNode(const_cast<LayoutNGTable*>(this)));
+  bool found = false;
+  for (NGBlockNode section : grouped_children) {
+    if (found &&
+        (skip == kDoNotSkipEmptySections || !section.IsEmptyTableSection())) {
+      return To<LayoutNGTableSection>(section.GetLayoutBox());
+    }
+    if (current == To<LayoutNGTableSection>(section.GetLayoutBox())) {
+      found = true;
+    }
+  }
+  return nullptr;
+}
+
+LayoutNGTableSection* LayoutNGTable::PreviousSection(
+    const LayoutNGTableSection* current,
+    SkipEmptySectionsValue skip) const {
+  NOT_DESTROYED();
+  NGTableGroupedChildren grouped_children(
+      NGBlockNode(const_cast<LayoutNGTable*>(this)));
+  auto stop = --grouped_children.begin();
+  bool found = false;
+  for (auto it = --grouped_children.end(); it != stop; --it) {
+    NGBlockNode section = *it;
+    if (found &&
+        (skip == kDoNotSkipEmptySections || !section.IsEmptyTableSection())) {
+      return To<LayoutNGTableSection>(section.GetLayoutBox());
+    }
+    if (current == To<LayoutNGTableSection>(section.GetLayoutBox())) {
+      found = true;
+    }
+  }
+  return nullptr;
+}
+
+LayoutNGTableSection* LayoutNGTable::FirstBody() const {
+  NOT_DESTROYED();
+  for (LayoutObject* child = FirstChild(); child;
+       child = child->NextSibling()) {
+    if (child->StyleRef().Display() == EDisplay::kTableRowGroup) {
+      return To<LayoutNGTableSection>(child);
+    }
+  }
+  return nullptr;
+}
+
 wtf_size_t LayoutNGTable::ColumnCount() const {
   NOT_DESTROYED();
   const NGLayoutResult* cached_layout_result = GetCachedLayoutResult(nullptr);
@@ -133,6 +269,7 @@
   NOT_DESTROYED();
   TableGridStructureChanged();
   // Only TablesNG table parts are allowed.
+  // TODO(1229581): Change this DCHECK to caption || column || section.
   DCHECK(child->IsLayoutNGObject() ||
          (!child->IsTableCaption() && !child->IsLayoutTableCol() &&
           !child->IsTableSection()));
@@ -179,8 +316,7 @@
       NeedsTableSection(*before_child))
     before_child = nullptr;
 
-  LayoutBox* section =
-      LayoutObjectFactory::CreateAnonymousTableSectionWithParent(*this);
+  auto* section = LayoutNGTableSection::CreateAnonymousWithParent(*this);
   AddChild(section, before_child);
   section->AddChild(child);
 }
@@ -212,7 +348,7 @@
 LayoutBox* LayoutNGTable::CreateAnonymousBoxWithSameTypeAs(
     const LayoutObject* parent) const {
   NOT_DESTROYED();
-  return LayoutObjectFactory::CreateAnonymousTableWithParent(*parent);
+  return CreateAnonymousWithParent(*parent);
 }
 
 PhysicalRect LayoutNGTable::OverflowClipRect(
@@ -376,128 +512,51 @@
 
 bool LayoutNGTable::IsFirstCell(const LayoutNGTableCellInterface& cell) const {
   NOT_DESTROYED();
-  const LayoutNGTableRowInterface* row = cell.RowInterface();
-  if (row->FirstCellInterface() != &cell)
-    return false;
-  const LayoutNGTableSectionInterface* section = row->SectionInterface();
-  if (section->FirstRowInterface() != row)
-    return false;
-  NGTableGroupedChildren grouped_children(
-      NGBlockNode(const_cast<LayoutNGTable*>(this)));
-  auto first_section = grouped_children.begin();
-  return first_section != grouped_children.end() &&
-         ToInterface<LayoutNGTableSectionInterface>(
-             (*first_section).GetLayoutBox()) == section;
+  return IsFirstCell(*To<LayoutNGTableCell>(cell.ToLayoutObject()));
 }
 
 // Only called from AXLayoutObject::IsDataTable()
 LayoutNGTableSectionInterface* LayoutNGTable::FirstBodyInterface() const {
   NOT_DESTROYED();
-  for (LayoutObject* child = FirstChild(); child;
-       child = child->NextSibling()) {
-    if (child->StyleRef().Display() == EDisplay::kTableRowGroup)
-      return ToInterface<LayoutNGTableSectionInterface>(child);
-  }
-  return nullptr;
+  return FirstBody();
 }
 
 // Called from many AXLayoutObject methods.
 LayoutNGTableSectionInterface* LayoutNGTable::FirstSectionInterface() const {
   NOT_DESTROYED();
-  NGTableGroupedChildren grouped_children(
-      NGBlockNode(const_cast<LayoutNGTable*>(this)));
-  auto first_section = grouped_children.begin();
-  if (first_section != grouped_children.end()) {
-    return ToInterface<LayoutNGTableSectionInterface>(
-        (*first_section).GetLayoutBox());
-  }
-  return nullptr;
+  return FirstSection();
 }
 
 LayoutNGTableSectionInterface* LayoutNGTable::FirstNonEmptySectionInterface()
     const {
   NOT_DESTROYED();
-  NGTableGroupedChildren grouped_children(
-      NGBlockNode(const_cast<LayoutNGTable*>(this)));
-  auto first_section = grouped_children.begin();
-  if (first_section == grouped_children.end())
-    return nullptr;
-
-  auto* first_section_interface = ToInterface<LayoutNGTableSectionInterface>(
-      (*first_section).GetLayoutBox());
-  if ((*first_section).IsEmptyTableSection()) {
-    return NextSectionInterface(first_section_interface, kSkipEmptySections);
-  }
-
-  return first_section_interface;
+  return FirstNonEmptySection();
 }
 
 LayoutNGTableSectionInterface* LayoutNGTable::LastSectionInterface() const {
   NOT_DESTROYED();
-  NGTableGroupedChildren grouped_children(
-      NGBlockNode(const_cast<LayoutNGTable*>(this)));
-  auto last_section = --grouped_children.end();
-  if (last_section != grouped_children.end()) {
-    return ToInterface<LayoutNGTableSectionInterface>(
-        (*last_section).GetLayoutBox());
-  }
-  return nullptr;
+  return LastSection();
 }
 
 LayoutNGTableSectionInterface* LayoutNGTable::LastNonEmptySectionInterface()
     const {
   NOT_DESTROYED();
-  NGTableGroupedChildren grouped_children(
-      NGBlockNode(const_cast<LayoutNGTable*>(this)));
-  auto last_section = --grouped_children.end();
-  if (last_section == grouped_children.end())
-    return nullptr;
-
-  auto* last_section_interface = ToInterface<LayoutNGTableSectionInterface>(
-      (*last_section).GetLayoutBox());
-  if ((*last_section).IsEmptyTableSection()) {
-    return PreviousSectionInterface(last_section_interface, kSkipEmptySections);
-  }
-
-  return last_section_interface;
+  return LastNonEmptySection();
 }
 
 LayoutNGTableSectionInterface* LayoutNGTable::NextSectionInterface(
     const LayoutNGTableSectionInterface* target,
     SkipEmptySectionsValue skip) const {
   NOT_DESTROYED();
-  NGTableGroupedChildren grouped_children(
-      NGBlockNode(const_cast<LayoutNGTable*>(this)));
-  bool found = false;
-  for (NGBlockNode section : grouped_children) {
-    if (found &&
-        ((skip == kDoNotSkipEmptySections) || (!section.IsEmptyTableSection())))
-      return To<LayoutNGTableSection>(section.GetLayoutBox());
-    if (target == To<LayoutNGTableSection>(section.GetLayoutBox())
-                      ->ToLayoutNGTableSectionInterface())
-      found = true;
-  }
-  return nullptr;
+  return NextSection(To<LayoutNGTableSection>(target->ToLayoutObject()), skip);
 }
 
 LayoutNGTableSectionInterface* LayoutNGTable::PreviousSectionInterface(
     const LayoutNGTableSectionInterface* target,
     SkipEmptySectionsValue skip) const {
   NOT_DESTROYED();
-  NGTableGroupedChildren grouped_children(
-      NGBlockNode(const_cast<LayoutNGTable*>(this)));
-  auto stop = --grouped_children.begin();
-  bool found = false;
-  for (auto it = --grouped_children.end(); it != stop; --it) {
-    NGBlockNode section = *it;
-    if (found &&
-        ((skip == kDoNotSkipEmptySections) || (!section.IsEmptyTableSection())))
-      return To<LayoutNGTableSection>(section.GetLayoutBox());
-    if (target == To<LayoutNGTableSection>(section.GetLayoutBox())
-                      ->ToLayoutNGTableSectionInterface())
-      found = true;
-  }
-  return nullptr;
+  return PreviousSection(To<LayoutNGTableSection>(target->ToLayoutObject()),
+                         skip);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h
index 6e154f4..071aa77d 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h
@@ -14,8 +14,72 @@
 
 namespace blink {
 
+class LayoutNGTableSection;
+class LayoutNGTableCell;
 class NGTableBorders;
 
+// LayoutNGTable is the LayoutObject associated with
+// display: table or inline-table.
+//
+// LayoutNGTable is the coordinator for determining the overall table structure.
+// The reason is that LayoutNGTableSection children have a local view over what
+// their structure is but don't account for other LayoutNGTableSection. Thus
+// LayoutNGTable helps keep consistency across LayoutNGTableSection.
+//
+// LayoutNGTable expects only 3 types of children:
+// - zero or more LayoutNGTableColumn
+// - zero or more LayoutNGTableCaption
+// - zero or more LayoutNGTableSection
+// This is aligned with what HTML5 expects:
+// https://html.spec.whatwg.org/C/#the-table-element
+// with one difference: we allow more than one caption as we follow what
+// CSS expects (https://bugs.webkit.org/show_bug.cgi?id=69773).
+// Those expectations are enforced by LayoutNGTable::AddChild, that wraps
+// unknown children into an anonymous LayoutNGTableSection. This is what the
+// "generate missing child wrapper" step in CSS mandates in
+// http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes.
+//
+// LayoutNGTable assumes a pretty strict structure that is mandated by CSS:
+// (note that this structure in HTML is enforced by the HTML5 Parser).
+//
+//                 LayoutNGTable
+//                 |          |
+//  LayoutNGTableSection    LayoutNGTableCaption
+//                 |
+//      LayoutNGTableRow
+//                 |
+//     LayoutNGTableCell
+//
+// This means that we have to generate some anonymous table wrappers in order to
+// satisfy the structure. See again
+// http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes.
+// The anonymous table wrappers are inserted in LayoutNGTable::AddChild,
+// LayoutNGTableSection::AddChild, LayoutNGTableRow::AddChild and
+// LayoutObject::AddChild.
+//
+// Note that this yields to interesting issues in the insertion code. The DOM
+// code is unaware of the anonymous LayoutObjects and thus can insert
+// LayoutObjects into a different part of the layout tree. An example is:
+//
+// <!DOCTYPE html>
+// <style>
+// tablerow { display: table-row; }
+// tablecell { display: table-cell; border: 5px solid purple; }
+// </style>
+// <tablerow id="firstRow">
+//     <tablecell>Short first row.</tablecell>
+// </tablerow>
+// <tablecell id="cell">Long second row, shows the table structure.</tablecell>
+//
+// The page generates a single anonymous table (LayoutNGTable) and table row
+// group (LayoutNGTableSection) to wrap the <tablerow> (#firstRow) and an
+// anonymous table row (LayoutNGTableRow) for the second <tablecell>. It is
+// possible for JavaScript to insert a new element between these 2 <tablecell>
+// (using Node.insertBefore), requiring us to split the anonymous table (or the
+// anonymous table row group) in 2. Also note that even though the second
+// <tablecell> and <tablerow> are siblings in the DOM tree, they are not in the
+// layout tree.
+//
 // Invalidation: LayoutNGTable differences from block invalidation:
 //
 // Cached collapsed borders:
@@ -31,13 +95,25 @@
 // The validation state is a IsTableColumnsConstraintsDirty flag
 // on LayoutObject. They are invalidated inside
 // LayoutObject::SetNeeds*Layout.
-
 class CORE_EXPORT LayoutNGTable : public LayoutNGBlock,
                                   public LayoutNGTableInterface {
  public:
   explicit LayoutNGTable(Element*);
   ~LayoutNGTable() override;
 
+  static LayoutNGTable* CreateAnonymousWithParent(const LayoutObject&);
+
+  bool IsFirstCell(const LayoutNGTableCell&) const;
+  LayoutNGTableSection* FirstSection() const;
+  LayoutNGTableSection* LastSection() const;
+  LayoutNGTableSection* FirstNonEmptySection() const;
+  LayoutNGTableSection* LastNonEmptySection() const;
+  LayoutNGTableSection* NextSection(const LayoutNGTableSection*,
+                                    SkipEmptySectionsValue) const;
+  LayoutNGTableSection* PreviousSection(const LayoutNGTableSection*,
+                                        SkipEmptySectionsValue) const;
+  LayoutNGTableSection* FirstBody() const;
+
   wtf_size_t ColumnCount() const;
 
   const NGTableBorders* GetCachedTableBorders() const {
@@ -122,7 +198,6 @@
   // Whether a table has opaque foreground depends on many factors, e.g. border
   // spacing, missing cells, etc. For simplicity, just conservatively assume
   // foreground of all tables are not opaque.
-  // Copied from LayoutTable.
   bool ForegroundIsKnownToBeOpaqueInRect(
       const PhysicalRect& local_rect,
       unsigned max_depth_to_test) const override {
@@ -228,9 +303,7 @@
 // wtf/casting.h helper.
 template <>
 struct DowncastTraits<LayoutNGTable> {
-  static bool AllowFrom(const LayoutObject& object) {
-    return object.IsTable() && object.IsLayoutNGObject();
-  }
+  static bool AllowFrom(const LayoutObject& object) { return object.IsTable(); }
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.cc b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.cc
index 6274f07f5..ea9e8e4 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h"
 
-#include "third_party/blink/renderer/core/layout/layout_table.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
@@ -13,13 +12,15 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
 
 namespace blink {
 
 LayoutNGTableCaption::LayoutNGTableCaption(Element* element)
-    : LayoutNGBlockFlowMixin<LayoutTableCaption>(element) {}
+    : LayoutNGBlockFlow(element) {}
 
 // Legacy method.
+// TODO(1229581): Remove.
 void LayoutNGTableCaption::CalculateAndSetMargins(
     const NGConstraintSpace& constraint_space,
     const NGPhysicalFragment& physical_fragment) {
@@ -51,26 +52,7 @@
       containing_block_style.GetWritingDirection()));
 }
 
-void LayoutNGTableCaption::InsertedIntoTree() {
-  NOT_DESTROYED();
-  LayoutBlockFlow::InsertedIntoTree();
-
-  LayoutNGTableInterface* table_interface = TableInterface();
-  if (!table_interface->ToLayoutObject()->IsLayoutNGObject())
-    To<LayoutTable>(table_interface->ToMutableLayoutObject())->AddCaption(this);
-}
-
-void LayoutNGTableCaption::WillBeRemovedFromTree() {
-  NOT_DESTROYED();
-  LayoutBlockFlow::WillBeRemovedFromTree();
-
-  LayoutNGTableInterface* table_interface = TableInterface();
-  if (!table_interface->ToLayoutObject()->IsLayoutNGObject()) {
-    To<LayoutTable>(table_interface->ToMutableLayoutObject())
-        ->RemoveCaption(this);
-  }
-}
-
+// TODO(1229581): Remove.
 void LayoutNGTableCaption::UpdateBlockLayout(bool relayout_children) {
   NOT_DESTROYED();
 
@@ -81,9 +63,4 @@
                          result->PhysicalFragment());
 }
 
-LayoutNGTableInterface* LayoutNGTableCaption::TableInterface() const {
-  NOT_DESTROYED();
-  return ToInterface<LayoutNGTableInterface>(Parent());
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h
index f28f999..068fb219 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h
@@ -6,21 +6,13 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_TABLE_LAYOUT_NG_TABLE_CAPTION_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 
 namespace blink {
 
-class LayoutNGTableInterface;
 class NGPhysicalFragment;
 
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
-    LayoutNGBlockFlowMixin<LayoutTableCaption>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT
-    LayoutNGMixin<LayoutTableCaption>;
-
-class CORE_EXPORT LayoutNGTableCaption final
-    : public LayoutNGBlockFlowMixin<LayoutTableCaption> {
+class CORE_EXPORT LayoutNGTableCaption final : public LayoutNGBlockFlow {
  public:
   explicit LayoutNGTableCaption(Element*);
 
@@ -31,23 +23,28 @@
     return "LayoutNGTableCaption";
   }
 
+  bool CreatesNewFormattingContext() const final {
+    NOT_DESTROYED();
+    return true;
+  }
+
+  bool IsOfType(LayoutObjectType type) const override {
+    NOT_DESTROYED();
+    return type == kLayoutObjectTableCaption ||
+           LayoutNGBlockFlow::IsOfType(type);
+  }
+
  private:
   // Legacy-only API.
-  void InsertedIntoTree() override;
-  // Legacy-only API.
-  void WillBeRemovedFromTree() override;
-  // Legacy-only API.
   void CalculateAndSetMargins(const NGConstraintSpace&,
                               const NGPhysicalFragment&);
-
-  LayoutNGTableInterface* TableInterface() const;
 };
 
 // wtf/casting.h helper.
 template <>
 struct DowncastTraits<LayoutNGTableCaption> {
   static bool AllowFrom(const LayoutObject& object) {
-    return object.IsTableCaption() && object.IsLayoutNGObject();
+    return object.IsTableCaption();
   }
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.cc b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.cc
index 501b995a..bd3d4fa0 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.cc
@@ -4,9 +4,9 @@
 
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
 
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
 #include "third_party/blink/renderer/core/html/html_table_cell_element.h"
 #include "third_party/blink/renderer/core/html/table_constants.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 #include "third_party/blink/renderer/core/paint/ng/ng_table_cell_paint_invalidator.h"
 
 namespace blink {
@@ -23,6 +24,17 @@
   UpdateColAndRowSpanFlags();
 }
 
+LayoutNGTableCell* LayoutNGTableCell::CreateAnonymousWithParent(
+    const LayoutObject& parent) {
+  scoped_refptr<const ComputedStyle> new_style =
+      parent.GetDocument().GetStyleResolver().CreateAnonymousStyleWithDisplay(
+          parent.StyleRef(), EDisplay::kTableCell);
+  auto* new_cell = MakeGarbageCollected<LayoutNGTableCell>(nullptr);
+  new_cell->SetDocumentForAnonymous(&parent.GetDocument());
+  new_cell->SetStyle(std::move(new_style));
+  return new_cell;
+}
+
 void LayoutNGTableCell::InvalidateLayoutResultCacheAfterMeasure() const {
   NOT_DESTROYED();
   if (LayoutBox* row = ParentBox()) {
@@ -86,6 +98,26 @@
   return LayoutNGBlockFlowMixin<LayoutBlockFlow>::BorderRight();
 }
 
+LayoutNGTableCell* LayoutNGTableCell::NextCell() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableCell>(NextSibling());
+}
+
+LayoutNGTableCell* LayoutNGTableCell::PreviousCell() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableCell>(PreviousSibling());
+}
+
+LayoutNGTableRow* LayoutNGTableCell::Row() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableRow>(Parent());
+}
+
+LayoutNGTableSection* LayoutNGTableCell::Section() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableSection>(Parent()->Parent());
+}
+
 LayoutNGTable* LayoutNGTableCell::Table() const {
   NOT_DESTROYED();
   if (LayoutObject* parent = Parent()) {
@@ -139,7 +171,7 @@
 LayoutBox* LayoutNGTableCell::CreateAnonymousBoxWithSameTypeAs(
     const LayoutObject* parent) const {
   NOT_DESTROYED();
-  return LayoutObjectFactory::CreateAnonymousTableCellWithParent(*parent);
+  return CreateAnonymousWithParent(*parent);
 }
 
 LayoutBlock* LayoutNGTableCell::StickyContainer() const {
@@ -226,28 +258,27 @@
 
 LayoutNGTableInterface* LayoutNGTableCell::TableInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableInterface>(Parent()->Parent()->Parent());
+  return ToInterface<LayoutNGTableInterface>(Table());
 }
 
 LayoutNGTableCellInterface* LayoutNGTableCell::NextCellInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableCellInterface>(LayoutObject::NextSibling());
+  return ToInterface<LayoutNGTableCellInterface>(NextCell());
 }
 
 LayoutNGTableCellInterface* LayoutNGTableCell::PreviousCellInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableCellInterface>(
-      LayoutObject::PreviousSibling());
+  return ToInterface<LayoutNGTableCellInterface>(PreviousCell());
 }
 
 LayoutNGTableRowInterface* LayoutNGTableCell::RowInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableRowInterface>(Parent());
+  return ToInterface<LayoutNGTableRowInterface>(Row());
 }
 
 LayoutNGTableSectionInterface* LayoutNGTableCell::SectionInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableSectionInterface>(Parent()->Parent());
+  return ToInterface<LayoutNGTableSectionInterface>(Section());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h
index df8117d6..d1036648 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h
@@ -14,6 +14,8 @@
 namespace blink {
 
 class LayoutNGTable;
+class LayoutNGTableRow;
+class LayoutNGTableSection;
 
 class CORE_EXPORT LayoutNGTableCell
     : public LayoutNGBlockFlowMixin<LayoutBlockFlow>,
@@ -21,6 +23,8 @@
  public:
   explicit LayoutNGTableCell(Element*);
 
+  static LayoutNGTableCell* CreateAnonymousWithParent(const LayoutObject&);
+
   // NOTE: Rowspan might overflow section boundaries.
   unsigned ComputedRowSpan() const {
     NOT_DESTROYED();
@@ -60,6 +64,10 @@
 
   LayoutRectOutsets BorderBoxOutsets() const override;
 
+  LayoutNGTableCell* NextCell() const;
+  LayoutNGTableCell* PreviousCell() const;
+  LayoutNGTableRow* Row() const;
+  LayoutNGTableSection* Section() const;
   LayoutNGTable* Table() const;
 
   // LayoutBlockFlow methods start.
@@ -164,7 +172,7 @@
 template <>
 struct DowncastTraits<LayoutNGTableCell> {
   static bool AllowFrom(const LayoutObject& object) {
-    return object.IsTableCell() && !object.IsTableCellLegacy();
+    return object.IsTableCell();
   }
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h
index 1377def..7ce9ee9 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h
@@ -124,7 +124,7 @@
 template <>
 struct DowncastTraits<LayoutNGTableColumn> {
   static bool AllowFrom(const LayoutObject& object) {
-    return object.IsLayoutTableCol() && object.IsLayoutNGObject();
+    return object.IsLayoutTableCol();
   }
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc
index b921abe..27f133d 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.cc
@@ -4,8 +4,8 @@
 
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
 
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
 #include "third_party/blink/renderer/core/editing/position_with_affinity.h"
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
@@ -16,11 +16,47 @@
 LayoutNGTableRow::LayoutNGTableRow(Element* element)
     : LayoutNGMixin<LayoutBlock>(element) {}
 
+LayoutNGTableRow* LayoutNGTableRow::CreateAnonymousWithParent(
+    const LayoutObject& parent) {
+  scoped_refptr<const ComputedStyle> new_style =
+      parent.GetDocument().GetStyleResolver().CreateAnonymousStyleWithDisplay(
+          parent.StyleRef(), EDisplay::kTableRow);
+  auto* new_row = MakeGarbageCollected<LayoutNGTableRow>(nullptr);
+  new_row->SetDocumentForAnonymous(&parent.GetDocument());
+  new_row->SetStyle(std::move(new_style));
+  return new_row;
+}
+
 bool LayoutNGTableRow::IsEmpty() const {
   NOT_DESTROYED();
   return !FirstChild();
 }
 
+LayoutNGTableCell* LayoutNGTableRow::FirstCell() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableCell>(FirstChild());
+}
+
+LayoutNGTableCell* LayoutNGTableRow::LastCell() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableCell>(LastChild());
+}
+
+LayoutNGTableRow* LayoutNGTableRow::NextRow() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableRow>(NextSibling());
+}
+
+LayoutNGTableRow* LayoutNGTableRow::PreviousRow() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableRow>(PreviousSibling());
+}
+
+LayoutNGTableSection* LayoutNGTableRow::Section() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableSection>(Parent());
+}
+
 LayoutNGTable* LayoutNGTableRow::Table() const {
   NOT_DESTROYED();
   if (LayoutObject* section = Parent()) {
@@ -66,8 +102,7 @@
       return;
     }
 
-    LayoutBlockFlow* cell =
-        LayoutObjectFactory::CreateAnonymousTableCellWithParent(*this);
+    auto* cell = LayoutNGTableCell::CreateAnonymousWithParent(*this);
     AddChild(cell, before_child);
     cell->AddChild(child);
     return;
@@ -110,7 +145,7 @@
 LayoutBox* LayoutNGTableRow::CreateAnonymousBoxWithSameTypeAs(
     const LayoutObject* parent) const {
   NOT_DESTROYED();
-  return LayoutObjectFactory::CreateAnonymousTableRowWithParent(*parent);
+  return CreateAnonymousWithParent(*parent);
 }
 
 LayoutBlock* LayoutNGTableRow::StickyContainer() const {
@@ -149,34 +184,29 @@
   return 0;
 }
 
-LayoutNGTableCell* LayoutNGTableRow::LastCell() const {
-  NOT_DESTROYED();
-  return To<LayoutNGTableCell>(LastChild());
-}
-
 LayoutNGTableSectionInterface* LayoutNGTableRow::SectionInterface() const {
   NOT_DESTROYED();
-  return To<LayoutNGTableSection>(Parent());
+  return Section();
 }
 
 LayoutNGTableRowInterface* LayoutNGTableRow::PreviousRowInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableRowInterface>(PreviousSibling());
+  return ToInterface<LayoutNGTableRowInterface>(PreviousRow());
 }
 
 LayoutNGTableRowInterface* LayoutNGTableRow::NextRowInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableRowInterface>(NextSibling());
+  return ToInterface<LayoutNGTableRowInterface>(NextRow());
 }
 
 LayoutNGTableCellInterface* LayoutNGTableRow::FirstCellInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableCellInterface>(FirstChild());
+  return ToInterface<LayoutNGTableCellInterface>(FirstCell());
 }
 
 LayoutNGTableCellInterface* LayoutNGTableRow::LastCellInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableCellInterface>(LastChild());
+  return ToInterface<LayoutNGTableCellInterface>(LastCell());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h
index ee4fef5..a1de11f5 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h
@@ -15,18 +15,24 @@
 namespace blink {
 
 class LayoutNGTableCell;
+class LayoutNGTableSection;
 class LayoutNGTable;
 
-// NOTE:
-// Legacy table row inherits from LayoutBox, not LayoutBlock.
 // Every child of LayoutNGTableRow must be LayoutNGTableCell.
 class CORE_EXPORT LayoutNGTableRow : public LayoutNGBlock,
                                      public LayoutNGTableRowInterface {
  public:
   explicit LayoutNGTableRow(Element*);
 
+  static LayoutNGTableRow* CreateAnonymousWithParent(const LayoutObject&);
+
   bool IsEmpty() const;
 
+  LayoutNGTableCell* FirstCell() const;
+  LayoutNGTableCell* LastCell() const;
+  LayoutNGTableRow* NextRow() const;
+  LayoutNGTableRow* PreviousRow() const;
+  LayoutNGTableSection* Section() const;
   LayoutNGTable* Table() const;
 
   // LayoutBlock methods start.
@@ -59,7 +65,6 @@
   // Whether a row has opaque background depends on many factors, e.g. border
   // spacing, border collapsing, missing cells, etc.
   // For simplicity, just conservatively assume all table rows are not opaque.
-  // Copied from Legacy's LayoutTableRow
   bool ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect&,
                                          unsigned) const override {
     NOT_DESTROYED();
@@ -121,8 +126,6 @@
   // LayoutNGTableRowInterface methods end.
 
  protected:
-  LayoutNGTableCell* LastCell() const;
-
   bool IsOfType(LayoutObjectType type) const override {
     NOT_DESTROYED();
     return type == kLayoutObjectTableRow ||
@@ -134,7 +137,7 @@
 template <>
 struct DowncastTraits<LayoutNGTableRow> {
   static bool AllowFrom(const LayoutObject& object) {
-    return object.IsTableRow() && object.IsLayoutNGObject();
+    return object.IsTableRow();
   }
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.cc b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.cc
index 5bf9b2d64..9006cd1 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.cc
@@ -4,7 +4,7 @@
 
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 
-#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
 #include "third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h"
@@ -14,11 +14,32 @@
 LayoutNGTableSection::LayoutNGTableSection(Element* element)
     : LayoutNGMixin<LayoutBlock>(element) {}
 
+LayoutNGTableSection* LayoutNGTableSection::CreateAnonymousWithParent(
+    const LayoutObject& parent) {
+  scoped_refptr<const ComputedStyle> new_style =
+      parent.GetDocument().GetStyleResolver().CreateAnonymousStyleWithDisplay(
+          parent.StyleRef(), EDisplay::kTableRowGroup);
+  auto* new_section = MakeGarbageCollected<LayoutNGTableSection>(nullptr);
+  new_section->SetDocumentForAnonymous(&parent.GetDocument());
+  new_section->SetStyle(std::move(new_style));
+  return new_section;
+}
+
 bool LayoutNGTableSection::IsEmpty() const {
   NOT_DESTROYED();
   return !FirstChild();
 }
 
+LayoutNGTableRow* LayoutNGTableSection::FirstRow() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableRow>(FirstChild());
+}
+
+LayoutNGTableRow* LayoutNGTableSection::LastRow() const {
+  NOT_DESTROYED();
+  return To<LayoutNGTableRow>(LastChild());
+}
+
 LayoutNGTable* LayoutNGTableSection::Table() const {
   NOT_DESTROYED();
   return To<LayoutNGTable>(Parent());
@@ -63,8 +84,7 @@
       return;
     }
 
-    LayoutObject* row =
-        LayoutObjectFactory::CreateAnonymousTableRowWithParent(*this);
+    auto* row = LayoutNGTableRow::CreateAnonymousWithParent(*this);
     AddChild(row, before_child);
     row->AddChild(child);
     return;
@@ -105,7 +125,7 @@
 LayoutBox* LayoutNGTableSection::CreateAnonymousBoxWithSameTypeAs(
     const LayoutObject* parent) const {
   NOT_DESTROYED();
-  return LayoutObjectFactory::CreateAnonymousTableSectionWithParent(*parent);
+  return CreateAnonymousWithParent(*parent);
 }
 
 LayoutNGTableInterface* LayoutNGTableSection::TableInterface() const {
@@ -120,12 +140,12 @@
 
 LayoutNGTableRowInterface* LayoutNGTableSection::FirstRowInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableRowInterface>(FirstChild());
+  return ToInterface<LayoutNGTableRowInterface>(FirstRow());
 }
 
 LayoutNGTableRowInterface* LayoutNGTableSection::LastRowInterface() const {
   NOT_DESTROYED();
-  return ToInterface<LayoutNGTableRowInterface>(LastChild());
+  return ToInterface<LayoutNGTableRowInterface>(LastRow());
 }
 
 // TODO(crbug.com/1079133): Used by AXLayoutObject::IsDataTable, verify
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h
index ade3dbb7..d8c6dc1 100644
--- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h
+++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h
@@ -13,6 +13,7 @@
 namespace blink {
 
 class LayoutNGTable;
+class LayoutNGTableRow;
 
 // NOTE:
 // Every child of LayoutNGTableSection must be LayoutNGTableRow.
@@ -21,8 +22,12 @@
  public:
   explicit LayoutNGTableSection(Element*);
 
+  static LayoutNGTableSection* CreateAnonymousWithParent(const LayoutObject&);
+
   bool IsEmpty() const;
 
+  LayoutNGTableRow* FirstRow() const;
+  LayoutNGTableRow* LastRow() const;
   LayoutNGTable* Table() const;
 
   // LayoutBlock methods start.
@@ -58,7 +63,6 @@
   // Whether a section has opaque background depends on many factors, e.g.
   // border spacing, border collapsing, missing cells, etc. For simplicity,
   // just conservatively assume all table sections are not opaque.
-  // Copied from LayoutTableSection,
   bool ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect&,
                                          unsigned) const override {
     NOT_DESTROYED();
@@ -135,7 +139,7 @@
 template <>
 struct DowncastTraits<LayoutNGTableSection> {
   static bool AllowFrom(const LayoutObject& object) {
-    return object.IsTableSection() && object.IsLayoutNGObject();
+    return object.IsTableSection();
   }
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
index 9b167a8..80e8fcb4 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -938,9 +938,11 @@
   // subsequent fragment.
   LayoutUnit border_spacing_before_first_section = border_spacing.block_size;
 
+  LayoutUnit monolithic_overflow;
   bool is_past_table_box = false;
   if (BreakToken()) {
     previously_consumed_block_size = BreakToken()->ConsumedBlockSize();
+    monolithic_overflow = BreakToken()->MonolithicOverflow();
     incoming_table_break_data =
         DynamicTo<NGTableBreakTokenData>(BreakToken()->TokenData());
     if (incoming_table_break_data) {
@@ -1164,6 +1166,15 @@
     }
   }
 
+  bool has_entered_non_repeated_section = false;
+  if (monolithic_overflow) {
+    // If the page was overflowed by monolithic content (inside the table) on a
+    // previous page, it has to mean that we've already entered a non-repeated
+    // section, since those are the only ones that can cause fragmentation
+    // overflow.
+    has_entered_non_repeated_section = true;
+  }
+
   LayoutUnit grid_block_size_inflation;
   LayoutUnit repeated_header_block_size;
   bool broke_inside = false;
@@ -1198,6 +1209,8 @@
     LayoutUnit child_block_end_margin;  // Captions allow margins.
     absl::optional<TableBoxExtent> new_table_box_extent;
     bool is_repeated_section = false;
+    bool has_overlapping_repeated_header = false;
+
     if (child.IsTableCaption()) {
       if (!relayout_captions)
         continue;
@@ -1285,6 +1298,18 @@
           // non-repeated content (i.e. regular sections).
           offset_before_repeated_header.emplace(child_block_offset);
 
+          if (monolithic_overflow) {
+            // There's monolithic content from previous pages in the way, but we
+            // still want to place the table header at the block-start. In
+            // addition to this (probably) making sense, our implementation
+            // requires it. Once we have decided to repeat a table section, we
+            // need to be consistent about it. Take the header "out of flow",
+            // and just restore the block-offset back to
+            // offset_before_repeated_header afterwards.
+            child_block_offset = -monolithic_overflow;
+            has_overlapping_repeated_header = true;
+          }
+
           // A header will share its collapsed border with the block-start of
           // the table. However when repeated it will draw the whole border
           // itself. We need to reserve additional space at the block-start for
@@ -1372,6 +1397,9 @@
         To<NGPhysicalBoxFragment>(child_result->PhysicalFragment());
     NGBoxFragment fragment(table_writing_direction, physical_fragment);
     if (child.IsTableSection()) {
+      if (!is_repeated_section) {
+        has_entered_non_repeated_section = true;
+      }
       if (!first_baseline) {
         if (const auto& section_first_baseline = fragment.FirstBaseline())
           first_baseline = child_block_offset + *section_first_baseline;
@@ -1389,6 +1417,12 @@
         repeated_header_block_size = child_block_offset -
                                      *offset_before_repeated_header +
                                      border_spacing.block_size;
+
+        if (has_overlapping_repeated_header) {
+          // The header was taken "out of flow" and placed on top of monolithic
+          // content. Now restore the offset.
+          child_block_offset = *offset_before_repeated_header;
+        }
       }
 
       if (new_table_box_extent) {
@@ -1450,7 +1484,25 @@
     }
     DCHECK_EQ(entry.GetNode(), grouped_children.footer);
 
-    LogicalOffset offset(section_inline_offset, child_block_offset);
+    // The only case where we should allow a break before a repeatable section
+    // is when we haven't processed a non-repeated section yet (a regular TBODY,
+    // for instance). In all other cases we should make sure that the footer
+    // fits, by forcefully making room for it, if necessary. This may be
+    // necessary when there's monolithic content that overflows the current
+    // page. We'll then place the repeated footer on top of any overflowing
+    // monolithic content, at the bottom of the page. Our implementation
+    // requires that once we've started repeating a section, it needs to be
+    // present in *every* subsequent table fragment that contains parts of the
+    // table box (i.e. non-captions).
+    LayoutUnit adjusted_child_block_offset = child_block_offset;
+    if (has_entered_non_repeated_section) {
+      adjusted_child_block_offset =
+          std::min(adjusted_child_block_offset,
+                   UnclampedFragmentainerSpaceLeft(ConstraintSpace()) -
+                       repeated_footer_block_size);
+    }
+
+    LogicalOffset offset(section_inline_offset, adjusted_child_block_offset);
     NGConstraintSpace child_space = CreateSectionConstraintSpace(
         grouped_children.footer, offset.block_offset, entry.GetSectionIndex(),
         /* reserved_space */ LayoutUnit(), kMayRepeatAgain);
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor.cc b/third_party/blink/renderer/core/layout/scroll_anchor.cc
index 39afaaf..3bd9e24 100644
--- a/third_party/blink/renderer/core/layout/scroll_anchor.cc
+++ b/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -19,7 +19,6 @@
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/layout/layout_block_flow.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
 #include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
diff --git a/third_party/blink/renderer/core/layout/table_grid_cell.cc b/third_party/blink/renderer/core/layout/table_grid_cell.cc
deleted file mode 100644
index cf97bcb9..0000000
--- a/third_party/blink/renderer/core/layout/table_grid_cell.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// 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/core/layout/table_grid_cell.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-
-namespace blink {
-
-TableGridCell::TableGridCell() = default;
-
-TableGridCell::~TableGridCell() = default;
-
-void TableGridCell::Trace(Visitor* visitor) const {
-  visitor->Trace(cells_);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/table_grid_cell.h b/third_party/blink/renderer/core/layout/table_grid_cell.h
deleted file mode 100644
index 3907b82..0000000
--- a/third_party/blink/renderer/core/layout/table_grid_cell.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// 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_CORE_LAYOUT_TABLE_GRID_CELL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_GRID_CELL_H_
-
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class LayoutTableCell;
-
-// TableGridCell represents a single unit in the table grid.
-// - Without rowspan and colspan, TableGridCells and LayoutTableCells have 1:1
-//   relationship.
-// - A LayoutTableCell spanning multiple rows or effective columns can cover
-//   multiple TableGridCells.
-// - Multiple LayoutTableCells can span into the same TableGridCell, e.g.
-//    <tr><td>A</td><td rowspan="2">B</td></tr>
-//    <tr><td colspan="2">C></td></tr>
-//   both LayoutTableCell B and C cover the TableGridCell at (1,1).
-
-class TableGridCell {
-  DISALLOW_NEW();
-
- public:
-  // We can't inline the constructor and destructor because cells_ needs full
-  // definition of LayoutTableCell, and we can't include layout_table_cell.h
-  // from this file due to circular includes.
-  TableGridCell();
-  ~TableGridCell();
-  void Trace(Visitor*) const;
-
-  // This is the LayoutTableCell covering this TableGridCell that is on top of
-  // the others (aka the last LayoutTableCell in DOM order for this
-  // TableGridCell).
-  //
-  // The concept of a primary cell is dubious at most as it doesn't correspond
-  // to a DOM or rendering concept. Also callers should be careful about
-  // assumptions about it. For example, even though the primary cell is visibly
-  // the top most, it is not guaranteed to be the only one visible for this
-  // unit due to different visual overflow rectangles.
-  LayoutTableCell* PrimaryCell() {
-    return HasCells() ? cells_.back() : nullptr;
-  }
-  const LayoutTableCell* PrimaryCell() const {
-    return const_cast<TableGridCell*>(this)->PrimaryCell();
-  }
-
-  bool HasCells() const { return cells_.size() > 0; }
-
-  HeapVector<Member<LayoutTableCell>, 1>& Cells() { return cells_; }
-  const HeapVector<Member<LayoutTableCell>, 1>& Cells() const { return cells_; }
-
-  bool InColSpan() const { return in_col_span_; }
-  void SetInColSpan(bool in_col_span) { in_col_span_ = in_col_span; }
-
- private:
-  // All LayoutTableCells covering this TableGridCell.
-  // Due to colspan / rowpsan, it is possible to have overlapping cells
-  // (see class comment about an example).
-  // This Vector is sorted in DOM order.
-  HeapVector<Member<LayoutTableCell>, 1> cells_;
-
-  // True for columns after the first in a colspan.
-  bool in_col_span_ = false;
-};
-
-}  // namespace blink
-
-namespace WTF {
-
-template <>
-struct VectorTraits<blink::TableGridCell>
-    : VectorTraitsBase<blink::TableGridCell> {
-  STATIC_ONLY(VectorTraits);
-  static constexpr bool kCanClearUnusedSlotsWithMemset = true;
-};
-
-}  // namespace WTF
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_GRID_CELL_H_
diff --git a/third_party/blink/renderer/core/layout/table_layout_algorithm.h b/third_party/blink/renderer/core/layout/table_layout_algorithm.h
deleted file mode 100644
index 32f181d..0000000
--- a/third_party/blink/renderer/core/layout/table_layout_algorithm.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
- *           (C) 2002 Dirk Mueller (mueller@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_LAYOUT_ALGORITHM_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_LAYOUT_ALGORITHM_H_
-
-#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/heap/visitor.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class LayoutTable;
-
-class TableLayoutAlgorithm : public GarbageCollected<TableLayoutAlgorithm> {
- public:
-  explicit TableLayoutAlgorithm(LayoutTable* table) : table_(table) {}
-  TableLayoutAlgorithm(const TableLayoutAlgorithm&) = delete;
-  TableLayoutAlgorithm& operator=(const TableLayoutAlgorithm&) = delete;
-
-  virtual ~TableLayoutAlgorithm() = default;
-
-  virtual void ComputeIntrinsicLogicalWidths(LayoutUnit& min_width,
-                                             LayoutUnit& max_width) = 0;
-  virtual LayoutUnit ScaledWidthFromPercentColumns() { return LayoutUnit(); }
-  virtual void ApplyPreferredLogicalWidthQuirks(
-      LayoutUnit& min_width,
-      LayoutUnit& max_width) const = 0;
-  virtual void UpdateLayout() = 0;
-  virtual void WillChangeTableLayout() = 0;
-
-  virtual void Trace(Visitor* visitor) const { visitor->Trace(table_); }
-
- protected:
-  // FIXME: Once we enable SATURATED_LAYOUT_ARITHMETHIC, this should just be
-  // LayoutUnit::nearlyMax(). Until then though, using nearlyMax causes
-  // overflow in some tests, so we just pick a large number.
-  const static int kTableMaxWidth = 1000000;
-
-  Member<LayoutTable> table_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_LAYOUT_ALGORITHM_H_
diff --git a/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc b/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
deleted file mode 100644
index 584c5e80..0000000
--- a/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
- *           (C) 2002 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006, 2008, 2010 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "third_party/blink/renderer/core/layout/table_layout_algorithm_auto.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_interface.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h"
-#include "third_party/blink/renderer/core/layout/text_autosizer.h"
-#include "third_party/blink/renderer/platform/geometry/calculation_value.h"
-
-namespace blink {
-
-TableLayoutAlgorithmAuto::TableLayoutAlgorithmAuto(LayoutTable* table)
-    : TableLayoutAlgorithm(table),
-      has_percent_(false),
-      effective_logical_width_dirty_(true),
-      scaled_width_from_percent_columns_() {}
-
-TableLayoutAlgorithmAuto::~TableLayoutAlgorithmAuto() = default;
-
-void TableLayoutAlgorithmAuto::RecalcColumn(unsigned eff_col) {
-  Layout& column_layout = layout_struct_[eff_col];
-
-  LayoutTableCell* fixed_contributor = nullptr;
-  LayoutTableCell* max_contributor = nullptr;
-
-  for (LayoutObject* child = table_->Children()->FirstChild(); child;
-       child = child->NextSibling()) {
-    if (child->IsLayoutTableCol()) {
-      // LayoutTableCols don't have the concept of preferred logical width, but
-      // we need to clear their dirty bits so that if we call
-      // setPreferredWidthsDirty(true) on a col or one of its descendants, we'll
-      // mark it's ancestors as dirty.
-      To<LayoutTableCol>(child)->ClearIntrinsicLogicalWidthsDirtyBits();
-    } else if (child->IsTableSection()) {
-      LayoutTableSection* section = To<LayoutTableSection>(child);
-      unsigned num_rows = section->NumRows();
-      for (unsigned i = 0; i < num_rows; i++) {
-        if (eff_col >= section->NumCols(i))
-          continue;
-        auto& grid_cell = section->GridCellAt(i, eff_col);
-        LayoutTableCell* cell = grid_cell.PrimaryCell();
-
-        if (grid_cell.InColSpan() || !cell)
-          continue;
-        column_layout.column_has_no_cells = false;
-
-        MinMaxSizes cell_preferred_logical_widths =
-            cell->PreferredLogicalWidths();
-
-        if (cell_preferred_logical_widths.max_size)
-          column_layout.empty_cells_only = false;
-
-        if (cell->ColSpan() == 1) {
-          column_layout.min_logical_width =
-              std::max<int>(cell_preferred_logical_widths.min_size.ToInt(),
-                            column_layout.min_logical_width);
-          if (cell_preferred_logical_widths.max_size >
-              column_layout.max_logical_width) {
-            column_layout.max_logical_width =
-                cell_preferred_logical_widths.max_size.ToInt();
-            max_contributor = cell;
-          }
-
-          // All browsers implement a size limit on the cell's max width.
-          // Our limit is based on KHTML's representation that used 16 bits
-          // widths.
-          // FIXME: Other browsers have a lower limit for the cell's max width.
-          const int kCCellMaxWidth = 32760;
-          Length cell_logical_width = cell->StyleOrColLogicalWidth();
-          // A calculated width that mixes lengths and percentages in fixed
-          // table layout must be treated as 'auto'.
-          // https://drafts.csswg.org/css-values-4/#calc-computed-value
-          if (cell_logical_width.IsCalculated()) {
-            const CalculationValue& calc =
-                cell_logical_width.GetCalculationValue();
-            if (!calc.IsExpression() && !calc.Pixels()) {
-              cell_logical_width = Length::Percent(calc.Percent());
-            } else {
-              cell_logical_width = Length();  // Make it Auto
-            }
-          }
-          if (cell_logical_width.Value() > kCCellMaxWidth)
-            cell_logical_width = Length::Fixed(kCCellMaxWidth);
-          if (cell_logical_width.IsNegative())
-            cell_logical_width = Length::Fixed(0);
-          switch (cell_logical_width.GetType()) {
-            case Length::kFixed:
-              // ignore width=0
-              if (cell_logical_width.IsPositive() &&
-                  !column_layout.logical_width.IsPercentOrCalc()) {
-                int logical_width =
-                    cell->AdjustBorderBoxLogicalWidthForBoxSizing(
-                            cell_logical_width.Value())
-                        .ToInt();
-                if (column_layout.logical_width.IsFixed()) {
-                  // Nav/IE weirdness
-                  if ((logical_width > column_layout.logical_width.Value()) ||
-                      ((column_layout.logical_width.Value() == logical_width) &&
-                       (max_contributor == cell))) {
-                    column_layout.logical_width = Length::Fixed(logical_width);
-                    fixed_contributor = cell;
-                  }
-                } else {
-                  column_layout.logical_width = Length::Fixed(logical_width);
-                  fixed_contributor = cell;
-                }
-              }
-              break;
-            case Length::kPercent:
-              has_percent_ = true;
-              // TODO(alancutter): Make this work correctly for calc lengths.
-              if (cell_logical_width.IsPositive() &&
-                  (!column_layout.logical_width.IsPercentOrCalc() ||
-                   cell_logical_width.Value() >
-                       column_layout.logical_width.Value()))
-                column_layout.logical_width = cell_logical_width;
-              break;
-            default:
-              break;
-          }
-        } else if (!eff_col || section->PrimaryCellAt(i, eff_col - 1) != cell) {
-          // If a cell originates in this spanning column ensure we have a
-          // min/max width of at least 1px for it.
-          column_layout.min_logical_width =
-              std::max<int>(column_layout.min_logical_width,
-                            cell_preferred_logical_widths.max_size ? 1 : 0);
-
-          // This spanning cell originates in this column. Insert the cell into
-          // spanning cells list.
-          InsertSpanCell(cell);
-        }
-      }
-    }
-  }
-
-  // Nav/IE weirdness
-  if (column_layout.logical_width.IsFixed()) {
-    if (table_->GetDocument().InQuirksMode() &&
-        column_layout.max_logical_width > column_layout.logical_width.Value() &&
-        fixed_contributor != max_contributor) {
-      column_layout.logical_width = Length();
-      fixed_contributor = nullptr;
-    }
-  }
-
-  column_layout.max_logical_width = std::max(column_layout.max_logical_width,
-                                             column_layout.min_logical_width);
-}
-
-void TableLayoutAlgorithmAuto::FullRecalc() {
-  has_percent_ = false;
-  effective_logical_width_dirty_ = true;
-
-  unsigned n_eff_cols = table_->NumEffectiveColumns();
-  layout_struct_.resize(n_eff_cols);
-  layout_struct_.Fill(Layout());
-  span_cells_.clear();
-
-  Length group_logical_width;
-  unsigned current_column = 0;
-  for (LayoutTableCol* column = table_->FirstColumn(); column;
-       column = column->NextColumn()) {
-    if (column->IsTableColumnGroupWithColumnChildren()) {
-      group_logical_width = column->StyleRef().LogicalWidth();
-    } else {
-      Length col_logical_width = column->StyleRef().LogicalWidth();
-      if (col_logical_width.IsCalculated() || col_logical_width.IsAuto())
-        col_logical_width = group_logical_width;
-      // TODO(alancutter): Make this work correctly for calc lengths.
-      if ((col_logical_width.IsFixed() ||
-           col_logical_width.IsPercentOrCalc()) &&
-          col_logical_width.IsZero())
-        col_logical_width = Length();
-      unsigned eff_col =
-          table_->AbsoluteColumnToEffectiveColumn(current_column);
-      unsigned span = column->Span();
-      if (!col_logical_width.IsAuto() && span == 1 && eff_col < n_eff_cols &&
-          table_->SpanOfEffectiveColumn(eff_col) == 1) {
-        layout_struct_[eff_col].logical_width = col_logical_width;
-        if (col_logical_width.IsFixed() &&
-            layout_struct_[eff_col].max_logical_width <
-                col_logical_width.Value())
-          layout_struct_[eff_col].max_logical_width = col_logical_width.Value();
-      }
-      current_column += span;
-    }
-
-    // For the last column in a column-group, we invalidate our group logical
-    // width.
-    if (column->IsTableColumn() && !column->NextSibling())
-      group_logical_width = Length();
-  }
-
-  for (unsigned i = 0; i < n_eff_cols; i++)
-    RecalcColumn(i);
-}
-
-static bool ShouldScaleColumnsForParent(LayoutTable* table) {
-  LayoutBlock* cb = table->ContainingBlock();
-  // TODO(layout-dev): We can probably abort before reaching LayoutView in many
-  // cases. For example, if we find an object with contain:size, or even if we
-  // find a regular block with fixed logical width.
-  while (!IsA<LayoutView>(cb)) {
-    // It doesn't matter if our table is auto or fixed: auto means we don't
-    // scale. Fixed doesn't care if we do or not because it doesn't depend
-    // on the cell contents' preferred widths.
-    if (cb->IsTableCell())
-      return false;
-    // The max logical width of a table may be "infinity" (or kTableMaxWidth, to
-    // be more exact) if the sum of the columns' percentages is 100% or more,
-    // AND there is at least one column that has a non-percentage-based positive
-    // logical width. In such situations no table logical width will be large
-    // enough to satisfy the constraint set by the contents. So the idea is to
-    // use ~infinity to make sure we use all available size in the containing
-    // block. However, this just doesn't work if this is a flex or grid item, so
-    // disallow scaling in that case.
-    const bool is_deprecated_webkit_box =
-        cb->StyleRef().IsDeprecatedWebkitBox();
-    if ((!is_deprecated_webkit_box && cb->IsFlexibleBoxIncludingNG()) ||
-        cb->IsLayoutNGGrid()) {
-      return false;
-    }
-    cb = cb->ContainingBlock();
-  }
-  return true;
-}
-
-// FIXME: This needs to be adapted for vertical writing modes.
-static bool ShouldScaleColumnsForSelf(LayoutNGTableInterface* table) {
-  // Normally, scale all columns to satisfy this from CSS2.2:
-  // "A percentage value for a column width is relative to the table width.
-  // If the table has 'width: auto', a percentage represents a constraint on the
-  // column's width"
-
-  // A special case.  If this table is not fixed width and contained inside
-  // a cell, then don't bloat the maxwidth by examining percentage growth.
-  while (true) {
-    const LayoutObject* layout_table = table->ToLayoutObject();
-    const Length& tw = layout_table->StyleRef().Width();
-    if ((!tw.IsAuto() && !tw.IsPercentOrCalc()) ||
-        layout_table->IsOutOfFlowPositioned())
-      return true;
-    LayoutBlock* cb = layout_table->ContainingBlock();
-
-    while (!IsA<LayoutView>(cb) && !cb->IsTableCell() &&
-           cb->StyleRef().Width().IsAuto() && !cb->IsOutOfFlowPositioned())
-      cb = cb->ContainingBlock();
-
-    // TODO(dgrogan): Should the second clause check for isFixed() instead?
-    if (!cb->IsTableCell() || (!cb->StyleRef().Width().IsAuto() &&
-                               !cb->StyleRef().Width().IsPercentOrCalc()))
-      return true;
-
-    LayoutNGTableCellInterface* cell =
-        ToInterface<LayoutNGTableCellInterface>(cb);
-    table = cell->TableInterface();
-    const Length& table_logical_width =
-        table->ToLayoutObject()->StyleRef().LogicalWidth();
-    bool width_is_auto = (!table_logical_width.IsSpecified() ||
-                          !table_logical_width.IsPositive()) &&
-                         !table_logical_width.IsContentOrIntrinsic();
-    if (cell->ColSpan() > 1 || width_is_auto)
-      return false;
-  }
-  NOTREACHED();
-  return true;
-}
-
-void TableLayoutAlgorithmAuto::ComputeIntrinsicLogicalWidths(
-    LayoutUnit& min_width,
-    LayoutUnit& max_width) {
-  TextAutosizer::TableLayoutScope text_autosizer_table_layout_scope(table_);
-
-  FullRecalc();
-
-  int span_max_logical_width = CalcEffectiveLogicalWidth();
-  min_width = LayoutUnit();
-  max_width = LayoutUnit();
-  float max_percent = 0;
-  float max_non_percent = 0;
-  bool scale_columns_for_self = ShouldScaleColumnsForSelf(table_);
-
-  float remaining_percent = 100;
-  for (wtf_size_t i = 0; i < layout_struct_.size(); ++i) {
-    min_width += layout_struct_[i].effective_min_logical_width;
-    max_width += layout_struct_[i].effective_max_logical_width;
-    if (scale_columns_for_self) {
-      if (layout_struct_[i].effective_logical_width.IsPercentOrCalc()) {
-        float percent =
-            std::min(static_cast<float>(
-                         layout_struct_[i].effective_logical_width.Percent()),
-                     remaining_percent);
-        // When percent columns meet or exceed 100% and there are remaining
-        // columns, the other browsers (FF, Edge) use an artificially high max
-        // width, so we do too. Instead of division by zero, logical_width and
-        // max_non_percent are set to kTableMaxWidth. Issue:
-        // https://github.com/w3c/csswg-drafts/issues/1501
-        float logical_width =
-            (percent > 0) ? static_cast<float>(
-                                layout_struct_[i].effective_max_logical_width) *
-                                100 / percent
-                          : kTableMaxWidth;
-        max_percent = std::max(logical_width, max_percent);
-        remaining_percent -= percent;
-      } else {
-        max_non_percent += layout_struct_[i].effective_max_logical_width;
-      }
-    }
-  }
-
-  if (scale_columns_for_self) {
-    if (max_non_percent != 0) {
-      max_non_percent = (remaining_percent > 0)
-                            ? max_non_percent * 100 / remaining_percent
-                            : kTableMaxWidth;
-    }
-    scaled_width_from_percent_columns_ =
-        std::min(LayoutUnit(kTableMaxWidth),
-                 LayoutUnit(std::max(max_percent, max_non_percent)));
-    if (scaled_width_from_percent_columns_ > max_width &&
-        ShouldScaleColumnsForParent(table_))
-      max_width = scaled_width_from_percent_columns_;
-  }
-
-  max_width = LayoutUnit(std::max(max_width.Floor(), span_max_logical_width));
-}
-
-void TableLayoutAlgorithmAuto::ApplyPreferredLogicalWidthQuirks(
-    LayoutUnit& min_width,
-    LayoutUnit& max_width) const {
-  const Length& table_logical_width = table_->StyleRef().LogicalWidth();
-  if (table_logical_width.IsFixed() && table_logical_width.IsPositive()) {
-    // |minWidth| is the result of measuring the intrinsic content's size. Keep
-    // it to make sure we are *never* smaller than the actual content.
-    LayoutUnit min_content_width = min_width;
-    // FIXME: This line looks REALLY suspicious as it could allow the minimum
-    // preferred logical width to be smaller than the table content. This has
-    // to be cross-checked against other browsers.
-    min_width = max_width = LayoutUnit(
-        std::max<int>(min_width.Floor(), table_logical_width.Value()));
-
-    const Length& style_max_logical_width =
-        table_->StyleRef().LogicalMaxWidth();
-    if (style_max_logical_width.IsFixed() &&
-        !style_max_logical_width.IsNegative()) {
-      min_width = LayoutUnit(
-          std::min<int>(min_width.Floor(), style_max_logical_width.Value()));
-      min_width = std::max(min_width, min_content_width);
-      max_width = min_width;
-    }
-  }
-}
-
-/*
-  This method takes care of colspans.
-  effWidth is the same as width for cells without colspans. If we have colspans,
-  they get modified.
- */
-int TableLayoutAlgorithmAuto::CalcEffectiveLogicalWidth() {
-  int max_logical_width = 0;
-
-  wtf_size_t n_eff_cols = layout_struct_.size();
-  int16_t spacing_in_row_direction = table_->HBorderSpacing();
-
-  for (wtf_size_t i = 0; i < n_eff_cols; ++i) {
-    layout_struct_[i].effective_logical_width = layout_struct_[i].logical_width;
-    layout_struct_[i].effective_min_logical_width =
-        layout_struct_[i].min_logical_width;
-    layout_struct_[i].effective_max_logical_width =
-        layout_struct_[i].max_logical_width;
-  }
-
-  for (wtf_size_t i = 0; i < span_cells_.size(); ++i) {
-    LayoutTableCell* cell = span_cells_[i];
-    if (!cell)
-      break;
-
-    unsigned span = cell->ColSpan();
-
-    Length cell_logical_width = cell->StyleOrColLogicalWidth();
-    if (cell_logical_width.IsZero() || cell_logical_width.IsCalculated())
-      cell_logical_width = Length();  // Make it Auto
-
-    unsigned eff_col =
-        table_->AbsoluteColumnToEffectiveColumn(cell->AbsoluteColumnIndex());
-    wtf_size_t last_col = eff_col;
-    MinMaxSizes cell_preferred_logical_widths = cell->PreferredLogicalWidths();
-    int cell_min_logical_width =
-        (cell_preferred_logical_widths.min_size + spacing_in_row_direction)
-            .ToInt();
-    int cell_max_logical_width =
-        (cell_preferred_logical_widths.max_size + spacing_in_row_direction)
-            .ToInt();
-    float total_percent = 0;
-    int span_min_logical_width = 0;
-    int span_max_logical_width = 0;
-    bool all_cols_are_percent = true;
-    bool all_cols_are_fixed = true;
-    bool have_auto = false;
-    bool span_has_empty_cells_only = true;
-    int fixed_width = 0;
-    while (last_col < n_eff_cols && span > 0) {
-      Layout& column_layout = layout_struct_[last_col];
-      switch (column_layout.logical_width.GetType()) {
-        case Length::kPercent:
-          total_percent += column_layout.logical_width.Percent();
-          all_cols_are_fixed = false;
-          break;
-        case Length::kFixed:
-          if (column_layout.logical_width.Value() > 0) {
-            fixed_width += column_layout.logical_width.Value();
-            all_cols_are_percent = false;
-            // IE resets effWidth to Auto here, but this breaks the konqueror
-            // about page and seems to be some bad legacy behaviour anyway.
-            // mozilla doesn't do this so I decided we don't neither.
-            break;
-          }
-          [[fallthrough]];
-        case Length::kAuto:
-          have_auto = true;
-          [[fallthrough]];
-        default:
-          // If the column is a percentage width, do not let the spanning cell
-          // overwrite the width value.  This caused a mis-layout on amazon.com.
-          // Sample snippet:
-          // <table border=2 width=100%><
-          //   <tr><td>1</td><td colspan=2>2-3</tr>
-          //   <tr><td>1</td><td colspan=2 width=100%>2-3</td></tr>
-          // </table>
-          // TODO(alancutter): Make this work correctly for calc lengths.
-          if (!column_layout.effective_logical_width.IsPercentOrCalc()) {
-            column_layout.effective_logical_width = Length();
-            all_cols_are_percent = false;
-          } else {
-            total_percent += column_layout.effective_logical_width.Percent();
-          }
-          all_cols_are_fixed = false;
-      }
-      if (!column_layout.empty_cells_only)
-        span_has_empty_cells_only = false;
-      span -= table_->SpanOfEffectiveColumn(last_col);
-      span_min_logical_width += column_layout.effective_min_logical_width;
-      span_max_logical_width += column_layout.effective_max_logical_width;
-      last_col++;
-      cell_min_logical_width -= spacing_in_row_direction;
-      cell_max_logical_width -= spacing_in_row_direction;
-    }
-
-    // adjust table max width if needed
-    if (cell_logical_width.IsPercentOrCalc()) {
-      if (total_percent >= cell_logical_width.Percent() ||
-          all_cols_are_percent) {
-        // can't satisfy this condition, treat as variable
-        cell_logical_width = Length();
-      } else {
-        max_logical_width =
-            std::max(max_logical_width,
-                     static_cast<int>(std::max(span_max_logical_width,
-                                               cell_max_logical_width) *
-                                      100 / cell_logical_width.Percent()));
-
-        // all non percent columns in the span get percent values to sum up
-        // correctly.
-        float percent_missing = cell_logical_width.Percent() - total_percent;
-        int total_width = 0;
-        for (unsigned pos = eff_col; pos < last_col; ++pos) {
-          if (!layout_struct_[pos].effective_logical_width.IsPercentOrCalc())
-            total_width +=
-                layout_struct_[pos].ClampedEffectiveMaxLogicalWidth();
-        }
-
-        for (unsigned pos = eff_col; pos < last_col && total_width > 0; ++pos) {
-          if (!layout_struct_[pos].effective_logical_width.IsPercentOrCalc()) {
-            float percent =
-                percent_missing *
-                static_cast<float>(
-                    layout_struct_[pos].effective_max_logical_width) /
-                total_width;
-            total_width -=
-                layout_struct_[pos].ClampedEffectiveMaxLogicalWidth();
-            percent_missing -= percent;
-            layout_struct_[pos].effective_logical_width =
-                percent > 0 ? Length::Percent(percent) : Length();
-          }
-        }
-      }
-    }
-
-    // make sure minWidth and maxWidth of the spanning cell are honoured
-    if (cell_min_logical_width > span_min_logical_width) {
-      if (all_cols_are_fixed) {
-        for (unsigned pos = eff_col; fixed_width > 0 && pos < last_col; ++pos) {
-          int col_logical_width = std::max(
-              layout_struct_[pos].effective_min_logical_width,
-              static_cast<int>(cell_min_logical_width *
-                               layout_struct_[pos].logical_width.Value() /
-                               fixed_width));
-          fixed_width -= layout_struct_[pos].logical_width.Value();
-          cell_min_logical_width -= col_logical_width;
-          layout_struct_[pos].effective_min_logical_width = col_logical_width;
-        }
-      } else if (all_cols_are_percent) {
-        // In this case, we just split the colspan's min amd max widths
-        // following the percentage.
-        int allocated_min_logical_width = 0;
-        int allocated_max_logical_width = 0;
-        for (unsigned pos = eff_col; pos < last_col; ++pos) {
-          // TODO(alancutter): Make this work correctly for calc lengths.
-          DCHECK(layout_struct_[pos].logical_width.IsPercentOrCalc() ||
-                 layout_struct_[pos].effective_logical_width.IsPercentOrCalc());
-          // |allColsArePercent| means that either the logicalWidth *or* the
-          // effectiveLogicalWidth are percents, handle both of them here.
-          float percent =
-              layout_struct_[pos].logical_width.IsPercentOrCalc()
-                  ? layout_struct_[pos].logical_width.Percent()
-                  : layout_struct_[pos].effective_logical_width.Percent();
-          int column_min_logical_width = static_cast<int>(
-              percent * cell_min_logical_width / total_percent);
-          int column_max_logical_width = static_cast<int>(
-              percent * cell_max_logical_width / total_percent);
-          layout_struct_[pos].effective_min_logical_width =
-              std::max(layout_struct_[pos].effective_min_logical_width,
-                       column_min_logical_width);
-          column_max_logical_width =
-              std::max(column_max_logical_width, column_min_logical_width);
-          layout_struct_[pos].effective_max_logical_width =
-              std::max(layout_struct_[pos].effective_max_logical_width,
-                       column_max_logical_width);
-          allocated_min_logical_width += column_min_logical_width;
-          allocated_max_logical_width += column_max_logical_width;
-        }
-        DCHECK_LE(allocated_min_logical_width, cell_min_logical_width);
-        DCHECK_LE(allocated_max_logical_width, cell_max_logical_width);
-        cell_min_logical_width -= allocated_min_logical_width;
-        cell_max_logical_width -= allocated_max_logical_width;
-      } else {
-        int remaining_max_logical_width = span_max_logical_width;
-        int remaining_min_logical_width = span_min_logical_width;
-
-        // Give min to variable first, to fixed second, and to others third.
-        for (unsigned pos = eff_col;
-             remaining_max_logical_width >= 0 && pos < last_col; ++pos) {
-          if (layout_struct_[pos].logical_width.IsFixed() && have_auto &&
-              fixed_width <= cell_min_logical_width) {
-            int col_min_logical_width =
-                std::max<int>(layout_struct_[pos].effective_min_logical_width,
-                              layout_struct_[pos].logical_width.Value());
-            fixed_width -= layout_struct_[pos].logical_width.Value();
-            remaining_min_logical_width -=
-                layout_struct_[pos].effective_min_logical_width;
-            remaining_max_logical_width -=
-                layout_struct_[pos].effective_max_logical_width;
-            cell_min_logical_width -= col_min_logical_width;
-            layout_struct_[pos].effective_min_logical_width =
-                col_min_logical_width;
-          }
-        }
-
-        for (unsigned pos = eff_col;
-             remaining_max_logical_width >= 0 && pos < last_col &&
-             remaining_min_logical_width < cell_min_logical_width;
-             ++pos) {
-          if (!(layout_struct_[pos].logical_width.IsFixed() && have_auto &&
-                fixed_width <= cell_min_logical_width)) {
-            int col_min_logical_width = std::max<int>(
-                layout_struct_[pos].effective_min_logical_width,
-                static_cast<int>(
-                    remaining_max_logical_width
-                        ? cell_min_logical_width *
-                              static_cast<float>(
-                                  layout_struct_[pos]
-                                      .effective_max_logical_width) /
-                              remaining_max_logical_width
-                        : cell_min_logical_width));
-            col_min_logical_width = std::min<int>(
-                layout_struct_[pos].effective_min_logical_width +
-                    (cell_min_logical_width - remaining_min_logical_width),
-                col_min_logical_width);
-            remaining_max_logical_width -=
-                layout_struct_[pos].effective_max_logical_width;
-            remaining_min_logical_width -=
-                layout_struct_[pos].effective_min_logical_width;
-            cell_min_logical_width -= col_min_logical_width;
-            layout_struct_[pos].effective_min_logical_width =
-                col_min_logical_width;
-          }
-        }
-      }
-    }
-    if (!cell_logical_width.IsPercentOrCalc()) {
-      if (cell_max_logical_width > span_max_logical_width) {
-        for (unsigned pos = eff_col;
-             span_max_logical_width >= 0 && pos < last_col; ++pos) {
-          int col_max_logical_width = std::max(
-              layout_struct_[pos].effective_max_logical_width,
-              static_cast<int>(span_max_logical_width
-                                   ? cell_max_logical_width *
-                                         static_cast<float>(
-                                             layout_struct_[pos]
-                                                 .effective_max_logical_width) /
-                                         span_max_logical_width
-                                   : cell_max_logical_width));
-          span_max_logical_width -=
-              layout_struct_[pos].effective_max_logical_width;
-          cell_max_logical_width -= col_max_logical_width;
-          layout_struct_[pos].effective_max_logical_width =
-              col_max_logical_width;
-        }
-      }
-    } else {
-      for (unsigned pos = eff_col; pos < last_col; ++pos)
-        layout_struct_[pos].max_logical_width =
-            std::max(layout_struct_[pos].max_logical_width,
-                     layout_struct_[pos].min_logical_width);
-    }
-    // treat span ranges consisting of empty cells only as if they had content
-    if (span_has_empty_cells_only) {
-      for (unsigned pos = eff_col; pos < last_col; ++pos)
-        layout_struct_[pos].empty_cells_only = false;
-    }
-  }
-  effective_logical_width_dirty_ = false;
-
-  return std::min(max_logical_width, INT_MAX / 2);
-}
-
-/* gets all cells that originate in a column and have a cellspan > 1
-   Sorts them by increasing cellspan
-*/
-void TableLayoutAlgorithmAuto::InsertSpanCell(LayoutTableCell* cell) {
-  DCHECK(cell);
-  DCHECK_NE(cell->ColSpan(), 1u);
-  if (!cell || cell->ColSpan() == 1)
-    return;
-
-  unsigned size = span_cells_.size();
-  if (!size || span_cells_[size - 1] != 0) {
-    span_cells_.Grow(size + 10);
-    for (unsigned i = 0; i < 10; i++)
-      span_cells_[size + i] = nullptr;
-    size += 10;
-  }
-
-  // Add them in sort. This is a slow algorithm, and a binary search or a fast
-  // sorting after collection would be better.
-  unsigned pos = 0;
-  unsigned span = cell->ColSpan();
-  while (pos < span_cells_.size() && span_cells_[pos] &&
-         span > span_cells_[pos]->ColSpan())
-    pos++;
-  memmove(span_cells_.data() + pos + 1, span_cells_.data() + pos,
-          (size - pos - 1) * sizeof(decltype(span_cells_)::value_type));
-  span_cells_[pos] = cell;
-}
-
-void TableLayoutAlgorithmAuto::UpdateLayout() {
-  // table layout based on the values collected in the layout structure.
-  int table_logical_width = (table_->LogicalWidth() -
-                             table_->BordersPaddingAndSpacingInRowDirection())
-                                .ToInt();
-  int available = table_logical_width;
-  unsigned n_eff_cols = table_->NumEffectiveColumns();
-
-  // FIXME: It is possible to be called without having properly updated our
-  // internal representation.  This means that our preferred logical widths were
-  // not recomputed as expected.
-  if (n_eff_cols != layout_struct_.size()) {
-    FullRecalc();
-    // FIXME: Table layout shouldn't modify our table structure (but does due to
-    // columns and column-groups).
-    n_eff_cols = table_->NumEffectiveColumns();
-  }
-
-  if (effective_logical_width_dirty_)
-    CalcEffectiveLogicalWidth();
-
-  bool have_percent = false;
-  int num_auto = 0;
-  int num_fixed = 0;
-  float total_auto = 0;
-  float total_fixed = 0;
-  float total_percent = 0;
-  int alloc_auto = 0;
-  unsigned num_auto_empty_cells_only = 0;
-
-  // fill up every cell with its minWidth
-  for (unsigned i = 0; i < n_eff_cols; ++i) {
-    int cell_logical_width = layout_struct_[i].effective_min_logical_width;
-    layout_struct_[i].computed_logical_width = cell_logical_width;
-    available -= cell_logical_width;
-    Length& logical_width = layout_struct_[i].effective_logical_width;
-    switch (logical_width.GetType()) {
-      case Length::kPercent:
-        have_percent = true;
-        total_percent += logical_width.Percent();
-        break;
-      case Length::kFixed:
-        num_fixed++;
-        total_fixed += layout_struct_[i].ClampedEffectiveMaxLogicalWidth();
-        // fall through
-        break;
-      case Length::kAuto:
-        if (layout_struct_[i].empty_cells_only) {
-          num_auto_empty_cells_only++;
-        } else {
-          num_auto++;
-          total_auto += layout_struct_[i].ClampedEffectiveMaxLogicalWidth();
-        }
-        if (!layout_struct_[i].column_has_no_cells)
-          alloc_auto += cell_logical_width;
-        break;
-      default:
-        break;
-    }
-  }
-
-  // allocate width to percent cols
-  if (available > 0 && have_percent) {
-    for (unsigned i = 0; i < n_eff_cols; ++i) {
-      Length& logical_width = layout_struct_[i].effective_logical_width;
-      if (logical_width.IsPercentOrCalc()) {
-        int cell_logical_width =
-            std::max<int>(layout_struct_[i].effective_min_logical_width,
-                          MinimumValueForLength(logical_width,
-                                                LayoutUnit(table_logical_width))
-                              .ToInt());
-        available +=
-            layout_struct_[i].computed_logical_width - cell_logical_width;
-        layout_struct_[i].computed_logical_width = cell_logical_width;
-      }
-    }
-    if (total_percent > 100) {
-      // remove overallocated space from the last columns
-      int excess = table_logical_width * (total_percent - 100) / 100;
-      for (unsigned i = n_eff_cols; i;) {
-        --i;
-        if (layout_struct_[i].effective_logical_width.IsPercentOrCalc()) {
-          int cell_logical_width = layout_struct_[i].computed_logical_width;
-          int reduction = std::min(cell_logical_width, excess);
-          // The lines below might look inconsistent, but that's the way it's
-          // handled in mozilla.
-          excess -= reduction;
-          int new_logical_width =
-              std::max<int>(layout_struct_[i].effective_min_logical_width,
-                            cell_logical_width - reduction);
-          available += cell_logical_width - new_logical_width;
-          layout_struct_[i].computed_logical_width = new_logical_width;
-        }
-      }
-    }
-  }
-
-  // then allocate width to fixed cols
-  if (available > 0) {
-    for (unsigned i = 0; i < n_eff_cols; ++i) {
-      Length& logical_width = layout_struct_[i].effective_logical_width;
-      if (logical_width.IsFixed() &&
-          logical_width.Value() > layout_struct_[i].computed_logical_width) {
-        available +=
-            layout_struct_[i].computed_logical_width - logical_width.Value();
-        layout_struct_[i].computed_logical_width = logical_width.Value();
-      }
-    }
-  }
-
-  // Give each auto width column its share of the available width, non-empty
-  // columns then empty columns.
-  if (available > 0 && (num_auto || num_auto_empty_cells_only)) {
-    available += alloc_auto;
-    if (num_auto) {
-      DistributeWidthToColumns<float, Length::kAuto, kNonEmptyCells,
-                               kInitialWidth, kStartToEnd>(available,
-                                                           total_auto);
-    }
-    if (num_auto_empty_cells_only) {
-      DistributeWidthToColumns<unsigned, Length::kAuto, kEmptyCells,
-                               kInitialWidth, kStartToEnd>(
-          available, num_auto_empty_cells_only);
-    }
-  }
-
-  // Any remaining available width expands fixed width, percent width, and
-  // non-empty auto width columns, in that order.
-  if (available > 0 && num_fixed) {
-    DistributeWidthToColumns<float, Length::kFixed, kAllCells, kExtraWidth,
-                             kStartToEnd>(available, total_fixed);
-  }
-
-  if (available > 0 && has_percent_ && total_percent < 100) {
-    DistributeWidthToColumns<float, Length::kPercent, kAllCells, kExtraWidth,
-                             kStartToEnd>(available, total_percent);
-  }
-
-  if (available > 0 && n_eff_cols > num_auto_empty_cells_only) {
-    unsigned total = n_eff_cols - num_auto_empty_cells_only;
-    // Starting from the last cell is for compatibility with FF/IE - it isn't
-    // specified anywhere.
-    DistributeWidthToColumns<unsigned, Length::kAuto, kNonEmptyCells,
-                             kLeftoverWidth, kEndToStart>(available, total);
-  }
-
-  // If we have overallocated, reduce every cell according to the difference
-  // between desired width and minwidth. This seems to produce to the pixel
-  // exact results with IE. Wonder is some of this also holds for width
-  // distributing. This is basically the reverse of how we grew the cells.
-  if (available < 0)
-    ShrinkColumnWidth(Length::kAuto, available);
-  if (available < 0)
-    ShrinkColumnWidth(Length::kFixed, available);
-  if (available < 0)
-    ShrinkColumnWidth(Length::kPercent, available);
-
-  DCHECK_EQ(table_->EffectiveColumnPositions().size(), n_eff_cols + 1);
-  int pos = 0;
-  for (unsigned i = 0; i < n_eff_cols; ++i) {
-    table_->SetEffectiveColumnPosition(i, pos);
-    pos += layout_struct_[i].computed_logical_width + table_->HBorderSpacing();
-  }
-  // The extra position is for the imaginary column after the last column.
-  table_->SetEffectiveColumnPosition(n_eff_cols, pos);
-}
-
-template <typename Total,
-          Length::Type lengthType,
-          TableLayoutAlgorithmAuto::CellsToProcess cellsToProcess,
-          TableLayoutAlgorithmAuto::DistributionMode distributionMode,
-          TableLayoutAlgorithmAuto::DistributionDirection distributionDirection>
-void TableLayoutAlgorithmAuto::DistributeWidthToColumns(int& available,
-                                                        Total total) {
-  // TODO(alancutter): Make this work correctly for calc lengths.
-  int n_eff_cols = static_cast<int>(table_->NumEffectiveColumns());
-  bool start_to_end = distributionDirection == kStartToEnd;
-  for (int i = start_to_end ? 0 : n_eff_cols - 1;
-       start_to_end ? i < n_eff_cols : i > -1; start_to_end ? ++i : --i) {
-    const Length& logical_width = layout_struct_[i].effective_logical_width;
-    if (cellsToProcess == kNonEmptyCells && logical_width.IsAuto() &&
-        layout_struct_[i].empty_cells_only)
-      continue;
-    // When allocating width to columns with nothing but empty cells we avoid
-    // columns that exist only to flesh out a colspan and have no actual cells.
-    if (cellsToProcess == kEmptyCells && logical_width.IsAuto() &&
-        (!layout_struct_[i].empty_cells_only ||
-         layout_struct_[i].column_has_no_cells))
-      continue;
-    if (distributionMode != kLeftoverWidth &&
-        logical_width.GetType() != lengthType)
-      continue;
-
-    float factor = 1;
-    if (distributionMode != kLeftoverWidth) {
-      if (lengthType == Length::kPercent)
-        factor = logical_width.Percent();
-      else if (lengthType == Length::kAuto || lengthType == Length::kFixed)
-        factor = layout_struct_[i].ClampedEffectiveMaxLogicalWidth();
-    }
-
-    int new_width = available * factor / total;
-    int cell_logical_width =
-        (distributionMode == kInitialWidth)
-            ? max<int>(layout_struct_[i].computed_logical_width, new_width)
-            : new_width;
-    available -= cell_logical_width;
-    total -= factor;
-    layout_struct_[i].computed_logical_width =
-        (distributionMode == kInitialWidth)
-            ? cell_logical_width
-            : layout_struct_[i].computed_logical_width + cell_logical_width;
-
-    // If we have run out of width to allocate we're done.
-    // TODO(rhogan): Extend this to Fixed as well.
-    if (lengthType == Length::kPercent && (!available || !total))
-      return;
-    if (lengthType == Length::kAuto && !total)
-      return;
-  }
-}
-
-void TableLayoutAlgorithmAuto::ShrinkColumnWidth(
-    const Length::Type& length_type,
-    int& available) {
-  unsigned n_eff_cols = table_->NumEffectiveColumns();
-  int logical_width_beyond_min = 0;
-  for (unsigned i = n_eff_cols; i;) {
-    --i;
-    Length& logical_width = layout_struct_[i].effective_logical_width;
-    if (logical_width.GetType() == length_type)
-      logical_width_beyond_min += layout_struct_[i].computed_logical_width -
-                                  layout_struct_[i].effective_min_logical_width;
-  }
-
-  for (unsigned i = n_eff_cols; i && logical_width_beyond_min > 0;) {
-    --i;
-    Length& logical_width = layout_struct_[i].effective_logical_width;
-    if (logical_width.GetType() == length_type) {
-      int min_max_diff = layout_struct_[i].computed_logical_width -
-                         layout_struct_[i].effective_min_logical_width;
-      int reduce = available * min_max_diff / logical_width_beyond_min;
-      layout_struct_[i].computed_logical_width += reduce;
-      available -= reduce;
-      logical_width_beyond_min -= min_max_diff;
-      if (available >= 0)
-        break;
-    }
-  }
-}
-
-void TableLayoutAlgorithmAuto::Trace(Visitor* visitor) const {
-  visitor->Trace(span_cells_);
-  TableLayoutAlgorithm::Trace(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.h b/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.h
deleted file mode 100644
index fe10674..0000000
--- a/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
- *           (C) 2002 Dirk Mueller (mueller@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_LAYOUT_ALGORITHM_AUTO_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_LAYOUT_ALGORITHM_AUTO_H_
-
-#include "third_party/blink/renderer/core/layout/table_layout_algorithm.h"
-#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
-#include "third_party/blink/renderer/platform/geometry/length.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class LayoutTable;
-class LayoutTableCell;
-
-class TableLayoutAlgorithmAuto final : public TableLayoutAlgorithm {
- public:
-  TableLayoutAlgorithmAuto(LayoutTable*);
-  ~TableLayoutAlgorithmAuto() override;
-
-  void ComputeIntrinsicLogicalWidths(LayoutUnit& min_width,
-                                     LayoutUnit& max_width) override;
-  LayoutUnit ScaledWidthFromPercentColumns() override {
-    return scaled_width_from_percent_columns_;
-  }
-  void ApplyPreferredLogicalWidthQuirks(LayoutUnit& min_width,
-                                        LayoutUnit& max_width) const override;
-  void UpdateLayout() override;
-  void WillChangeTableLayout() override {}
-
-  void Trace(Visitor*) const override;
-
- private:
-  enum CellsToProcess { kAllCells, kNonEmptyCells, kEmptyCells };
-  enum DistributionMode { kExtraWidth, kInitialWidth, kLeftoverWidth };
-  enum DistributionDirection { kStartToEnd, kEndToStart };
-
-  void FullRecalc();
-  void RecalcColumn(unsigned eff_col);
-
-  int CalcEffectiveLogicalWidth();
-  void ShrinkColumnWidth(const Length::Type&, int& available);
-  template <typename Total,
-            Length::Type,
-            CellsToProcess,
-            DistributionMode,
-            DistributionDirection>
-  void DistributeWidthToColumns(int& available, Total);
-
-  void InsertSpanCell(LayoutTableCell*);
-
-  struct Layout {
-    Layout()
-        : min_logical_width(0),
-          max_logical_width(0),
-          effective_min_logical_width(0),
-          effective_max_logical_width(0),
-          computed_logical_width(0),
-          empty_cells_only(true),
-          column_has_no_cells(true) {}
-
-    Length logical_width;
-    Length effective_logical_width;
-    int min_logical_width;
-    int max_logical_width;
-    int effective_min_logical_width;
-    int effective_max_logical_width;
-    int computed_logical_width;
-    bool empty_cells_only;
-    bool column_has_no_cells;
-    int ClampedEffectiveMaxLogicalWidth() {
-      return std::max<int>(1, effective_max_logical_width);
-    }
-  };
-
-  Vector<Layout, 4> layout_struct_;
-  HeapVector<Member<LayoutTableCell>, 4> span_cells_;
-  bool has_percent_ : 1;
-  mutable bool effective_logical_width_dirty_ : 1;
-  LayoutUnit scaled_width_from_percent_columns_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_LAYOUT_ALGORITHM_AUTO_H_
diff --git a/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.cc b/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.cc
deleted file mode 100644
index 1c246341..0000000
--- a/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.cc
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
- *           (C) 2002 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.h"
-
-#include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-#include "third_party/blink/renderer/platform/geometry/calculation_value.h"
-#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
-#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
-
-/*
-  The text below is from the CSS 2.1 specs.
-
-  Fixed table layout
-
-  With this (fast) algorithm, the horizontal layout of the table does
-  not depend on the contents of the cells; it only depends on the
-  table's width, the width of the columns, and borders or cell
-  spacing.
-
-  The table's width may be specified explicitly with the 'width'
-  property. A value of 'auto' (for both 'display: table' and 'display:
-  inline-table') means use the automatic table layout algorithm.
-
-  In the fixed table layout algorithm, the width of each column is
-  determined as follows:
-
-    1. A column element with a value other than 'auto' for the 'width'
-    property sets the width for that column.
-
-    2. Otherwise, a cell in the first row with a value other than
-    'auto' for the 'width' property sets the width for that column. If
-    the cell spans more than one column, the width is divided over the
-    columns.
-
-    3. Any remaining columns equally divide the remaining horizontal
-    table space (minus borders or cell spacing).
-
-  The width of the table is then the greater of the value of the
-  'width' property for the table element and the sum of the column
-  widths (plus cell spacing or borders). If the table is wider than
-  the columns, the extra space should be distributed over the columns.
-
-
-  In this manner, the user agent can begin to lay out the table once
-  the entire first row has been received. Cells in subsequent rows do
-  not affect column widths. Any cell that has content that overflows
-  uses the 'overflow' property to determine whether to clip the
-  overflow content.
-*/
-
-namespace blink {
-
-static Length BrokenLegacyMultiply(const Length& length, float v) {
-  if (length.IsCalculated()) {
-    NOTREACHED();
-    return length;
-  }
-
-  Length ret = length.GetRoundToInt()
-                   ? Length(static_cast<int>(length.GetFloatValue() * v),
-                            length.GetType())
-                   : Length(length.GetFloatValue() * v, length.GetType());
-  ret.SetQuirk(length.Quirk());
-  return ret;
-}
-
-TableLayoutAlgorithmFixed::TableLayoutAlgorithmFixed(LayoutTable* table)
-    : TableLayoutAlgorithm(table), recorded_width_difference_(false) {}
-
-int TableLayoutAlgorithmFixed::CalcWidthArray() {
-  // FIXME: We might want to wait until we have all of the first row before
-  // computing for the first time.
-  int used_width = 0;
-
-  // iterate over all <col> elements
-  unsigned n_eff_cols = table_->NumEffectiveColumns();
-  width_.resize(n_eff_cols);
-  width_.Fill(Length::Auto());
-
-  unsigned current_effective_column = 0;
-  for (LayoutTableCol* col = table_->FirstColumn(); col;
-       col = col->NextColumn()) {
-    // LayoutTableCols don't have the concept of preferred logical width, but we
-    // need to clear their dirty bits so that if we call
-    // SetPreferredWidthsDirty(true) on a col or one of its descendants, we'll
-    // mark it's ancestors as dirty.
-    col->ClearIntrinsicLogicalWidthsDirtyBits();
-
-    // Width specified by column-groups that have column child does not affect
-    // column width in fixed layout tables
-    if (col->IsTableColumnGroupWithColumnChildren())
-      continue;
-
-    const Length& col_style_logical_width = col->StyleRef().LogicalWidth();
-    int effective_col_width = 0;
-    if (col_style_logical_width.IsFixed() &&
-        col_style_logical_width.Value() > 0)
-      effective_col_width = col_style_logical_width.Value();
-
-    unsigned span = col->Span();
-    while (span) {
-      unsigned span_in_current_effective_column;
-      if (current_effective_column >= n_eff_cols) {
-        table_->AppendEffectiveColumn(span);
-        n_eff_cols++;
-        width_.push_back(Length());
-        span_in_current_effective_column = span;
-      } else {
-        if (span < table_->SpanOfEffectiveColumn(current_effective_column)) {
-          table_->SplitEffectiveColumn(current_effective_column, span);
-          n_eff_cols++;
-          width_.push_back(Length());
-        }
-        span_in_current_effective_column =
-            table_->SpanOfEffectiveColumn(current_effective_column);
-      }
-      // TODO(alancutter): Make this work correctly for calc lengths.
-      if ((col_style_logical_width.IsFixed() ||
-           col_style_logical_width.IsPercent()) &&
-          col_style_logical_width.IsPositive()) {
-        width_[current_effective_column] = BrokenLegacyMultiply(
-            col_style_logical_width, span_in_current_effective_column);
-        used_width += effective_col_width * span_in_current_effective_column;
-      }
-      span -= span_in_current_effective_column;
-      current_effective_column++;
-    }
-  }
-
-  // Iterate over the first row in case some are unspecified.
-  LayoutTableSection* section = table_->TopNonEmptySection();
-  if (!section)
-    return used_width;
-
-  unsigned current_column = 0;
-
-  LayoutTableRow* first_row = section->FirstRow();
-  for (LayoutTableCell* cell = first_row->FirstCell(); cell;
-       cell = cell->NextCell()) {
-    Length logical_width = cell->StyleOrColLogicalWidth();
-
-    if (logical_width.IsCalculated()) {
-      // A calculated width that mixes lengths and percentages in fixed table
-      // layout must be treated as 'auto'.
-      // https://drafts.csswg.org/css-values-4/#calc-computed-value
-      const CalculationValue& calc = logical_width.GetCalculationValue();
-      if (calc.IsExpression() || calc.Pixels())
-        logical_width = Length();
-      else
-        logical_width = Length::Percent(calc.Percent());
-    }
-
-    unsigned span = cell->ColSpan();
-    int fixed_border_box_logical_width = 0;
-    // FIXME: Support other length types. If the width is non-auto, it should
-    // probably just use LayoutBox::computeLogicalWidthUsing to compute the
-    // width.
-    if (logical_width.IsFixed() && logical_width.IsPositive()) {
-      fixed_border_box_logical_width =
-          cell->AdjustBorderBoxLogicalWidthForBoxSizing(logical_width.Value())
-              .ToInt();
-      logical_width = Length::Fixed(fixed_border_box_logical_width);
-    }
-
-    unsigned used_span = 0;
-    while (used_span < span && current_column < n_eff_cols) {
-      float e_span = table_->SpanOfEffectiveColumn(current_column);
-      // Only set if no col element has already set it.
-      if (width_[current_column].IsAuto() && !logical_width.IsAuto()) {
-        width_[current_column] =
-            BrokenLegacyMultiply(logical_width, e_span / span);
-        used_width += fixed_border_box_logical_width * e_span / span;
-      }
-      used_span += e_span;
-      ++current_column;
-    }
-
-    // TableLayoutAlgorithmFixed doesn't use PreferredLogicalWidths, but we
-    // need to clear the dirty bit on the cell so that we'll correctly mark its
-    // ancestors dirty in case we later call SetIntrinsicLogicalWidthsDirty()
-    // on it later.
-    if (cell->IntrinsicLogicalWidthsDirty())
-      cell->ClearIntrinsicLogicalWidthsDirty();
-  }
-
-  return used_width;
-}
-
-void TableLayoutAlgorithmFixed::ComputeIntrinsicLogicalWidths(
-    LayoutUnit& min_width,
-    LayoutUnit& max_width) {
-  min_width = max_width = LayoutUnit(CalcWidthArray());
-}
-
-void TableLayoutAlgorithmFixed::ApplyPreferredLogicalWidthQuirks(
-    LayoutUnit& min_width,
-    LayoutUnit& max_width) const {
-  const Length& table_logical_width = table_->StyleRef().LogicalWidth();
-  if (table_logical_width.IsFixed() && table_logical_width.IsPositive()) {
-    min_width = max_width = LayoutUnit(
-        max(min_width,
-            LayoutUnit(table_logical_width.Value() -
-                       table_->BordersPaddingAndSpacingInRowDirection()))
-            .Floor());
-  }
-
-  /*
-        <table style="width:100%; background-color:red"><tr><td>
-            <table style="background-color:blue"><tr><td>
-                <table style="width:100%; background-color:green;
-                              table-layout:fixed"><tr><td>
-                    Content
-                </td></tr></table>
-            </td></tr></table>
-        </td></tr></table>
-    */
-  // In this example, the two inner tables should be as large as the outer
-  // table. We can achieve this effect by making the maxwidth of fixed tables
-  // with percentage widths be infinite.
-  if (!table_->IsOutOfFlowPositioned() &&
-      table_->StyleRef().LogicalWidth().IsPercentOrCalc() &&
-      max_width < kTableMaxWidth)
-    max_width = LayoutUnit(kTableMaxWidth);
-}
-
-void TableLayoutAlgorithmFixed::UpdateLayout() {
-  int table_logical_width = (table_->LogicalWidth() -
-                             table_->BordersPaddingAndSpacingInRowDirection())
-                                .ToInt();
-  unsigned n_eff_cols = table_->NumEffectiveColumns();
-
-  // FIXME: It is possible to be called without having properly updated our
-  // internal representation. This means that our preferred logical widths were
-  // not recomputed as expected.
-  if (n_eff_cols != width_.size()) {
-    CalcWidthArray();
-    // FIXME: Table layout shouldn't modify our table structure (but does due to
-    // columns and column-groups).
-    n_eff_cols = table_->NumEffectiveColumns();
-  }
-
-  Vector<int> calc_width(n_eff_cols, 0);
-
-  unsigned num_auto = 0;
-  unsigned auto_span = 0;
-  int total_fixed_width = 0;
-  int total_percent_width = 0;
-  float total_percent = 0;
-
-  // Compute requirements and try to satisfy fixed and percent widths.
-  // Percentages are of the table's width, so for example
-  // for a table width of 100px with columns (40px, 10%), the 10% compute
-  // to 10px here, and will scale up to 20px in the final (80px, 20px).
-  for (unsigned i = 0; i < n_eff_cols; i++) {
-    if (width_[i].IsFixed()) {
-      calc_width[i] = width_[i].Value();
-      total_fixed_width += calc_width[i];
-    } else if (width_[i].IsPercent()) {
-      // TODO(alancutter): Make this work correctly for calc lengths.
-      calc_width[i] =
-          ValueForLength(width_[i], LayoutUnit(table_logical_width)).ToInt();
-      total_percent_width += calc_width[i];
-      total_percent += width_[i].Percent();
-    } else if (width_[i].IsAuto()) {
-      num_auto++;
-      auto_span += table_->SpanOfEffectiveColumn(i);
-    }
-  }
-
-  int16_t hspacing = table_->HBorderSpacing();
-  int total_width = total_fixed_width + total_percent_width;
-  if (!num_auto || total_width > table_logical_width) {
-    // If there are no auto columns, or if the total is too wide, take
-    // what we have and scale it to fit as necessary.
-    if (total_width != table_logical_width) {
-      // Fixed widths only scale up
-      if (total_fixed_width && total_width < table_logical_width) {
-        int first_pass_fixed_width_total = total_fixed_width;
-        total_fixed_width = 0;
-        int width_available_for_fixed =
-            table_logical_width - total_percent_width;
-        for (unsigned i = 0; i < n_eff_cols; i++) {
-          if (width_[i].IsFixed()) {
-            int legacy_expanded_width =
-                calc_width[i] * table_logical_width / total_width;
-            if (!recorded_width_difference_) {
-              int future_expanded_width = calc_width[i] *
-                                          width_available_for_fixed /
-                                          first_pass_fixed_width_total;
-              if (future_expanded_width != legacy_expanded_width) {
-                recorded_width_difference_ = true;
-                UseCounter::Count(
-                    table_->GetDocument(),
-                    WebFeature::kFixedWidthTableDistributionChanged);
-              }
-            }
-            calc_width[i] = legacy_expanded_width;
-            total_fixed_width += calc_width[i];
-          }
-        }
-      }
-      if (total_percent) {
-        total_percent_width = 0;
-        for (unsigned i = 0; i < n_eff_cols; i++) {
-          // TODO(alancutter): Make this work correctly for calc lengths.
-          if (width_[i].IsPercent()) {
-            calc_width[i] = width_[i].Percent() *
-                            (table_logical_width - total_fixed_width) /
-                            total_percent;
-            total_percent_width += calc_width[i];
-          }
-        }
-      }
-      total_width = total_fixed_width + total_percent_width;
-    }
-  } else {
-    // Divide the remaining width among the auto columns.
-    DCHECK_GE(auto_span, num_auto);
-    int remaining_width = table_logical_width - total_fixed_width -
-                          total_percent_width -
-                          hspacing * (auto_span - num_auto);
-    int last_auto = 0;
-    for (unsigned i = 0; i < n_eff_cols; i++) {
-      if (width_[i].IsAuto()) {
-        unsigned span = table_->SpanOfEffectiveColumn(i);
-        int w = remaining_width * span / auto_span;
-        calc_width[i] = std::max<int>((w + hspacing * (span - 1)), 0);
-        remaining_width -= w;
-        if (!remaining_width)
-          break;
-        last_auto = i;
-        DCHECK_GE(auto_span, span);
-        auto_span -= span;
-      }
-    }
-    // Last one gets the remainder.
-    if (remaining_width) {
-      calc_width[last_auto] =
-          std::max(calc_width[last_auto] + remaining_width, 0);
-    }
-    total_width = table_logical_width;
-  }
-
-  if (total_width < table_logical_width) {
-    // Spread extra space over columns.
-    int remaining_width = table_logical_width - total_width;
-    int total = n_eff_cols;
-    while (total) {
-      int w = remaining_width / total;
-      remaining_width -= w;
-      calc_width[--total] += w;
-    }
-    if (n_eff_cols > 0)
-      calc_width[n_eff_cols - 1] += remaining_width;
-  }
-
-  DCHECK_EQ(table_->EffectiveColumnPositions().size(), n_eff_cols + 1);
-  int pos = 0;
-  for (unsigned i = 0; i < n_eff_cols; i++) {
-    table_->SetEffectiveColumnPosition(i, pos);
-    pos += calc_width[i] + hspacing;
-  }
-  // The extra position is for the imaginary column after the last column.
-  table_->SetEffectiveColumnPosition(n_eff_cols, pos);
-}
-
-void TableLayoutAlgorithmFixed::WillChangeTableLayout() {
-  // When switching table layout algorithm, we need to dirty the preferred
-  // logical widths as we cleared the bits without computing them.
-  // (see calcWidthArray above.) This optimization is preferred to always
-  // computing the logical widths we never intended to use.
-  table_->RecalcSectionsIfNeeded();
-  table_->MarkAllCellsWidthsDirtyAndOrNeedsLayout(LayoutTable::kMarkDirtyOnly);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.h b/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.h
deleted file mode 100644
index d929c02..0000000
--- a/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
- *           (C) 2002 Dirk Mueller (mueller@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_LAYOUT_ALGORITHM_FIXED_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_LAYOUT_ALGORITHM_FIXED_H_
-
-#include "third_party/blink/renderer/core/layout/table_layout_algorithm.h"
-#include "third_party/blink/renderer/platform/geometry/length.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class LayoutTable;
-
-class TableLayoutAlgorithmFixed final : public TableLayoutAlgorithm {
- public:
-  TableLayoutAlgorithmFixed(LayoutTable*);
-
-  void ComputeIntrinsicLogicalWidths(LayoutUnit& min_width,
-                                     LayoutUnit& max_width) override;
-  void ApplyPreferredLogicalWidthQuirks(LayoutUnit& min_width,
-                                        LayoutUnit& max_width) const override;
-  void UpdateLayout() override;
-  void WillChangeTableLayout() override;
-
- private:
-  int CalcWidthArray();
-  bool recorded_width_difference_;
-
-  Vector<Length> width_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_LAYOUT_ALGORITHM_FIXED_H_
diff --git a/third_party/blink/renderer/core/layout/text_autosizer.cc b/third_party/blink/renderer/core/layout/text_autosizer.cc
index 643a1c4..4da9334 100644
--- a/third_party/blink/renderer/core/layout/text_autosizer.cc
+++ b/third_party/blink/renderer/core/layout/text_autosizer.cc
@@ -47,11 +47,13 @@
 #include "third_party/blink/renderer/core/layout/layout_inline.h"
 #include "third_party/blink/renderer/core/layout/layout_list_item.h"
 #include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 #include "third_party/blink/renderer/core/layout/style_retain_scope.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
 #include "third_party/blink/renderer/core/page/page.h"
@@ -450,11 +452,10 @@
 
   LayoutObject* child = nullptr;
   if (parent->IsRuby()) {
-    // Skip layoutRubyRun which is inline-block.
+    // Skip LayoutNGRubyRun which is inline-block.
     // Inflate rubyRun's inner blocks.
-    LayoutObject* run = parent->SlowFirstChild();
-    if (run && run->IsRubyRun()) {
-      child = To<LayoutRubyRun>(run)->FirstChild();
+    if (auto* run = DynamicTo<LayoutNGRubyRun>(parent->SlowFirstChild())) {
+      child = run->FirstChild();
       behavior = kDescendToInnerBlocks;
     }
   } else if (parent->IsListMarker()) {
@@ -1049,10 +1050,7 @@
   // methods to obtain a width, and fall back on a containing block's width.
   for (; block; block = block->ContainingBlock()) {
     float width;
-    Length specified_width =
-        block->IsTableCellLegacy()
-            ? To<LayoutTableCell>(block)->StyleOrColLogicalWidth()
-            : block->StyleRef().LogicalWidth();
+    Length specified_width = block->StyleRef().LogicalWidth();
     if (specified_width.IsFixed()) {
       if ((width = specified_width.Value()) > 0)
         return width;
diff --git a/third_party/blink/renderer/core/layout/traced_layout_object.cc b/third_party/blink/renderer/core/layout/traced_layout_object.cc
index ea14bdd..f0f56ae 100644
--- a/third_party/blink/renderer/core/layout/traced_layout_object.cc
+++ b/third_party/blink/renderer/core/layout/traced_layout_object.cc
@@ -7,9 +7,9 @@
 #include <inttypes.h>
 #include <memory>
 #include "third_party/blink/renderer/core/layout/layout_inline.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/layout/layout_text.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.cc b/third_party/blink/renderer/core/loader/resource/script_resource.cc
index d9950f4..d474e7ad 100644
--- a/third_party/blink/renderer/core/loader/resource/script_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/script_resource.cc
@@ -182,30 +182,20 @@
 
 String ScriptResource::TextForInspector() const {
   // If the resource buffer exists, we can safely return the decoded text.
-  if (ResourceBuffer())
+  if (ResourceBuffer()) {
     return DecodedText();
-
-  // If there is no resource buffer, then we have three cases.
-  // TODO(crbug.com/865098): Simplify the below code and remove the CHECKs once
-  // the assumptions are confirmed.
-
-  if (IsLoaded()) {
-    if (!source_text_.IsNull()) {
-      // 1. We have finished loading, and have already decoded the buffer into
-      //    the source text and cleared the resource buffer to save space.
-      return source_text_.ToString();
-    }
-
-    // 2. We have finished loading with no data received, so no streaming ever
-    //    happened or streaming was suppressed.
-    DCHECK(!streamer_ ||
-           streamer_->StreamingSuppressedReason() ==
-               ScriptStreamer::NotStreamingReason::kScriptTooSmall);
-    return "";
   }
 
-  // 3. We haven't started loading, and actually haven't received any data yet
-  //    at all to initialise the resource buffer, so the resource is empty.
+  // If there is no resource buffer, then we've finished loading and have
+  // already decoded the buffer into the source text, clearing the resource
+  // buffer to save space...
+  if (IsLoaded() && !source_text_.IsNull()) {
+    return source_text_.ToString();
+  }
+
+  // ... or we either haven't started loading and haven't received data yet, or
+  // we finished loading with an error/cancellation, and thus don't have data.
+  // In both cases, we can treat the resource as empty.
   return "";
 }
 
@@ -292,12 +282,14 @@
   // Do not revalidate until ClassicPendingScript is removed, i.e. the script
   // content is retrieved in ScriptLoader::ExecuteScriptBlock().
   // crbug.com/692856
-  if (HasClientsOrObservers())
+  if (HasClientsOrObservers()) {
     return false;
+  }
 
   // Do not revalidate until streaming is complete.
-  if (!IsLoaded())
+  if (!IsLoaded()) {
     return false;
+  }
 
   return Resource::CanUseCacheValidator();
 }
@@ -346,8 +338,9 @@
 void ScriptResource::ResponseBodyReceived(
     ResponseBodyLoaderDrainableInterface& body_loader,
     scoped_refptr<base::SingleThreadTaskRunner> loader_task_runner) {
-  if (streaming_state_ == StreamingState::kStreamingDisabled)
+  if (streaming_state_ == StreamingState::kStreamingDisabled) {
     return;
+  }
 
   CHECK_EQ(streaming_state_, StreamingState::kWaitingForDataPipe);
 
@@ -434,8 +427,9 @@
 
 ResourceScriptStreamer* ScriptResource::TakeStreamer() {
   CHECK(IsLoaded());
-  if (!streamer_)
+  if (!streamer_) {
     return nullptr;
+  }
 
   ResourceScriptStreamer* streamer = streamer_;
   // A second use of the streamer is not possible, so we null it out and disable
@@ -501,8 +495,9 @@
 ScriptCacheConsumer* ScriptResource::TakeCacheConsumer() {
   CHECK(IsLoaded());
   CheckConsumeCacheState();
-  if (!cache_consumer_)
+  if (!cache_consumer_) {
     return nullptr;
+  }
   CHECK_EQ(consume_cache_state_, ConsumeCacheState::kRunningOffThread);
 
   ScriptCacheConsumer* cache_consumer = cache_consumer_;
diff --git a/third_party/blink/renderer/core/loader/threaded_icon_loader.cc b/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
index f31a966b..7ecf388 100644
--- a/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
+++ b/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
@@ -67,7 +67,7 @@
   };
 
   std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
-      std::move(data), /* data_complete= */ true,
+      std::move(data), /*data_complete=*/true,
       ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth,
       ColorBehavior::TransformToSRGB());
 
diff --git a/third_party/blink/renderer/core/page/grid_focusgroup_structure_info.cc b/third_party/blink/renderer/core/page/grid_focusgroup_structure_info.cc
index 0468dda8..fc61d35 100644
--- a/third_party/blink/renderer/core/page/grid_focusgroup_structure_info.cc
+++ b/third_party/blink/renderer/core/page/grid_focusgroup_structure_info.cc
@@ -10,11 +10,9 @@
 #include "third_party/blink/renderer/core/html/html_table_element.h"
 #include "third_party/blink/renderer/core/html/html_table_row_element.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell_interface.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
-#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row_interface.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 
 namespace blink {
@@ -30,8 +28,9 @@
   visitor->Trace(table_);
 }
 
-const LayoutNGTableInterface* AutomaticGridFocusgroupStructureInfo::Table() {
-  return table_->ToLayoutNGTableInterface();
+const LayoutNGTable* AutomaticGridFocusgroupStructureInfo::Table() {
+  CHECK(table_->IsTable());
+  return To<LayoutNGTable>(table_.Get());
 }
 
 Element* AutomaticGridFocusgroupStructureInfo::Root() {
@@ -45,7 +44,7 @@
 unsigned AutomaticGridFocusgroupStructureInfo::ColumnCount() {
   // The actual column count of a table is not stored on an HTMLTableElement,
   // but it is on its associated layout object.
-  auto* section = Table()->FirstSectionInterface();
+  auto* section = Table()->FirstSection();
   if (!section)
     return 0;
 
@@ -55,19 +54,15 @@
 Element* AutomaticGridFocusgroupStructureInfo::PreviousCellInRow(
     const Element* cell_element) {
   DCHECK(cell_element);
-  if (!IsA<LayoutNGTableCell>(cell_element->GetLayoutObject()))
-    return nullptr;
-
-  auto* cell =
-      ToInterface<LayoutNGTableCellInterface>(cell_element->GetLayoutObject());
+  auto* cell = DynamicTo<LayoutNGTableCell>(cell_element->GetLayoutObject());
   if (!cell)
     return nullptr;
 
-  auto* row = cell->RowInterface();
+  auto* row = cell->Row();
   if (!row)
     return nullptr;
 
-  Element* row_element = DynamicTo<Element>(row->ToLayoutObject()->GetNode());
+  Element* row_element = DynamicTo<Element>(row->GetNode());
   if (!row_element)
     return nullptr;
 
@@ -78,11 +73,7 @@
 Element* AutomaticGridFocusgroupStructureInfo::NextCellInRow(
     const Element* cell_element) {
   DCHECK(cell_element);
-  if (!IsA<LayoutNGTableCell>(cell_element->GetLayoutObject()))
-    return nullptr;
-
-  auto* cell =
-      ToInterface<LayoutNGTableCellInterface>(cell_element->GetLayoutObject());
+  auto* cell = DynamicTo<LayoutNGTableCell>(cell_element->GetLayoutObject());
   if (!cell)
     return nullptr;
 
@@ -93,11 +84,11 @@
     return nullptr;
   }
 
-  auto* row = cell->RowInterface();
+  auto* row = cell->Row();
   if (!row)
     return nullptr;
 
-  Element* row_element = DynamicTo<Element>(row->ToLayoutObject()->GetNode());
+  Element* row_element = DynamicTo<Element>(row->GetNode());
   if (!row_element)
     return nullptr;
 
@@ -126,13 +117,10 @@
 unsigned AutomaticGridFocusgroupStructureInfo::ColumnIndexForCell(
     const Element* cell_element) {
   DCHECK(cell_element);
-  if (!IsA<LayoutNGTableCell>(cell_element->GetLayoutObject()))
-    return 0;
 
   // The actual column index takes into account the previous rowspan/colspan
   // values that might affect this cell's col index.
-  auto* cell =
-      ToInterface<LayoutNGTableCellInterface>(cell_element->GetLayoutObject());
+  auto* cell = DynamicTo<LayoutNGTableCell>(cell_element->GetLayoutObject());
   if (!cell)
     return 0;
 
@@ -142,14 +130,12 @@
 Element* AutomaticGridFocusgroupStructureInfo::PreviousCellInColumn(
     const Element* cell_element) {
   DCHECK(cell_element);
-  if (!IsA<LayoutNGTableCell>(cell_element->GetLayoutObject()))
+  auto* cell = DynamicTo<LayoutNGTableCell>(cell_element->GetLayoutObject());
+  if (!cell) {
     return nullptr;
+  }
 
-  auto* cell =
-      ToInterface<LayoutNGTableCellInterface>(cell_element->GetLayoutObject());
-  DCHECK(cell);
-
-  auto* row = cell->RowInterface();
+  auto* row = cell->Row();
   if (!row)
     return nullptr;
 
@@ -157,8 +143,7 @@
   if (!previous_row)
     return nullptr;
 
-  auto* previous_row_element =
-      DynamicTo<Element>(previous_row->ToLayoutObject()->GetNode());
+  auto* previous_row_element = DynamicTo<Element>(previous_row->GetNode());
   if (!previous_row_element)
     return nullptr;
 
@@ -170,15 +155,12 @@
 Element* AutomaticGridFocusgroupStructureInfo::NextCellInColumn(
     const Element* cell_element) {
   DCHECK(cell_element);
-  if (!IsA<LayoutNGTableCell>(cell_element->GetLayoutObject()))
-    return nullptr;
 
-  auto* cell =
-      ToInterface<LayoutNGTableCellInterface>(cell_element->GetLayoutObject());
+  auto* cell = DynamicTo<LayoutNGTableCell>(cell_element->GetLayoutObject());
   if (!cell)
     return nullptr;
 
-  auto* row = cell->RowInterface();
+  auto* row = cell->Row();
   if (!row)
     return nullptr;
 
@@ -190,8 +172,7 @@
       return nullptr;
   }
 
-  auto* next_row_element =
-      DynamicTo<Element>(next_row->ToLayoutObject()->GetNode());
+  auto* next_row_element = DynamicTo<Element>(next_row->GetNode());
   if (!next_row_element)
     return nullptr;
 
@@ -220,11 +201,7 @@
 Element* AutomaticGridFocusgroupStructureInfo::PreviousRow(
     Element* row_element) {
   DCHECK(row_element);
-  if (!IsA<LayoutNGTableRow>(row_element->GetLayoutObject()))
-    return nullptr;
-
-  auto* row =
-      ToInterface<LayoutNGTableRowInterface>(row_element->GetLayoutObject());
+  auto* row = DynamicTo<LayoutNGTableRow>(row_element->GetLayoutObject());
   if (!row)
     return nullptr;
 
@@ -232,16 +209,12 @@
   if (!previous_row)
     return nullptr;
 
-  return DynamicTo<Element>(previous_row->ToLayoutObject()->GetNode());
+  return DynamicTo<Element>(previous_row->GetNode());
 }
 
 Element* AutomaticGridFocusgroupStructureInfo::NextRow(Element* row_element) {
   DCHECK(row_element);
-  if (!IsA<LayoutNGTableRow>(row_element->GetLayoutObject()))
-    return nullptr;
-
-  auto* row =
-      ToInterface<LayoutNGTableRowInterface>(row_element->GetLayoutObject());
+  auto* row = DynamicTo<LayoutNGTableRow>(row_element->GetLayoutObject());
   if (!row)
     return nullptr;
 
@@ -249,68 +222,67 @@
   if (!next_row)
     return nullptr;
 
-  return DynamicTo<Element>(next_row->ToLayoutObject()->GetNode());
+  return DynamicTo<Element>(next_row->GetNode());
 }
 
 Element* AutomaticGridFocusgroupStructureInfo::FirstRow() {
-  auto* first_section = Table()->FirstNonEmptySectionInterface();
-  auto* first_row = first_section->FirstRowInterface();
+  auto* first_section = Table()->FirstNonEmptySection();
+  auto* first_row = first_section->FirstRow();
   while (first_row) {
     // Layout rows can be empty (i.e., have no cells), so make sure that we
     // return the first row that has at least one cell.
-    if (first_row->FirstCellInterface())
-      return DynamicTo<Element>(first_row->ToLayoutObject()->GetNode());
-    first_row = first_row->NextRowInterface();
+    if (first_row->FirstCell()) {
+      return DynamicTo<Element>(first_row->GetNode());
+    }
+    first_row = first_row->NextRow();
   }
   return nullptr;
 }
 
 Element* AutomaticGridFocusgroupStructureInfo::LastRow() {
-  auto* last_section = Table()->LastNonEmptySectionInterface();
-  auto* last_row = last_section->LastRowInterface();
+  auto* last_section = Table()->LastNonEmptySection();
+  auto* last_row = last_section->LastRow();
   while (last_row) {
     // See comment in `PreviousRow()` to understand why we need to ensure this
     // functions returns a row that has cells.
-    if (last_row->FirstCellInterface())
-      return DynamicTo<Element>(last_row->ToLayoutObject()->GetNode());
+    if (last_row->FirstCell()) {
+      return DynamicTo<Element>(last_row->GetNode());
+    }
 
-    last_row = last_row->PreviousRowInterface();
+    last_row = last_row->PreviousRow();
   }
   return nullptr;
 }
 
 Element* AutomaticGridFocusgroupStructureInfo::RowForCell(
     Element* cell_element) {
-  if (!IsA<LayoutNGTableCell>(cell_element->GetLayoutObject()))
+  auto* cell = DynamicTo<LayoutNGTableCell>(cell_element->GetLayoutObject());
+  if (!cell) {
     return nullptr;
+  }
 
-  auto* cell =
-      ToInterface<LayoutNGTableCellInterface>(cell_element->GetLayoutObject());
-  DCHECK(cell);
-
-  auto* row = cell->RowInterface();
+  auto* row = cell->Row();
   if (!row)
     return nullptr;
 
-  return DynamicTo<Element>(row->ToLayoutObject()->GetNode());
+  return DynamicTo<Element>(row->GetNode());
 }
 
 Element* AutomaticGridFocusgroupStructureInfo::CellAtIndexInRow(
     unsigned index,
     Element* row_element,
     NoCellFoundAtIndexBehavior behavior) {
-  if (!IsA<LayoutNGTableRow>(row_element->GetLayoutObject()))
+  auto* row = DynamicTo<LayoutNGTableRow>(row_element->GetLayoutObject());
+  if (!row) {
     return nullptr;
-
-  auto* row =
-      ToInterface<LayoutNGTableRowInterface>(row_element->GetLayoutObject());
-  DCHECK(row);
+  }
 
   // This can happen when |row|'s nth previous sibling row has a rowspan value
   // of n + 1 and a colspan value equal to the table's column count. In that
   // case, |row| won't have any cell.
-  if (!row->FirstCellInterface())
+  if (!row->FirstCell()) {
     return nullptr;
+  }
 
   unsigned total_col_count = ColumnCount();
   if (index >= total_col_count)
@@ -353,13 +325,13 @@
   if (!cell)
     return nullptr;
 
-  return DynamicTo<Element>(cell->ToLayoutObject()->GetNode());
+  return DynamicTo<Element>(cell->GetNode());
 }
 
-LayoutNGTableRowInterface* AutomaticGridFocusgroupStructureInfo::PreviousRow(
-    LayoutNGTableRowInterface* current_row) {
-  auto* current_section = current_row->SectionInterface();
-  LayoutNGTableRowInterface* previous_row = current_row->PreviousRowInterface();
+LayoutNGTableRow* AutomaticGridFocusgroupStructureInfo::PreviousRow(
+    LayoutNGTableRow* current_row) {
+  auto* current_section = current_row->Section();
+  LayoutNGTableRow* previous_row = current_row->PreviousRow();
 
   // Here, it's possible the previous row has no cells at all if the nth
   // previous row has a rowspan attribute of value n + 1 and a colspan value
@@ -369,28 +341,28 @@
   // Also, it's possible that the previous row is actually located in the
   // previous section. When we can't find a previous row, get the last row from
   // the previous section.
-  while (!previous_row || !previous_row->FirstCellInterface()) {
-    if (previous_row && previous_row->FirstCellInterface()) {
-      previous_row = previous_row->PreviousRowInterface();
+  while (!previous_row || !previous_row->FirstCell()) {
+    if (previous_row && previous_row->FirstCell()) {
+      previous_row = previous_row->PreviousRow();
       continue;
     }
 
     auto* previous_section =
-        Table()->PreviousSectionInterface(current_section, kSkipEmptySections);
+        Table()->PreviousSection(current_section, kSkipEmptySections);
     if (!previous_section)
       return nullptr;
 
     current_section = previous_section;
-    previous_row = previous_section->LastRowInterface();
+    previous_row = previous_section->LastRow();
   }
 
   return previous_row;
 }
 
-LayoutNGTableRowInterface* AutomaticGridFocusgroupStructureInfo::NextRow(
-    LayoutNGTableRowInterface* current_row) {
-  auto* current_section = current_row->SectionInterface();
-  LayoutNGTableRowInterface* next_row = current_row->NextRowInterface();
+LayoutNGTableRow* AutomaticGridFocusgroupStructureInfo::NextRow(
+    LayoutNGTableRow* current_row) {
+  auto* current_section = current_row->Section();
+  LayoutNGTableRow* next_row = current_row->NextRow();
 
   // Here, it's possible the next row has no cells at all if the current row (or
   // a previous sibling) has a rowspan attribute that encapsulates the next row
@@ -400,36 +372,35 @@
   // Also, it's possible that the next row is actually located in the
   // next section. When we can't find a previous row, get the last row from
   // the previous section.
-  while (!next_row || !next_row->FirstCellInterface()) {
-    if (next_row && next_row->FirstCellInterface()) {
-      next_row = next_row->NextRowInterface();
+  while (!next_row || !next_row->FirstCell()) {
+    if (next_row && next_row->FirstCell()) {
+      next_row = next_row->NextRow();
       continue;
     }
 
     auto* next_section =
-        Table()->NextSectionInterface(current_section, kSkipEmptySections);
+        Table()->NextSection(current_section, kSkipEmptySections);
     if (!next_section)
       return nullptr;
 
     current_section = next_section;
-    next_row = next_section->FirstRowInterface();
+    next_row = next_section->FirstRow();
   }
 
   return next_row;
 }
 
-LayoutNGTableCellInterface*
+LayoutNGTableCell*
 AutomaticGridFocusgroupStructureInfo::TableCellAtIndexInRowRecursive(
     unsigned index,
-    LayoutNGTableRowInterface* row,
+    LayoutNGTableRow* row,
     absl::optional<unsigned> expected_rowspan) {
   if (!row)
     return nullptr;
 
   // 1. Define a starting point for the search. Start from the end.
-  auto* cell = row->LastCellInterface();
-  if (auto* table_row =
-          DynamicTo<HTMLTableRowElement>(row->ToLayoutObject()->GetNode())) {
+  auto* cell = row->LastCell();
+  if (auto* table_row = DynamicTo<HTMLTableRowElement>(row->GetNode())) {
     // This is a shortcut that allows us to get the cell at |index| in constant
     // time. This shortcut is only possible with HTML tables. If the table
     // contains rowspans/colspans that affect this cell, it might actually not
@@ -438,9 +409,9 @@
     // the search on the first/last cell of a row.
     auto* table_cell =
         DynamicTo<HTMLTableCellElement>(table_row->cells()->item(index));
-    if (table_cell)
-      cell = ToInterface<LayoutNGTableCellInterface>(
-          table_cell->GetLayoutObject());
+    if (table_cell) {
+      cell = To<LayoutNGTableCell>(table_cell->GetLayoutObject());
+    }
   }
 
   // 2. Get the cell's actual index. Its index might not be equal to |index|,
@@ -461,7 +432,7 @@
   // current |cell|.
   while (actual_index != index) {
     if (actual_index > index) {
-      cell = cell->PreviousCellInterface();
+      cell = cell->PreviousCell();
       if (cell) {
         actual_index = cell->AbsoluteColumnIndex();
         continue;
@@ -519,4 +490,4 @@
   return cell;
 }
 
-}  // namespace blink
\ No newline at end of file
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/page/grid_focusgroup_structure_info.h b/third_party/blink/renderer/core/page/grid_focusgroup_structure_info.h
index 326acbb..ace16237 100644
--- a/third_party/blink/renderer/core/page/grid_focusgroup_structure_info.h
+++ b/third_party/blink/renderer/core/page/grid_focusgroup_structure_info.h
@@ -16,9 +16,9 @@
 
 class Element;
 class LayoutObject;
-class LayoutNGTableInterface;
-class LayoutNGTableCellInterface;
-class LayoutNGTableRowInterface;
+class LayoutNGTable;
+class LayoutNGTableCell;
+class LayoutNGTableRow;
 
 // This interface is used to expose the grid focusgroup navigation functions
 // while hiding the type of grid we're in. A grid focusgroup can either be
@@ -89,7 +89,7 @@
 
   void Trace(Visitor*) const;
 
-  const LayoutNGTableInterface* Table();
+  const LayoutNGTable* Table();
 
   Element* Root() override;
   FocusgroupFlags Flags() override;
@@ -118,13 +118,12 @@
                             NoCellFoundAtIndexBehavior behavior) override;
 
  private:
-  LayoutNGTableRowInterface* PreviousRow(
-      LayoutNGTableRowInterface* current_row);
-  LayoutNGTableRowInterface* NextRow(LayoutNGTableRowInterface* current_row);
+  LayoutNGTableRow* PreviousRow(LayoutNGTableRow* current_row);
+  LayoutNGTableRow* NextRow(LayoutNGTableRow* current_row);
 
-  LayoutNGTableCellInterface* TableCellAtIndexInRowRecursive(
+  LayoutNGTableCell* TableCellAtIndexInRowRecursive(
       unsigned index,
-      LayoutNGTableRowInterface* row,
+      LayoutNGTableRow* row,
       absl::optional<unsigned> expected_rowspan = absl::nullopt);
 
   Member<LayoutObject> table_;
diff --git a/third_party/blink/renderer/core/paint/background_image_geometry.cc b/third_party/blink/renderer/core/paint/background_image_geometry.cc
index cc7adb6..34b84a21 100644
--- a/third_party/blink/renderer/core/paint/background_image_geometry.cc
+++ b/third_party/blink/renderer/core/paint/background_image_geometry.cc
@@ -7,8 +7,6 @@
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
@@ -215,98 +213,6 @@
   phase_ += fixed_adjustment;
 }
 
-enum ColumnGroupDirection { kColumnGroupStart, kColumnGroupEnd };
-
-static void ExpandToTableColumnGroup(const LayoutTableCell& cell,
-                                     const LayoutTableCol& column_group,
-                                     LayoutUnit& value,
-                                     ColumnGroupDirection column_direction) {
-  auto sibling_cell = column_direction == kColumnGroupStart
-                          ? &LayoutTableCell::PreviousCell
-                          : &LayoutTableCell::NextCell;
-  for (const auto* sibling = (cell.*sibling_cell)(); sibling;
-       sibling = (sibling->*sibling_cell)()) {
-    LayoutTableCol* innermost_col =
-        cell.Table()
-            ->ColElementAtAbsoluteColumn(sibling->AbsoluteColumnIndex())
-            .InnermostColOrColGroup();
-    if (!innermost_col || innermost_col->EnclosingColumnGroup() != column_group)
-      break;
-    value += sibling->Size().Width();
-  }
-}
-
-PhysicalOffset BackgroundImageGeometry::GetPositioningOffsetForCell(
-    const LayoutTableCell& cell,
-    const LayoutBox& positioning_box) {
-  LayoutUnit h_border_spacing(cell.Table()->HBorderSpacing());
-  LayoutUnit v_border_spacing(cell.Table()->VBorderSpacing());
-  // TODO(layout-ng): It looks incorrect to use Location() in this function.
-  if (positioning_box.IsTableSection()) {
-    return PhysicalOffset(cell.Location().X() - h_border_spacing,
-                          cell.Location().Y() - v_border_spacing);
-  }
-  if (positioning_box.IsLegacyTableRow()) {
-    return PhysicalOffset(cell.Location().X() - h_border_spacing, LayoutUnit());
-  }
-
-  PhysicalRect sections_rect(PhysicalOffset(), cell.Table()->Size());
-  cell.Table()->SubtractCaptionRect(sections_rect);
-  LayoutUnit height_of_captions =
-      cell.Table()->Size().Height() - sections_rect.Height();
-  PhysicalOffset offset_in_background = PhysicalOffset(
-      LayoutUnit(), (cell.Section()->Location().Y() -
-                     cell.Table()->BorderBefore() - height_of_captions) +
-                        cell.Location().Y());
-
-  const auto& table_col = To<LayoutTableCol>(positioning_box);
-  if (table_col.IsTableColumn()) {
-    offset_in_background.top -= v_border_spacing;
-    return offset_in_background;
-  }
-
-  DCHECK(table_col.IsTableColumnGroup());
-  LayoutUnit offset = offset_in_background.left;
-  ExpandToTableColumnGroup(cell, table_col, offset, kColumnGroupStart);
-  offset_in_background.left += offset;
-  offset_in_background.top -= v_border_spacing;
-  return offset_in_background;
-}
-
-PhysicalSize BackgroundImageGeometry::GetBackgroundObjectDimensions(
-    const LayoutTableCell& cell,
-    const LayoutBox& positioning_box) {
-  PhysicalSize border_spacing(LayoutUnit(cell.Table()->HBorderSpacing()),
-                              LayoutUnit(cell.Table()->VBorderSpacing()));
-  if (positioning_box.IsTableSection()) {
-    return PhysicalSizeToBeNoop(positioning_box.Size()) - border_spacing -
-           border_spacing;
-  }
-
-  if (positioning_box.IsTableRow()) {
-    return PhysicalSizeToBeNoop(positioning_box.Size()) -
-           PhysicalSize(border_spacing.width, LayoutUnit()) -
-           PhysicalSize(border_spacing.width, LayoutUnit());
-  }
-
-  DCHECK(positioning_box.IsLayoutTableCol());
-  PhysicalRect sections_rect(PhysicalOffset(), cell.Table()->Size());
-  cell.Table()->SubtractCaptionRect(sections_rect);
-  LayoutUnit column_height = sections_rect.Height() -
-                             cell.Table()->BorderBefore() -
-                             border_spacing.height - border_spacing.height;
-  const auto& table_col = To<LayoutTableCol>(positioning_box);
-  if (table_col.IsTableColumn())
-    return PhysicalSize(cell.Size().Width(), column_height);
-
-  DCHECK(table_col.IsTableColumnGroup());
-  LayoutUnit width = cell.Size().Width();
-  ExpandToTableColumnGroup(cell, table_col, width, kColumnGroupStart);
-  ExpandToTableColumnGroup(cell, table_col, width, kColumnGroupEnd);
-
-  return PhysicalSize(width, column_height);
-}
-
 bool BackgroundImageGeometry::ShouldUseFixedAttachment(
     const FillLayer& fill_layer) const {
   // Only backgrounds fixed to viewport should be treated as fixed attachment.
@@ -391,25 +297,6 @@
     const LayoutBoxModelObject& obj)
     : BackgroundImageGeometry(&obj, &obj) {}
 
-BackgroundImageGeometry::BackgroundImageGeometry(
-    const LayoutTableCell& cell,
-    const LayoutObject* background_object)
-    : BackgroundImageGeometry(
-          &cell,
-          background_object && !background_object->IsTableCell()
-              ? &To<LayoutBoxModelObject>(*background_object)
-              : &cell) {
-  painting_table_cell_ = true;
-  cell_using_container_background_ =
-      background_object && !background_object->IsTableCell();
-  if (cell_using_container_background_) {
-    element_positioning_area_offset_ =
-        GetPositioningOffsetForCell(cell, To<LayoutBox>(*background_object));
-    positioning_size_override_ =
-        GetBackgroundObjectDimensions(cell, To<LayoutBox>(*background_object));
-  }
-}
-
 // TablesNG background painting.
 BackgroundImageGeometry::BackgroundImageGeometry(const LayoutNGTableCell& cell,
                                                  PhysicalOffset cell_offset,
diff --git a/third_party/blink/renderer/core/paint/background_image_geometry.h b/third_party/blink/renderer/core/paint/background_image_geometry.h
index 4c02a02..77824e0 100644
--- a/third_party/blink/renderer/core/paint/background_image_geometry.h
+++ b/third_party/blink/renderer/core/paint/background_image_geometry.h
@@ -19,8 +19,6 @@
 class LayoutBox;
 class LayoutBoxModelObject;
 class LayoutNGTableCell;
-class LayoutObject;
-class LayoutTableCell;
 class LayoutView;
 class NGPhysicalBoxFragment;
 struct PaintInfo;
@@ -34,11 +32,6 @@
       const LayoutView&,
       const PhysicalOffset& element_positioning_area_offset);
 
-  // Constructor for table cells where background_object may be the row or
-  // column the background image is attached to.
-  BackgroundImageGeometry(const LayoutTableCell&,
-                          const LayoutObject* background_object);
-
   // Generic constructor for all other elements.
   explicit BackgroundImageGeometry(const LayoutBoxModelObject&);
 
@@ -128,10 +121,6 @@
   void SetSpaceY(LayoutUnit space, LayoutUnit extra_offset);
 
   void UseFixedAttachment(const PhysicalOffset& attachment_point);
-  PhysicalOffset GetPositioningOffsetForCell(const LayoutTableCell&,
-                                             const LayoutBox&);
-  PhysicalSize GetBackgroundObjectDimensions(const LayoutTableCell&,
-                                             const LayoutBox&);
 
   // Compute adjustments for the destination rects. Adjustments
   // both optimize painting when the background is obscured by a
diff --git a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
index cca3852..49caea9b 100644
--- a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
@@ -180,8 +180,9 @@
     return PaintInvalidationReason::kLayout;
 
   // Needs to repaint frame boundaries.
-  if (box_.IsFrameSetIncludingNG())
+  if (box_.IsFrameSet()) {
     return PaintInvalidationReason::kLayout;
+  }
 
   // Needs to repaint column rules.
   if (box_.IsLayoutMultiColumnSet())
diff --git a/third_party/blink/renderer/core/paint/build.gni b/third_party/blink/renderer/core/paint/build.gni
index bd58729..4932ada0 100644
--- a/third_party/blink/renderer/core/paint/build.gni
+++ b/third_party/blink/renderer/core/paint/build.gni
@@ -32,8 +32,6 @@
   "clip_rect.cc",
   "clip_rect.h",
   "clip_rects.h",
-  "collapsed_border_painter.cc",
-  "collapsed_border_painter.h",
   "compositing/compositing_reason_finder.cc",
   "compositing/compositing_reason_finder.h",
   "css_mask_painter.cc",
@@ -62,8 +60,6 @@
   "fragment_data_iterator.h",
   "frame_painter.cc",
   "frame_painter.h",
-  "frame_set_painter.cc",
-  "frame_set_painter.h",
   "highlight_painting_utils.cc",
   "highlight_painting_utils.h",
   "hit_testing_transform_state.cc",
@@ -198,18 +194,6 @@
   "svg_root_painter.h",
   "svg_shape_painter.cc",
   "svg_shape_painter.h",
-  "table_cell_painter.cc",
-  "table_cell_painter.h",
-  "table_cell_paint_invalidator.cc",
-  "table_cell_paint_invalidator.h",
-  "table_painter.cc",
-  "table_painter.h",
-  "table_paint_invalidator.cc",
-  "table_paint_invalidator.h",
-  "table_row_painter.cc",
-  "table_row_painter.h",
-  "table_section_painter.cc",
-  "table_section_painter.h",
   "text_decoration_info.cc",
   "text_decoration_info.h",
   "text_painter_base.cc",
diff --git a/third_party/blink/renderer/core/paint/collapsed_border_painter.cc b/third_party/blink/renderer/core/paint/collapsed_border_painter.cc
deleted file mode 100644
index f40da85..0000000
--- a/third_party/blink/renderer/core/paint/collapsed_border_painter.cc
+++ /dev/null
@@ -1,403 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// 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/core/paint/collapsed_border_painter.h"
-
-#include "third_party/blink/renderer/core/paint/block_painter.h"
-#include "third_party/blink/renderer/core/paint/box_border_painter.h"
-#include "third_party/blink/renderer/core/paint/paint_auto_dark_mode.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
-#include "third_party/blink/renderer/core/paint/table_cell_painter.h"
-
-namespace blink {
-
-void CollapsedBorderPainter::SetupBorders() {
-  const auto* values = cell_.GetCollapsedBorderValues();
-  DCHECK(values);
-  if (values->StartBorder().IsVisible()) {
-    start_.value = &values->StartBorder();
-    start_.inner_width = cell_.CollapsedInnerBorderStart();
-    start_.outer_width = cell_.CollapsedOuterBorderStart();
-  } else {
-    start_.value = nullptr;
-  }
-
-  if (values->EndBorder().IsVisible()) {
-    end_.value = &values->EndBorder();
-    end_.inner_width = cell_.CollapsedInnerBorderEnd();
-    end_.outer_width = cell_.CollapsedOuterBorderEnd();
-  } else {
-    end_.value = nullptr;
-  }
-
-  if (values->BeforeBorder().IsVisible()) {
-    before_.value = &values->BeforeBorder();
-    before_.inner_width = cell_.CollapsedInnerBorderBefore();
-    before_.outer_width = cell_.CollapsedOuterBorderBefore();
-  } else {
-    before_.value = nullptr;
-  }
-
-  if (values->AfterBorder().IsVisible()) {
-    after_.value = &values->AfterBorder();
-    after_.inner_width = cell_.CollapsedInnerBorderAfter();
-    after_.outer_width = cell_.CollapsedOuterBorderAfter();
-  } else {
-    after_.value = nullptr;
-  }
-
-  // At first, let all borders paint the joints. This is to keep the current
-  // behavior for web tests e.g. css2.1/t170602-bdr-conflict-w-01-d.html.
-  // TODO(crbug.com/672216): Determine the best way to deal with this.
-  if (start_.value && before_.value) {
-    start_.begin_outset = before_.outer_width;
-    before_.begin_outset = start_.outer_width;
-  }
-  if (end_.value && before_.value) {
-    end_.begin_outset = before_.outer_width;
-    before_.end_outset = end_.outer_width;
-  }
-  if (start_.value && after_.value) {
-    start_.end_outset = after_.outer_width;
-    after_.begin_outset = start_.outer_width;
-  }
-  if (after_.value && end_.value) {
-    end_.end_outset = after_.outer_width;
-    after_.end_outset = end_.outer_width;
-  }
-
-  // TODO(crbug.com/727173): We have a lot of bugs about mixed row direction.
-  // Just bail out not to optimize duplicated borders.
-  if (!cell_.Row()->HasSameDirectionAs(&table_) ||
-      !cell_.Section()->HasSameDirectionAs(&table_))
-    return;
-
-  // Skip painting the start border if it will be painted by the preceding cell
-  // as its end border.
-  if (start_.value) {
-    const auto* cell_preceding = table_.CellPreceding(cell_);
-    if (cell_.StartsAtSameRow(cell_preceding) &&
-        cell_preceding->ResolvedRowSpan() >= cell_.ResolvedRowSpan() &&
-        // |cell_preceding| didn't paint the border if it is invisible.
-        cell_preceding->StyleRef().Visibility() == EVisibility::kVisible) {
-      start_.value = nullptr;
-      // Otherwise we'll still paint the shared border twice which may cause
-      // incorrect border conflict resolution for row/col spanning cells.
-      // TODO(crbug.com/2902 etc.): Paint collapsed borders by grid cells.
-    }
-  }
-
-  // Skip painting the before border if it will be painted by the above cell
-  // as its after border. If we break page before the row with non-zero strut
-  // (which means a gap between this row and the row above), or if we are
-  // painting the top row of a footer that repeats on each page we need to paint
-  // the before border separately.
-  // TODO(crbug.com/751177) : This will double-paint the top border of the
-  // footer on the last page.
-  if (before_.value && !cell_.Row()->PaginationStrut()) {
-    const auto* cell_above = table_.CellAbove(cell_);
-    if (cell_.StartsAtSameColumn(cell_above) &&
-        cell_above->ColSpan() >= cell_.ColSpan() &&
-        // |cell_above| didn't paint the border if it is invisible.
-        cell_above->StyleRef().Visibility() == EVisibility::kVisible &&
-        cell_above->Row()->HasSameDirectionAs(&table_)) {
-      bool cell_is_top_of_repeating_footer =
-          cell_.Section()->IsRepeatingFooterGroup() &&
-          (!cell_above || cell_above->Section() != cell_.Section());
-      if (!cell_is_top_of_repeating_footer)
-        before_.value = nullptr;
-      // Otherwise we'll still paint the shared border twice which may cause
-      // incorrect border conflict resolution for row/col spanning cells.
-      // TODO(crbug.com/2902 etc.): Paint collapsed borders by grid cells.
-    }
-  }
-}
-
-static const CollapsedBorderValues* GetCollapsedBorderValues(
-    const LayoutTableCell* cell) {
-  return cell ? cell->GetCollapsedBorderValues() : nullptr;
-}
-
-void CollapsedBorderPainter::AdjustJoints() {
-  // TODO(crbug.com/727173): We have a lot of bugs about mixed row direction.
-  // Just bail out not to adjust the joints.
-  if (!cell_.Row()->HasSameDirectionAs(&table_) ||
-      !cell_.Section()->HasSameDirectionAs(&table_))
-    return;
-
-  // If we break page before the row with non-zero strut, we need to paint the
-  // before border as if there is no cell above.
-  const auto* cell_above =
-      cell_.Row()->PaginationStrut() ? nullptr : table_.CellAbove(cell_);
-  if (cell_above && (!cell_above->Row()->HasSameDirectionAs(&table_) ||
-                     !cell_above->Section()->HasSameDirectionAs(&table_)))
-    cell_above = nullptr;
-
-  const auto* cell_below = table_.CellBelow(cell_);
-  if (cell_below && (!cell_below->Row()->HasSameDirectionAs(&table_) ||
-                     !cell_below->Section()->HasSameDirectionAs(&table_)))
-    cell_above = nullptr;
-
-  const auto* cell_preceding = table_.CellPreceding(cell_);
-  const auto* cell_following = table_.CellFollowing(cell_);
-
-  const auto* borders_preceding = GetCollapsedBorderValues(cell_preceding);
-  const auto* borders_following = GetCollapsedBorderValues(cell_following);
-  const auto* borders_above = GetCollapsedBorderValues(cell_above);
-  const auto* borders_below = GetCollapsedBorderValues(cell_below);
-
-  // These variables indicate whether |cell_| forms joints at the corners
-  // with the borders of the adjacent cells. For example,
-  // |before_start_adjoins_preceding| indicates that |cell_| shares the
-  // before-start (logical top-left) corner with |cell_preceding_|.
-  bool before_start_adjoins_preceding =
-      borders_preceding && cell_.StartsAtSameRow(cell_preceding);
-  bool before_start_adjoins_above =
-      borders_above && cell_.StartsAtSameColumn(cell_above);
-  bool before_end_adjoins_above =
-      borders_above && cell_.EndsAtSameColumn(cell_above);
-  bool before_end_adjoins_following =
-      borders_following && cell_.StartsAtSameRow(cell_following);
-  bool after_end_adjoins_following =
-      borders_following && cell_.EndsAtSameRow(cell_following);
-  bool after_end_adjoins_below =
-      borders_below && cell_.EndsAtSameColumn(cell_below);
-  bool after_start_adjoins_below =
-      borders_below && cell_.StartsAtSameColumn(cell_below);
-  bool after_start_adjoins_preceding =
-      borders_preceding && cell_.EndsAtSameRow(cell_preceding);
-
-  if (start_.value) {
-    if (start_.value->CoversJoint(
-            before_.value,
-            before_start_adjoins_preceding ? &borders_preceding->BeforeBorder()
-                                           : nullptr,
-            before_start_adjoins_above ? &borders_above->StartBorder()
-                                       : nullptr)) {
-      if (before_start_adjoins_preceding) {
-        start_.begin_outset = std::max<int>(
-            start_.begin_outset, cell_preceding->CollapsedOuterBorderBefore());
-      }
-    } else {
-      start_.begin_outset =
-          -std::max<int>(cell_.CollapsedInnerBorderBefore(),
-                         before_start_adjoins_preceding
-                             ? cell_preceding->CollapsedInnerBorderBefore()
-                             : 0);
-    }
-    if (start_.value->CoversJoint(
-            after_.value,
-            after_start_adjoins_preceding ? &borders_preceding->AfterBorder()
-                                          : nullptr,
-            after_start_adjoins_below ? &borders_below->StartBorder()
-                                      : nullptr)) {
-      if (after_start_adjoins_preceding) {
-        start_.end_outset = std::max<int>(
-            start_.end_outset, cell_preceding->CollapsedOuterBorderAfter());
-      }
-    } else {
-      start_.end_outset =
-          -std::max<int>(cell_.CollapsedInnerBorderAfter(),
-                         after_start_adjoins_preceding
-                             ? cell_preceding->CollapsedInnerBorderAfter()
-                             : 0);
-    }
-  }
-
-  if (end_.value) {
-    if (end_.value->CoversJoint(
-            before_.value,
-            before_end_adjoins_following ? &borders_following->BeforeBorder()
-                                         : nullptr,
-            before_end_adjoins_above ? &borders_above->EndBorder() : nullptr)) {
-      if (before_end_adjoins_following) {
-        end_.begin_outset = std::max<int>(
-            end_.begin_outset, cell_following->CollapsedOuterBorderBefore());
-      }
-    } else {
-      end_.begin_outset =
-          -std::max<int>(cell_.CollapsedInnerBorderBefore(),
-                         before_end_adjoins_following
-                             ? cell_following->CollapsedInnerBorderBefore()
-                             : 0);
-    }
-    if (end_.value->CoversJoint(
-            after_.value,
-            after_end_adjoins_following ? &borders_following->AfterBorder()
-                                        : nullptr,
-            after_end_adjoins_below ? &borders_below->EndBorder() : nullptr)) {
-      if (after_end_adjoins_following) {
-        end_.end_outset = std::max<int>(
-            end_.end_outset, cell_following->CollapsedOuterBorderAfter());
-      }
-    } else {
-      end_.end_outset =
-          -std::max<int>(cell_.CollapsedInnerBorderAfter(),
-                         after_end_adjoins_following
-                             ? cell_following->CollapsedInnerBorderAfter()
-                             : 0);
-    }
-  }
-
-  if (before_.value) {
-    if (before_.value->CoversJoint(
-            start_.value,
-            before_start_adjoins_preceding ? &borders_preceding->BeforeBorder()
-                                           : nullptr,
-            before_start_adjoins_above ? &borders_above->StartBorder()
-                                       : nullptr)) {
-      if (before_start_adjoins_above) {
-        before_.begin_outset = std::max<int>(
-            before_.begin_outset, cell_above->CollapsedOuterBorderStart());
-      }
-    } else {
-      before_.begin_outset = -std::max<int>(
-          cell_.CollapsedInnerBorderStart(),
-          before_start_adjoins_above ? cell_above->CollapsedInnerBorderStart()
-                                     : 0);
-    }
-    if (before_.value->CoversJoint(
-            end_.value,
-            before_end_adjoins_following ? &borders_following->BeforeBorder()
-                                         : nullptr,
-            before_end_adjoins_above ? &borders_above->EndBorder() : nullptr)) {
-      if (before_end_adjoins_above) {
-        before_.end_outset = std::max<int>(
-            before_.end_outset, cell_above->CollapsedOuterBorderEnd());
-      }
-    } else {
-      before_.end_outset = -std::max<int>(
-          cell_.CollapsedInnerBorderEnd(),
-          before_end_adjoins_above ? cell_above->CollapsedInnerBorderEnd() : 0);
-    }
-  }
-
-  if (after_.value) {
-    if (after_.value->CoversJoint(
-            start_.value,
-            after_start_adjoins_preceding ? &borders_preceding->AfterBorder()
-                                          : nullptr,
-            after_start_adjoins_below ? &borders_below->StartBorder()
-                                      : nullptr)) {
-      if (after_start_adjoins_below) {
-        after_.begin_outset = std::max<int>(
-            after_.begin_outset, cell_below->CollapsedOuterBorderStart());
-      }
-    } else {
-      after_.begin_outset = -std::max<int>(
-          cell_.CollapsedInnerBorderStart(),
-          after_start_adjoins_below ? cell_below->CollapsedInnerBorderStart()
-                                    : 0);
-    }
-    if (after_.value->CoversJoint(
-            end_.value,
-            after_end_adjoins_following ? &borders_following->AfterBorder()
-                                        : nullptr,
-            after_end_adjoins_below ? &borders_below->EndBorder() : nullptr)) {
-      if (after_end_adjoins_below) {
-        after_.end_outset = std::max<int>(
-            after_.end_outset, cell_below->CollapsedOuterBorderEnd());
-      }
-    } else {
-      after_.end_outset = -std::max<int>(
-          cell_.CollapsedInnerBorderEnd(),
-          after_end_adjoins_below ? cell_below->CollapsedInnerBorderEnd() : 0);
-    }
-  }
-}
-
-void CollapsedBorderPainter::AdjustForWritingModeAndDirection() {
-  const auto& style = cell_.TableStyle();
-  if (!style.IsLeftToRightDirection()) {
-    std::swap(start_, end_);
-    std::swap(before_.begin_outset, before_.end_outset);
-    std::swap(after_.begin_outset, after_.end_outset);
-  }
-  if (!style.IsHorizontalWritingMode()) {
-    std::swap(after_, end_);
-    std::swap(before_, start_);
-    if (style.IsFlippedBlocksWritingMode()) {
-      std::swap(start_, end_);
-      std::swap(before_.begin_outset, before_.end_outset);
-      std::swap(after_.begin_outset, after_.end_outset);
-    }
-  }
-}
-
-static EBorderStyle CollapsedBorderStyle(EBorderStyle style) {
-  if (style == EBorderStyle::kOutset)
-    return EBorderStyle::kGroove;
-  if (style == EBorderStyle::kInset)
-    return EBorderStyle::kRidge;
-  return style;
-}
-
-void CollapsedBorderPainter::PaintCollapsedBorders(
-    const PaintInfo& paint_info) {
-  if (cell_.StyleRef().Visibility() != EVisibility::kVisible)
-    return;
-
-  if (!cell_.GetCollapsedBorderValues())
-    return;
-
-  GraphicsContext& context = paint_info.context;
-
-  SetupBorders();
-  if (table_.NeedsAdjustCollapsedBorderJoints())
-    AdjustJoints();
-  AdjustForWritingModeAndDirection();
-  // Now left=start_, right=end_, before_=top, after_=bottom.
-
-  // Collapsed borders are half inside and half outside of |rect|.
-  ScopedPaintState paint_state(
-      cell_, paint_info, /*painting_legacy_table_part_in_ancestor_layer*/ true);
-  gfx::Rect rect = ToPixelSnappedRect(
-      TableCellPainter(cell_).PaintRectNotIncludingVisualOverflow(
-          paint_state.PaintOffset()));
-
-  AutoDarkMode auto_dark_mode(PaintAutoDarkMode(
-      cell_.StyleRef(), DarkModeFilter::ElementRole::kBorder));
-
-  // We never paint diagonals at the joins.  We simply let the border with the
-  // highest precedence paint on top of borders with lower precedence.
-  if (before_.value) {
-    gfx::Rect edge_rect(
-        rect.x() - before_.begin_outset, rect.y() - before_.outer_width,
-        rect.width() + before_.begin_outset + before_.end_outset,
-        before_.outer_width + before_.inner_width);
-    BoxBorderPainter::DrawBoxSide(
-        context, edge_rect, BoxSide::kTop, before_.value->GetColor(),
-        CollapsedBorderStyle(before_.value->Style()), auto_dark_mode);
-  }
-  if (after_.value) {
-    gfx::Rect edge_rect(rect.x() - after_.begin_outset,
-                        rect.bottom() - after_.inner_width,
-                        rect.width() + after_.begin_outset + after_.end_outset,
-                        after_.inner_width + after_.outer_width);
-    BoxBorderPainter::DrawBoxSide(
-        context, edge_rect, BoxSide::kBottom, after_.value->GetColor(),
-        CollapsedBorderStyle(after_.value->Style()), auto_dark_mode);
-  }
-  if (start_.value) {
-    gfx::Rect edge_rect(
-        rect.x() - start_.outer_width, rect.y() - start_.begin_outset,
-        start_.outer_width + start_.inner_width,
-        rect.height() + start_.begin_outset + start_.end_outset);
-    BoxBorderPainter::DrawBoxSide(
-        context, edge_rect, BoxSide::kLeft, start_.value->GetColor(),
-        CollapsedBorderStyle(start_.value->Style()), auto_dark_mode);
-  }
-  if (end_.value) {
-    gfx::Rect edge_rect(rect.right() - end_.inner_width,
-                        rect.y() - end_.begin_outset,
-                        end_.inner_width + end_.outer_width,
-                        rect.height() + end_.begin_outset + end_.end_outset);
-    BoxBorderPainter::DrawBoxSide(
-        context, edge_rect, BoxSide::kRight, end_.value->GetColor(),
-        CollapsedBorderStyle(end_.value->Style()), auto_dark_mode);
-  }
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/collapsed_border_painter.h b/third_party/blink/renderer/core/paint/collapsed_border_painter.h
deleted file mode 100644
index f827c05..0000000
--- a/third_party/blink/renderer/core/paint/collapsed_border_painter.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// 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_CORE_PAINT_COLLAPSED_BORDER_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_COLLAPSED_BORDER_PAINTER_H_
-
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-struct PaintInfo;
-
-class CollapsedBorderPainter {
-  STACK_ALLOCATED();
-
- public:
-  CollapsedBorderPainter(const LayoutTableCell& cell)
-      : cell_(cell), table_(*cell.Table()) {}
-
-  void PaintCollapsedBorders(const PaintInfo&);
-
- private:
-  void SetupBorders();
-  void AdjustJoints();
-  void AdjustForWritingModeAndDirection();
-
-  const LayoutTableCell& cell_;
-  const LayoutTable& table_;
-
-  struct Border {
-    STACK_ALLOCATED();
-
-   public:
-    // This will be set to null if we don't need to paint this border.
-    const CollapsedBorderValue* value = nullptr;
-    int inner_width = 0;
-    int outer_width = 0;
-    // We may paint the border not in full length if the corner is covered by
-    // another higher priority border. The following are the outsets from the
-    // border box of the begin and end points of the painted segment.
-    int begin_outset = 0;
-    int end_outset = 0;
-  };
-  Border start_;
-  Border end_;
-  Border before_;
-  Border after_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_COLLAPSED_BORDER_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/frame_set_painter.cc b/third_party/blink/renderer/core/paint/frame_set_painter.cc
deleted file mode 100644
index fe5e04a..0000000
--- a/third_party/blink/renderer/core/paint/frame_set_painter.cc
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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/core/paint/frame_set_painter.h"
-
-#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
-#include "third_party/blink/renderer/core/html/html_frame_set_element.h"
-#include "third_party/blink/renderer/core/layout/layout_frame_set.h"
-#include "third_party/blink/renderer/core/paint/box_painter.h"
-#include "third_party/blink/renderer/core/paint/paint_auto_dark_mode.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
-#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
-
-namespace blink {
-
-static Color BorderStartEdgeColor() {
-  return Color(170, 170, 170);
-}
-
-static Color BorderEndEdgeColor() {
-  return Color::kBlack;
-}
-
-static Color BorderFillColor() {
-  return Color(208, 208, 208);
-}
-
-void FrameSetPainter::PaintColumnBorder(const PaintInfo& paint_info,
-                                        const gfx::Rect& border_rect) {
-  if (!paint_info.GetCullRect().Intersects(border_rect))
-    return;
-
-  // FIXME: We should do something clever when borders from distinct framesets
-  // meet at a join.
-
-  AutoDarkMode auto_dark_mode(PaintAutoDarkMode(
-      layout_frame_set_.StyleRef(), DarkModeFilter::ElementRole::kBorder));
-
-  // Fill first.
-  GraphicsContext& context = paint_info.context;
-  context.FillRect(
-      border_rect,
-      layout_frame_set_.FrameSet()->HasBorderColor()
-          ? layout_frame_set_.ResolveColor(GetCSSPropertyBorderLeftColor())
-          : BorderFillColor(),
-      auto_dark_mode);
-
-  // Now stroke the edges but only if we have enough room to paint both edges
-  // with a little bit of the fill color showing through.
-  if (border_rect.width() >= 3) {
-    context.FillRect(
-        gfx::Rect(border_rect.origin(), gfx::Size(1, border_rect.height())),
-        BorderStartEdgeColor(), auto_dark_mode);
-    context.FillRect(
-        gfx::Rect(gfx::Point(border_rect.right() - 1, border_rect.y()),
-                  gfx::Size(1, border_rect.height())),
-        BorderEndEdgeColor(), auto_dark_mode);
-  }
-}
-
-void FrameSetPainter::PaintRowBorder(const PaintInfo& paint_info,
-                                     const gfx::Rect& border_rect) {
-  // FIXME: We should do something clever when borders from distinct framesets
-  // meet at a join.
-
-  AutoDarkMode auto_dark_mode(PaintAutoDarkMode(
-      layout_frame_set_.StyleRef(), DarkModeFilter::ElementRole::kBorder));
-
-  // Fill first.
-  GraphicsContext& context = paint_info.context;
-  context.FillRect(
-      border_rect,
-      layout_frame_set_.FrameSet()->HasBorderColor()
-          ? layout_frame_set_.ResolveColor(GetCSSPropertyBorderLeftColor())
-          : BorderFillColor(),
-      auto_dark_mode);
-
-  // Now stroke the edges but only if we have enough room to paint both edges
-  // with a little bit of the fill color showing through.
-  if (border_rect.height() >= 3) {
-    context.FillRect(
-        gfx::Rect(border_rect.origin(), gfx::Size(border_rect.width(), 1)),
-        BorderStartEdgeColor(), auto_dark_mode);
-    context.FillRect(
-        gfx::Rect(gfx::Point(border_rect.x(), border_rect.bottom() - 1),
-                  gfx::Size(border_rect.width(), 1)),
-        BorderEndEdgeColor(), auto_dark_mode);
-  }
-}
-
-static bool ShouldPaintBorderAfter(const LayoutFrameSet::GridAxis& axis,
-                                   wtf_size_t index) {
-  // Should not paint a border after the last frame along the axis.
-  return index + 1 < axis.sizes_.size() && axis.allow_border_[index + 1];
-}
-
-void FrameSetPainter::PaintBorders(const PaintInfo& paint_info,
-                                   const PhysicalOffset& paint_offset) {
-  if (DrawingRecorder::UseCachedDrawingIfPossible(
-          paint_info.context, layout_frame_set_, paint_info.phase))
-    return;
-
-  BoxDrawingRecorder recorder(paint_info.context, layout_frame_set_,
-                              paint_info.phase, paint_offset);
-
-  LayoutUnit border_thickness(
-      layout_frame_set_.FrameSet()->Border(layout_frame_set_.StyleRef()));
-  if (!border_thickness)
-    return;
-
-  LayoutObject* child = layout_frame_set_.FirstChild();
-  wtf_size_t rows = layout_frame_set_.Rows().sizes_.size();
-  wtf_size_t cols = layout_frame_set_.Columns().sizes_.size();
-  LayoutUnit y_pos;
-  for (wtf_size_t r = 0; r < rows; r++) {
-    LayoutUnit x_pos;
-    for (wtf_size_t c = 0; c < cols; c++) {
-      x_pos += layout_frame_set_.Columns().sizes_[c];
-      if (ShouldPaintBorderAfter(layout_frame_set_.Columns(), c)) {
-        PaintColumnBorder(
-            paint_info,
-            ToPixelSnappedRect(PhysicalRect(
-                paint_offset.left + x_pos, paint_offset.top + y_pos,
-                border_thickness, layout_frame_set_.Size().Height() - y_pos)));
-        x_pos += border_thickness;
-      }
-      child = child->NextSibling();
-      if (!child)
-        return;
-    }
-    y_pos += layout_frame_set_.Rows().sizes_[r];
-    if (ShouldPaintBorderAfter(layout_frame_set_.Rows(), r)) {
-      PaintRowBorder(paint_info,
-                     ToPixelSnappedRect(PhysicalRect(
-                         paint_offset.left, paint_offset.top + y_pos,
-                         layout_frame_set_.Size().Width(), border_thickness)));
-      y_pos += border_thickness;
-    }
-  }
-}
-
-void FrameSetPainter::PaintChildren(const PaintInfo& paint_info) {
-  if (paint_info.DescendantPaintingBlocked())
-    return;
-
-  // Paint only those children that fit in the grid.
-  // Remaining frames are "hidden".
-  // See also LayoutFrameSet::positionFrames.
-  LayoutObject* child = layout_frame_set_.FirstChild();
-  size_t rows = layout_frame_set_.Rows().sizes_.size();
-  size_t cols = layout_frame_set_.Columns().sizes_.size();
-  for (size_t r = 0; r < rows; r++) {
-    for (size_t c = 0; c < cols; c++) {
-      // Self-painting layers are painted during the PaintLayer paint recursion,
-      // not LayoutObject.
-      if (!child->IsBoxModelObject() ||
-          !To<LayoutBoxModelObject>(child)->HasSelfPaintingLayer())
-        child->Paint(paint_info);
-      child = child->NextSibling();
-      if (!child)
-        return;
-    }
-  }
-}
-
-void FrameSetPainter::Paint(const PaintInfo& paint_info) {
-  if (paint_info.phase != PaintPhase::kForeground)
-    return;
-
-  if (!layout_frame_set_.FirstChild())
-    return;
-
-  if (layout_frame_set_.StyleRef().Visibility() != EVisibility::kVisible)
-    return;
-
-  ScopedPaintState paint_state(layout_frame_set_, paint_info);
-  const auto& local_paint_info = paint_state.GetPaintInfo();
-  PaintChildren(local_paint_info);
-  PaintBorders(local_paint_info, paint_state.PaintOffset());
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/frame_set_painter.h b/third_party/blink/renderer/core/paint/frame_set_painter.h
deleted file mode 100644
index e897b79..0000000
--- a/third_party/blink/renderer/core/paint/frame_set_painter.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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_CORE_PAINT_FRAME_SET_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FRAME_SET_PAINTER_H_
-
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace gfx {
-class Rect;
-}
-
-namespace blink {
-
-class LayoutFrameSet;
-struct PaintInfo;
-struct PhysicalOffset;
-
-class FrameSetPainter {
-  STACK_ALLOCATED();
-
- public:
-  FrameSetPainter(const LayoutFrameSet& layout_frame_set)
-      : layout_frame_set_(layout_frame_set) {}
-
-  void Paint(const PaintInfo&);
-
- private:
-  void PaintBorders(const PaintInfo&, const PhysicalOffset& paint_offset);
-  void PaintChildren(const PaintInfo&);
-  void PaintRowBorder(const PaintInfo&, const gfx::Rect&);
-  void PaintColumnBorder(const PaintInfo&, const gfx::Rect&);
-
-  const LayoutFrameSet& layout_frame_set_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FRAME_SET_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index b23c11c..e54eca09 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -14,7 +14,6 @@
 #include "third_party/blink/renderer/core/layout/hit_test_location.h"
 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
 #include "third_party/blink/renderer/core/layout/layout_inline.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
@@ -26,6 +25,8 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_outline_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
 #include "third_party/blink/renderer/core/layout/pointer_events_hit_rules.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/paint/background_image_geometry.h"
@@ -1823,8 +1824,6 @@
 }
 
 LayoutRectOutsets NGBoxFragmentPainter::ComputeBorders() const {
-  if (box_fragment_.GetLayoutObject()->IsTableCellLegacy())
-    return To<LayoutBox>(box_fragment_.GetLayoutObject())->BorderBoxOutsets();
   return PhysicalFragment().Borders().ToLayoutRectOutsets();
 }
 
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
index a098243..9d6293a6 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
@@ -12,12 +12,12 @@
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/layout/geometry/logical_rect.h"
 #include "third_party/blink/renderer/core/layout/layout_counter.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_run.h"
-#include "third_party/blink/renderer/core/layout/layout_ruby_text.h"
 #include "third_party/blink/renderer/core/layout/list_marker.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
@@ -127,7 +127,7 @@
   const LayoutObject* parent = containing_block->Parent();
   if (!parent || !parent->IsRubyRun())
     return true;
-  const LayoutRubyText* ruby_text = To<LayoutRubyRun>(parent)->RubyText();
+  const auto* ruby_text = To<LayoutNGRubyRun>(parent)->RubyText();
   if (!ruby_text)
     return true;
   if (!NGInlineCursor(*ruby_text))
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.cc b/third_party/blink/renderer/core/paint/paint_invalidator.cc
index cc8f00e..8da75aab 100644
--- a/third_party/blink/renderer/core/paint/paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -13,8 +13,6 @@
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/layout/layout_block_flow.h"
 #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
 #include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index b2fb2d5..5470f3a 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -653,17 +653,11 @@
     // nearest enclosing object with a layer.
     LayoutObject* curr = GetLayoutObject().Container();
     while (curr && !curr->HasLayer()) {
-      if (curr->IsBox() && !curr->IsLegacyTableRow()) {
-        // Rows and cells share the same coordinate space (that of the section).
-        // Omit them when computing our xpos/ypos.
+      if (curr->IsBox()) {
         local_point += To<LayoutBox>(curr)->PhysicalLocation();
       }
       curr = curr->Container();
     }
-    if (curr && curr->IsLegacyTableRow()) {
-      // Put ourselves into the row coordinate space.
-      local_point -= To<LayoutBox>(curr)->PhysicalLocation();
-    }
   }
 
   if (PaintLayer* containing_layer = ContainingLayer()) {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 65781d0..9bc0564 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -1554,7 +1554,7 @@
   if (VisualViewportSuppliesScrollbars() ||
       !CanHaveOverflowScrollbars(*GetLayoutBox()) ||
       GetLayoutBox()->GetFrame()->GetSettings()->GetHideScrollbars() ||
-      GetLayoutBox()->IsFieldset() || GetLayoutBox()->IsLayoutNGFrameSet() ||
+      GetLayoutBox()->IsFieldset() || GetLayoutBox()->IsFrameSet() ||
       GetLayoutBox()->StyleRef().ScrollbarWidth() == EScrollbarWidth::kNone) {
     needs_horizontal_scrollbar = false;
     needs_vertical_scrollbar = false;
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index a94d555..ed13c4d 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -29,14 +29,15 @@
 #include "third_party/blink/renderer/core/layout/layout_inline.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_replaced.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
 #include "third_party/blink/renderer/core/layout/layout_video.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h"
+#include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h"
@@ -2941,16 +2942,6 @@
       // can be stored on PaintPropertyTreeBuilderFragmentContext instead of
       // recomputing them.
       context_.current.paint_offset += box->PhysicalLocation();
-
-      // This is a weird quirk that table cells paint as children of table rows,
-      // but their location have the row's location baked-in.
-      // Similar adjustment is done in LayoutTableCell::offsetFromContainer().
-      if (object_.IsTableCellLegacy()) {
-        LayoutObject* parent_row = object_.Parent();
-        DCHECK(parent_row && parent_row->IsTableRow());
-        context_.current.paint_offset -=
-            To<LayoutBox>(parent_row)->PhysicalLocation();
-      }
     }
   }
 
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
index f993781..925d4a1 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -15,8 +15,6 @@
 #include "third_party/blink/renderer/core/layout/layout_flow_thread.h"
 #include "third_party/blink/renderer/core/layout/layout_image.h"
 #include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
 #include "third_party/blink/renderer/core/layout/layout_tree_as_text.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
diff --git a/third_party/blink/renderer/core/paint/replaced_painter.cc b/third_party/blink/renderer/core/paint/replaced_painter.cc
index c01f239..c16a9d6 100644
--- a/third_party/blink/renderer/core/paint/replaced_painter.cc
+++ b/third_party/blink/renderer/core/paint/replaced_painter.cc
@@ -99,8 +99,9 @@
     const PaintInfo& paint_info) {
   // LayoutFrameSet paints everything in the foreground phase.
   if (layout_replaced_.IsLayoutEmbeddedContent() &&
-      layout_replaced_.Parent()->IsFrameSetIncludingNG())
+      layout_replaced_.Parent()->IsFrameSet()) {
     return paint_info.phase == PaintPhase::kForeground;
+  }
   return ShouldPaintSelfBlockBackground(paint_info.phase);
 }
 
diff --git a/third_party/blink/renderer/core/paint/scoped_paint_state.cc b/third_party/blink/renderer/core/paint/scoped_paint_state.cc
index 46505bdab..ad5b9a6 100644
--- a/third_party/blink/renderer/core/paint/scoped_paint_state.cc
+++ b/third_party/blink/renderer/core/paint/scoped_paint_state.cc
@@ -12,11 +12,9 @@
 
 namespace blink {
 
-ScopedPaintState::ScopedPaintState(
-    const LayoutObject& object,
-    const PaintInfo& paint_info,
-    const FragmentData* fragment_data,
-    bool painting_legacy_table_part_in_ancestor_layer)
+ScopedPaintState::ScopedPaintState(const LayoutObject& object,
+                                   const PaintInfo& paint_info,
+                                   const FragmentData* fragment_data)
     : fragment_to_paint_(fragment_data), input_paint_info_(paint_info) {
   if (!fragment_to_paint_) {
     // The object has nothing to paint in the current fragment.
@@ -28,12 +26,9 @@
   }
 
   paint_offset_ = fragment_to_paint_->PaintOffset();
-  if (painting_legacy_table_part_in_ancestor_layer) {
-    DCHECK(object.IsTableCellLegacy() || object.IsLegacyTableRow() ||
-           object.IsLegacyTableSection());
-  } else if (paint_info.phase == PaintPhase::kOverlayOverflowControls ||
-             (object.HasLayer() &&
-              To<LayoutBoxModelObject>(object).HasSelfPaintingLayer())) {
+  if (paint_info.phase == PaintPhase::kOverlayOverflowControls ||
+      (object.HasLayer() &&
+       To<LayoutBoxModelObject>(object).HasSelfPaintingLayer())) {
     // PaintLayerPainter already adjusted for PaintOffsetTranslation for
     // PaintContainer.
     return;
diff --git a/third_party/blink/renderer/core/paint/scoped_paint_state.h b/third_party/blink/renderer/core/paint/scoped_paint_state.h
index c492c70f..0fa8f40b 100644
--- a/third_party/blink/renderer/core/paint/scoped_paint_state.h
+++ b/third_party/blink/renderer/core/paint/scoped_paint_state.h
@@ -28,24 +28,12 @@
   STACK_ALLOCATED();
 
  public:
-  // If |paint_legacy_table_part_in_ancestor_layer| is true, we'll
-  // unconditionally apply PaintOffsetTranslation adjustment. For self-painting
-  // layers, this adjustment is typically applied by PaintLayerPainter rather
-  // than ScopedPaintState, but legacy tables table parts sometimes paint into
-  // ancestor's self-painting layer instead of their own.
-  // TODO(layout-dev): Remove this parameter when removing legacy table classes.
-  ScopedPaintState(const LayoutObject&,
-                   const PaintInfo&,
-                   const FragmentData*,
-                   bool painting_legacy_table_part_in_ancestor_layer = false);
+  ScopedPaintState(const LayoutObject&, const PaintInfo&, const FragmentData*);
 
-  ScopedPaintState(const LayoutObject& object,
-                   const PaintInfo& paint_info,
-                   bool painting_legacy_table_part_in_ancestor_layer = false)
+  ScopedPaintState(const LayoutObject& object, const PaintInfo& paint_info)
       : ScopedPaintState(object,
                          paint_info,
-                         paint_info.FragmentToPaint(object),
-                         painting_legacy_table_part_in_ancestor_layer) {}
+                         paint_info.FragmentToPaint(object)) {}
 
   ScopedPaintState(const NGPhysicalFragment& fragment,
                    const PaintInfo& paint_info)
diff --git a/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc b/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc
deleted file mode 100644
index 6fdc40b..0000000
--- a/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// 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/core/paint/table_cell_paint_invalidator.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-#include "third_party/blink/renderer/core/paint/block_paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-
-namespace blink {
-
-static bool DisplayItemClientIsFullyInvalidated(
-    const DisplayItemClient& client) {
-  return IsFullPaintInvalidationReason(client.GetPaintInvalidationReason());
-}
-
-void TableCellPaintInvalidator::InvalidateContainerForCellGeometryChange(
-    const LayoutObject& container,
-    const PaintInvalidatorContext& container_context) {
-  // We only need to do this if the container hasn't been fully invalidated.
-  DCHECK(!DisplayItemClientIsFullyInvalidated(container));
-
-  // At this time we have already walked the container for paint invalidation,
-  // so we should invalidate the container immediately here instead of setting
-  // paint invalidation flags.
-  container_context.painting_layer->SetNeedsRepaint();
-  container.InvalidateDisplayItemClients(PaintInvalidationReason::kLayout);
-}
-
-void TableCellPaintInvalidator::InvalidatePaint() {
-  // The cell's containing row and section paint backgrounds behind the cell,
-  // and the row or table paints collapsed borders. If the cell's geometry
-  // changed and the containers which will paint backgrounds and/or collapsed
-  // borders haven't been full invalidated, invalidate the containers.
-  if (context_.old_paint_offset != context_.fragment_data->PaintOffset() ||
-      cell_.Size() != cell_.PreviousSize()) {
-    const auto& row = *cell_.Row();
-    const auto& section = *row.Section();
-    const auto& table = *section.Table();
-    if (!DisplayItemClientIsFullyInvalidated(row) &&
-        (row.StyleRef().HasBackground() || table.HasCollapsedBorders())) {
-      InvalidateContainerForCellGeometryChange(row, *context_.ParentContext());
-      // Mark the table as needing repaint, in order to paint collapsed borders.
-      context_.ParentContext()
-          ->ParentContext()
-          ->ParentContext()
-          ->painting_layer->SetNeedsRepaint();
-    }
-
-    if (!DisplayItemClientIsFullyInvalidated(section)) {
-      bool section_paints_background = section.StyleRef().HasBackground();
-      if (!section_paints_background) {
-        auto col_and_colgroup = section.Table()->ColElementAtAbsoluteColumn(
-            cell_.AbsoluteColumnIndex());
-        if ((col_and_colgroup.col &&
-             col_and_colgroup.col->StyleRef().HasBackground()) ||
-            (col_and_colgroup.colgroup &&
-             col_and_colgroup.colgroup->StyleRef().HasBackground()))
-          section_paints_background = true;
-      }
-      if (section_paints_background) {
-        InvalidateContainerForCellGeometryChange(
-            section, *context_.ParentContext()->ParentContext());
-      }
-    }
-  }
-
-  BlockPaintInvalidator(cell_).InvalidatePaint(context_);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.h b/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.h
deleted file mode 100644
index 864ea76..0000000
--- a/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// 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_CORE_PAINT_TABLE_CELL_PAINT_INVALIDATOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_CELL_PAINT_INVALIDATOR_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class LayoutObject;
-class LayoutTableCell;
-struct PaintInvalidatorContext;
-
-class TableCellPaintInvalidator {
-  STACK_ALLOCATED();
-
- public:
-  TableCellPaintInvalidator(const LayoutTableCell& cell,
-                            const PaintInvalidatorContext& context)
-      : cell_(cell), context_(context) {}
-
-  void InvalidatePaint();
-
- private:
-  void InvalidateContainerForCellGeometryChange(
-      const LayoutObject& container,
-      const PaintInvalidatorContext& container_context);
-
-  const LayoutTableCell& cell_;
-  const PaintInvalidatorContext& context_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_CELL_PAINT_INVALIDATOR_H_
diff --git a/third_party/blink/renderer/core/paint/table_cell_painter.cc b/third_party/blink/renderer/core/paint/table_cell_painter.cc
deleted file mode 100644
index f6b3bf86..0000000
--- a/third_party/blink/renderer/core/paint/table_cell_painter.cc
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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/core/paint/table_cell_painter.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
-#include "third_party/blink/renderer/core/paint/block_painter.h"
-#include "third_party/blink/renderer/core/paint/box_decoration_data.h"
-#include "third_party/blink/renderer/core/paint/box_model_object_painter.h"
-#include "third_party/blink/renderer/core/paint/box_painter.h"
-#include "third_party/blink/renderer/core/paint/box_painter_base.h"
-#include "third_party/blink/renderer/core/paint/object_painter.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
-#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
-#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
-
-namespace blink {
-
-void TableCellPainter::PaintContainerBackgroundBehindCell(
-    const PaintInfo& paint_info,
-    const LayoutObject& background_object) {
-  DCHECK(background_object != layout_table_cell_);
-
-  if (layout_table_cell_.StyleRef().Visibility() != EVisibility::kVisible)
-    return;
-
-  LayoutTable* table = layout_table_cell_.Table();
-  if (!table->ShouldCollapseBorders() &&
-      layout_table_cell_.StyleRef().EmptyCells() == EEmptyCells::kHide &&
-      !layout_table_cell_.FirstChild())
-    return;
-
-  ScopedPaintState paint_state(
-      layout_table_cell_, paint_info,
-      /*painting_legacy_table_part_in_ancestor_layer*/ true);
-  auto paint_rect =
-      PaintRectNotIncludingVisualOverflow(paint_state.PaintOffset());
-  PaintBackground(paint_state.GetPaintInfo(), paint_rect, background_object);
-}
-
-void TableCellPainter::PaintBackground(const PaintInfo& paint_info,
-                                       const PhysicalRect& paint_rect,
-                                       const LayoutObject& background_object) {
-  if (layout_table_cell_.BackgroundTransfersToView())
-    return;
-
-  Color c = background_object.ResolveColor(GetCSSPropertyBackgroundColor());
-  const FillLayer& bg_layer = background_object.StyleRef().BackgroundLayers();
-  if (bg_layer.AnyLayerHasImage() || c.Alpha()) {
-    // We have to clip here because the background would paint
-    // on top of the borders otherwise.  This only matters for cells and rows.
-    bool should_clip = background_object.HasLayer() &&
-                       (background_object == layout_table_cell_ ||
-                        background_object == layout_table_cell_.Parent()) &&
-                       layout_table_cell_.Table()->ShouldCollapseBorders();
-    GraphicsContextStateSaver state_saver(paint_info.context, should_clip);
-    if (should_clip) {
-      PhysicalRect clip_rect(paint_rect.offset, layout_table_cell_.Size());
-      clip_rect.Expand(layout_table_cell_.BorderInsets());
-      paint_info.context.Clip(ToPixelSnappedRect(clip_rect));
-    }
-    BackgroundImageGeometry geometry(layout_table_cell_, &background_object);
-    BoxModelObjectPainter(layout_table_cell_)
-        .PaintFillLayers(paint_info, c, bg_layer, paint_rect, geometry);
-  }
-}
-
-void TableCellPainter::PaintBoxDecorationBackground(
-    const PaintInfo& paint_info,
-    const PhysicalOffset& paint_offset) {
-  LayoutTable* table = layout_table_cell_.Table();
-  const ComputedStyle& style = layout_table_cell_.StyleRef();
-  if (style.Visibility() != EVisibility::kVisible)
-    return;
-  if (!table->ShouldCollapseBorders() &&
-      style.EmptyCells() == EEmptyCells::kHide &&
-      !layout_table_cell_.FirstChild())
-    return;
-
-  BoxDecorationData box_decoration_data(paint_info, layout_table_cell_);
-
-  const DisplayItemClient* client = nullptr;
-  PhysicalRect paint_rect;
-  gfx::Rect visual_rect;
-  absl::optional<ScopedBoxContentsPaintState> contents_paint_state;
-  if (box_decoration_data.IsPaintingBackgroundInContentsSpace()) {
-    // See BoxPainter::PaintBoxDecorationBackground() for explanations.
-    // TODO(wangxianzhu): Perhaps we can merge them for CompositeAfterPaint.
-    paint_rect = layout_table_cell_.PhysicalLayoutOverflowRect();
-    contents_paint_state.emplace(paint_info, paint_offset, layout_table_cell_);
-    paint_rect.Move(contents_paint_state->PaintOffset());
-    paint_rect.Expand(layout_table_cell_.BorderBoxOutsets());
-    client = &layout_table_cell_.GetScrollableArea()
-                  ->GetScrollingBackgroundDisplayItemClient();
-    visual_rect = ToEnclosingRect(paint_rect);
-  } else {
-    paint_rect = PaintRectNotIncludingVisualOverflow(paint_offset);
-    visual_rect = BoxPainter(layout_table_cell_).VisualRect(paint_offset);
-    client = &layout_table_cell_;
-  }
-
-  if (box_decoration_data.ShouldPaint() &&
-      !DrawingRecorder::UseCachedDrawingIfPossible(
-          paint_info.context, *client, DisplayItem::kBoxDecorationBackground)) {
-    DrawingRecorder recorder(paint_info.context, *client,
-                             DisplayItem::kBoxDecorationBackground,
-                             visual_rect);
-
-    if (box_decoration_data.ShouldPaintShadow())
-      BoxPainterBase::PaintNormalBoxShadow(paint_info, paint_rect, style);
-
-    if (box_decoration_data.ShouldPaintBackground())
-      PaintBackground(paint_info, paint_rect, layout_table_cell_);
-
-    if (box_decoration_data.ShouldPaintShadow()) {
-      // If the table collapses borders, the inner rect is the border box rect
-      // inset by inner half widths of collapsed borders (which are returned
-      // from the overridden BorderXXX() methods). Otherwise the following code
-      // is equivalent to BoxPainterBase::PaintInsetBoxShadowWithBorderRect().
-      auto inner_rect = paint_rect;
-      inner_rect.Contract(layout_table_cell_.BorderBoxOutsets());
-      BoxPainterBase::PaintInsetBoxShadowWithInnerRect(
-          paint_info, inner_rect, layout_table_cell_.StyleRef());
-    }
-
-    if (box_decoration_data.ShouldPaintBorder()) {
-      BoxPainterBase::PaintBorder(
-          layout_table_cell_, layout_table_cell_.GetDocument(),
-          layout_table_cell_.GeneratingNode(), paint_info, paint_rect, style);
-    }
-  }
-
-  BoxPainter(layout_table_cell_)
-      .RecordHitTestData(paint_info, paint_rect, *client);
-  BoxPainter(layout_table_cell_)
-      .RecordRegionCaptureData(paint_info, paint_rect, *client);
-}
-
-void TableCellPainter::PaintMask(const PaintInfo& paint_info,
-                                 const PhysicalOffset& paint_offset) {
-  if (layout_table_cell_.StyleRef().Visibility() != EVisibility::kVisible ||
-      paint_info.phase != PaintPhase::kMask)
-    return;
-
-  LayoutTable* table_elt = layout_table_cell_.Table();
-  if (!table_elt->ShouldCollapseBorders() &&
-      layout_table_cell_.StyleRef().EmptyCells() == EEmptyCells::kHide &&
-      !layout_table_cell_.FirstChild())
-    return;
-
-  if (DrawingRecorder::UseCachedDrawingIfPossible(
-          paint_info.context, layout_table_cell_, paint_info.phase))
-    return;
-
-  BoxDrawingRecorder recorder(paint_info.context, layout_table_cell_,
-                              paint_info.phase, paint_offset);
-  PhysicalRect paint_rect = PaintRectNotIncludingVisualOverflow(paint_offset);
-  BoxPainter(layout_table_cell_).PaintMaskImages(paint_info, paint_rect);
-}
-
-// TODO(crbug.com/377847): When table cells fully support subpixel layout, we
-// should not snap the size to pixels here. We should remove this function and
-// snap to pixels for the rect with paint offset applied.
-PhysicalRect TableCellPainter::PaintRectNotIncludingVisualOverflow(
-    const PhysicalOffset& paint_offset) {
-  return PhysicalRect(paint_offset,
-                      PhysicalSize(layout_table_cell_.PixelSnappedSize()));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/table_cell_painter.h b/third_party/blink/renderer/core/paint/table_cell_painter.h
deleted file mode 100644
index 01dc32a..0000000
--- a/third_party/blink/renderer/core/paint/table_cell_painter.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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_CORE_PAINT_TABLE_CELL_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_CELL_PAINTER_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class LayoutTableCell;
-class LayoutObject;
-struct PaintInfo;
-struct PhysicalOffset;
-struct PhysicalRect;
-
-class TableCellPainter {
-  STACK_ALLOCATED();
-
- public:
-  TableCellPainter(const LayoutTableCell& layout_table_cell)
-      : layout_table_cell_(layout_table_cell) {}
-
-  void PaintContainerBackgroundBehindCell(
-      const PaintInfo&,
-      const LayoutObject& background_object);
-  void PaintBoxDecorationBackground(const PaintInfo&,
-                                    const PhysicalOffset& paint_offset);
-  void PaintMask(const PaintInfo&, const PhysicalOffset& paint_offset);
-
-  PhysicalRect PaintRectNotIncludingVisualOverflow(
-      const PhysicalOffset& paint_offset);
-
- private:
-  void PaintBackground(const PaintInfo&,
-                       const PhysicalRect&,
-                       const LayoutObject& background_object);
-
-  const LayoutTableCell& layout_table_cell_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_CELL_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/table_paint_invalidator.cc b/third_party/blink/renderer/core/paint/table_paint_invalidator.cc
deleted file mode 100644
index b27aa73..0000000
--- a/third_party/blink/renderer/core/paint/table_paint_invalidator.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2016 The Chromium Authors
-// 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/core/paint/table_paint_invalidator.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-#include "third_party/blink/renderer/core/paint/box_paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
-
-namespace blink {
-
-void TablePaintInvalidator::InvalidatePaint() {
-  BoxPaintInvalidator(table_, context_).InvalidatePaint();
-
-  // If any col changed background, we need to invalidate all sections because
-  // col background paints into section's background display item.
-  bool has_col_changed_background = false;
-  if (table_.HasColElements()) {
-    for (LayoutTableCol* col = table_.FirstColumn(); col;
-         col = col->NextColumn()) {
-      // This ensures that the BackgroundNeedsFullPaintInvalidation flag is
-      // up-to-date.
-      col->EnsureIsReadyForPaintInvalidation();
-      if (col->BackgroundNeedsFullPaintInvalidation()) {
-        has_col_changed_background = true;
-        break;
-      }
-    }
-  }
-
-  if (has_col_changed_background) {
-    for (LayoutObject* child = table_.FirstChild(); child;
-         child = child->NextSibling()) {
-      if (!child->IsTableSection())
-        continue;
-      LayoutTableSection* section = To<LayoutTableSection>(child);
-      section->EnsureIsReadyForPaintInvalidation();
-      ObjectPaintInvalidator(*section)
-          .SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(
-              *section, PaintInvalidationReason::kStyle);
-    }
-  }
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/table_paint_invalidator.h b/third_party/blink/renderer/core/paint/table_paint_invalidator.h
deleted file mode 100644
index 4cbc8b6..0000000
--- a/third_party/blink/renderer/core/paint/table_paint_invalidator.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Chromium Authors
-// 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_CORE_PAINT_TABLE_PAINT_INVALIDATOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_PAINT_INVALIDATOR_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class LayoutTable;
-struct PaintInvalidatorContext;
-
-class TablePaintInvalidator {
-  STACK_ALLOCATED();
-
- public:
-  TablePaintInvalidator(const LayoutTable& table,
-                        const PaintInvalidatorContext& context)
-      : table_(table), context_(context) {}
-
-  void InvalidatePaint();
-
- private:
-  const LayoutTable& table_;
-  const PaintInvalidatorContext& context_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_PAINT_INVALIDATOR_H_
diff --git a/third_party/blink/renderer/core/paint/table_painter.cc b/third_party/blink/renderer/core/paint/table_painter.cc
deleted file mode 100644
index 09b1d3e..0000000
--- a/third_party/blink/renderer/core/paint/table_painter.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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/core/paint/table_painter.h"
-
-#include "third_party/blink/renderer/core/layout/collapsed_border_value.h"
-#include "third_party/blink/renderer/core/layout/layout_table.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-#include "third_party/blink/renderer/core/paint/box_painter.h"
-#include "third_party/blink/renderer/core/paint/object_painter.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/table_section_painter.h"
-#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
-
-namespace blink {
-
-void TablePainter::PaintObject(const PaintInfo& paint_info,
-                               const PhysicalOffset& paint_offset) {
-  PaintPhase paint_phase = paint_info.phase;
-
-  if (ShouldPaintSelfBlockBackground(paint_phase)) {
-    PaintBoxDecorationBackground(paint_info, paint_offset);
-    if (paint_phase == PaintPhase::kSelfBlockBackgroundOnly)
-      return;
-  }
-
-  if (paint_phase == PaintPhase::kMask) {
-    PaintMask(paint_info, paint_offset);
-    return;
-  }
-
-  if (paint_phase != PaintPhase::kSelfOutlineOnly &&
-      !paint_info.DescendantPaintingBlocked()) {
-    PaintInfo paint_info_for_descendants = paint_info.ForDescendants();
-
-    for (LayoutObject* child = layout_table_.FirstChild(); child;
-         child = child->NextSibling()) {
-      if (child->IsBox() && !To<LayoutBox>(child)->HasSelfPaintingLayer() &&
-          (child->IsTableSection() || child->IsTableCaption())) {
-        child->Paint(paint_info_for_descendants);
-      }
-    }
-
-    if (layout_table_.HasCollapsedBorders() &&
-        ShouldPaintDescendantBlockBackgrounds(paint_phase) &&
-        layout_table_.StyleRef().Visibility() == EVisibility::kVisible) {
-      PaintCollapsedBorders(paint_info_for_descendants, paint_offset);
-    }
-  }
-
-  if (ShouldPaintSelfOutline(paint_phase))
-    ObjectPainter(layout_table_).PaintOutline(paint_info, paint_offset);
-}
-
-void TablePainter::PaintBoxDecorationBackground(
-    const PaintInfo& paint_info,
-    const PhysicalOffset& paint_offset) {
-  PhysicalRect rect(paint_offset, layout_table_.Size());
-  layout_table_.SubtractCaptionRect(rect);
-
-  if (layout_table_.HasBoxDecorationBackground() &&
-      layout_table_.StyleRef().Visibility() == EVisibility::kVisible) {
-    BoxPainter(layout_table_)
-        .PaintBoxDecorationBackgroundWithRect(
-            paint_info, BoxPainter(layout_table_).VisualRect(paint_offset),
-            rect, layout_table_);
-  }
-
-  BoxPainter(layout_table_).RecordHitTestData(paint_info, rect, layout_table_);
-  BoxPainter(layout_table_)
-      .RecordRegionCaptureData(paint_info, rect, layout_table_);
-}
-
-void TablePainter::PaintMask(const PaintInfo& paint_info,
-                             const PhysicalOffset& paint_offset) {
-  if (layout_table_.StyleRef().Visibility() != EVisibility::kVisible ||
-      paint_info.phase != PaintPhase::kMask)
-    return;
-
-  if (DrawingRecorder::UseCachedDrawingIfPossible(
-          paint_info.context, layout_table_, paint_info.phase))
-    return;
-
-  PhysicalRect rect(paint_offset, layout_table_.Size());
-  layout_table_.SubtractCaptionRect(rect);
-
-  BoxDrawingRecorder recorder(paint_info.context, layout_table_,
-                              paint_info.phase, paint_offset);
-  BoxPainter(layout_table_).PaintMaskImages(paint_info, rect);
-}
-
-void TablePainter::PaintCollapsedBorders(const PaintInfo& paint_info,
-                                         const PhysicalOffset& paint_offset) {
-  for (LayoutTableSection* section = layout_table_.BottomSection(); section;
-       section = layout_table_.SectionAbove(section)) {
-    TableSectionPainter(*section).PaintCollapsedBorders(paint_info);
-  }
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/table_painter.h b/third_party/blink/renderer/core/paint/table_painter.h
deleted file mode 100644
index 0bb1c288..0000000
--- a/third_party/blink/renderer/core/paint/table_painter.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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_CORE_PAINT_TABLE_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_PAINTER_H_
-
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class LayoutTable;
-struct PaintInfo;
-struct PhysicalOffset;
-
-class TablePainter {
-  STACK_ALLOCATED();
-
- public:
-  TablePainter(const LayoutTable& layout_table) : layout_table_(layout_table) {}
-
-  void PaintObject(const PaintInfo&, const PhysicalOffset& paint_offset);
-  void PaintBoxDecorationBackground(const PaintInfo&,
-                                    const PhysicalOffset& paint_offset);
-  void PaintMask(const PaintInfo&, const PhysicalOffset& paint_offset);
-
- private:
-  void PaintCollapsedBorders(const PaintInfo&,
-                             const PhysicalOffset& paint_offset);
-
-  const LayoutTable& layout_table_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/table_row_painter.cc b/third_party/blink/renderer/core/paint/table_row_painter.cc
deleted file mode 100644
index ce7dccb..0000000
--- a/third_party/blink/renderer/core/paint/table_row_painter.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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/core/paint/table_row_painter.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-#include "third_party/blink/renderer/core/paint/box_painter.h"
-#include "third_party/blink/renderer/core/paint/box_painter_base.h"
-#include "third_party/blink/renderer/core/paint/collapsed_border_painter.h"
-#include "third_party/blink/renderer/core/paint/object_painter.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
-#include "third_party/blink/renderer/core/paint/table_cell_painter.h"
-#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
-
-namespace blink {
-
-void TableRowPainter::Paint(const PaintInfo& paint_info) {
-  DCHECK(layout_table_row_.HasSelfPaintingLayer());
-
-  // TODO(crbug.com/805514): Paint mask for table row.
-  if (paint_info.phase == PaintPhase::kMask)
-    return;
-
-  // TODO(crbug.com/577282): This painting order is inconsistent with other
-  // outlines.
-  if (ShouldPaintSelfOutline(paint_info.phase))
-    PaintOutline(paint_info);
-  if (paint_info.phase == PaintPhase::kSelfOutlineOnly)
-    return;
-
-  if (ShouldPaintSelfBlockBackground(paint_info.phase)) {
-    PaintBoxDecorationBackground(
-        paint_info,
-        layout_table_row_.Section()->FullTableEffectiveColumnSpan());
-  }
-
-  if (paint_info.phase == PaintPhase::kSelfBlockBackgroundOnly)
-    return;
-
-  PaintInfo paint_info_for_cells = paint_info.ForDescendants();
-  for (LayoutTableCell* cell = layout_table_row_.FirstCell(); cell;
-       cell = cell->NextCell()) {
-    if (!cell->HasSelfPaintingLayer())
-      cell->Paint(paint_info_for_cells);
-  }
-}
-
-void TableRowPainter::PaintOutline(const PaintInfo& paint_info) {
-  DCHECK(ShouldPaintSelfOutline(paint_info.phase));
-  ScopedPaintState paint_state(layout_table_row_, paint_info);
-  ObjectPainter(layout_table_row_)
-      .PaintOutline(paint_state.GetPaintInfo(), paint_state.PaintOffset());
-}
-
-void TableRowPainter::HandleChangedPartialPaint(
-    const PaintInfo& paint_info,
-    const CellSpan& dirtied_columns) {
-  PaintResult paint_result =
-      dirtied_columns ==
-              layout_table_row_.Section()->FullTableEffectiveColumnSpan()
-          ? kFullyPainted
-          : kMayBeClippedByCullRect;
-  layout_table_row_.GetMutableForPainting().UpdatePaintResult(
-      paint_result, paint_info.GetCullRect());
-}
-
-void TableRowPainter::PaintBoxDecorationBackground(
-    const PaintInfo& paint_info,
-    const CellSpan& dirtied_columns) {
-  ScopedPaintState paint_state(layout_table_row_, paint_info);
-  const auto& local_paint_info = paint_state.GetPaintInfo();
-  auto paint_offset = paint_state.PaintOffset();
-  PhysicalRect paint_rect(paint_offset, layout_table_row_.Size());
-
-  BoxPainter(layout_table_row_)
-      .RecordHitTestData(local_paint_info, paint_rect, layout_table_row_);
-  BoxPainter(layout_table_row_)
-      .RecordRegionCaptureData(local_paint_info, paint_rect, layout_table_row_);
-
-  const bool has_background = layout_table_row_.StyleRef().HasBackground();
-  const bool has_box_shadow = layout_table_row_.StyleRef().BoxShadow();
-  if (!has_background && !has_box_shadow)
-    return;
-
-  HandleChangedPartialPaint(paint_info, dirtied_columns);
-
-  if (DrawingRecorder::UseCachedDrawingIfPossible(
-          paint_info.context, layout_table_row_,
-          DisplayItem::kBoxDecorationBackground))
-    return;
-
-  BoxDrawingRecorder recorder(local_paint_info.context, layout_table_row_,
-                              DisplayItem::kBoxDecorationBackground,
-                              paint_offset);
-
-  if (has_box_shadow) {
-    BoxPainterBase::PaintNormalBoxShadow(local_paint_info, paint_rect,
-                                         layout_table_row_.StyleRef());
-  }
-
-  if (has_background) {
-    const auto* section = layout_table_row_.Section();
-    PaintInfo paint_info_for_cells = local_paint_info.ForDescendants();
-    for (auto c = dirtied_columns.Start(); c < dirtied_columns.End(); c++) {
-      if (const auto* cell =
-              section->OriginatingCellAt(layout_table_row_.RowIndex(), c)) {
-        TableCellPainter(*cell).PaintContainerBackgroundBehindCell(
-            paint_info_for_cells, layout_table_row_);
-      }
-    }
-  }
-
-  if (has_box_shadow) {
-    BoxPainterBase::PaintInsetBoxShadowWithInnerRect(
-        local_paint_info, paint_rect, layout_table_row_.StyleRef());
-  }
-}
-
-void TableRowPainter::PaintCollapsedBorders(const PaintInfo& paint_info,
-                                            const CellSpan& dirtied_columns) {
-  ScopedPaintState paint_state(
-      layout_table_row_, paint_info,
-      /*painting_legacy_table_part_in_ancestor_layer*/ true);
-  absl::optional<BoxDrawingRecorder> recorder;
-
-  HandleChangedPartialPaint(paint_info, dirtied_columns);
-
-  if (DrawingRecorder::UseCachedDrawingIfPossible(
-          paint_info.context, layout_table_row_,
-          DisplayItem::kTableCollapsedBorders))
-    return;
-
-  recorder.emplace(paint_info.context, layout_table_row_,
-                   DisplayItem::kTableCollapsedBorders,
-                   paint_state.PaintOffset());
-
-  const auto* section = layout_table_row_.Section();
-  unsigned row = layout_table_row_.RowIndex();
-  for (unsigned c = std::min(dirtied_columns.End(), section->NumCols(row));
-       c > dirtied_columns.Start(); c--) {
-    if (const auto* cell = section->OriginatingCellAt(row, c - 1)) {
-      CollapsedBorderPainter(*cell).PaintCollapsedBorders(
-          paint_state.GetPaintInfo());
-    }
-  }
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/table_row_painter.h b/third_party/blink/renderer/core/paint/table_row_painter.h
deleted file mode 100644
index bbedcae..0000000
--- a/third_party/blink/renderer/core/paint/table_row_painter.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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_CORE_PAINT_TABLE_ROW_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_ROW_PAINTER_H_
-
-#include "third_party/blink/renderer/core/style/shadow_data.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class CellSpan;
-class LayoutTableRow;
-struct PaintInfo;
-
-class TableRowPainter {
-  STACK_ALLOCATED();
-
- public:
-  TableRowPainter(const LayoutTableRow& layout_table_row)
-      : layout_table_row_(layout_table_row) {}
-
-  void Paint(const PaintInfo&);
-  void PaintOutline(const PaintInfo&);
-  void PaintBoxDecorationBackground(const PaintInfo&,
-                                    const CellSpan& dirtied_columns);
-  void PaintCollapsedBorders(const PaintInfo&, const CellSpan& dirtied_columns);
-
- private:
-  void HandleChangedPartialPaint(const PaintInfo&,
-                                 const CellSpan& dirtied_columns);
-
-  const LayoutTableRow& layout_table_row_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_ROW_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/table_section_painter.cc b/third_party/blink/renderer/core/paint/table_section_painter.cc
deleted file mode 100644
index a1be8d4..0000000
--- a/third_party/blink/renderer/core/paint/table_section_painter.cc
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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/core/paint/table_section_painter.h"
-
-#include <algorithm>
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/core/layout/layout_table_col.h"
-#include "third_party/blink/renderer/core/layout/layout_table_row.h"
-#include "third_party/blink/renderer/core/paint/box_painter.h"
-#include "third_party/blink/renderer/core/paint/box_painter_base.h"
-#include "third_party/blink/renderer/core/paint/collapsed_border_painter.h"
-#include "third_party/blink/renderer/core/paint/object_painter.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
-#include "third_party/blink/renderer/core/paint/table_cell_painter.h"
-#include "third_party/blink/renderer/core/paint/table_row_painter.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
-#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h"
-
-namespace blink {
-
-void TableSectionPainter::Paint(const PaintInfo& paint_info) {
-  // TODO(crbug.com/805514): Paint mask for table section.
-  if (paint_info.phase == PaintPhase::kMask)
-    return;
-
-  // If the section has multiple fragments, it should repeatedly paint the
-  // fragments by itself if:
-  // - It's not a self-painting layer (otherwise PaintLayerPainter should
-  //   initiate painting of the multiple fragments);
-  // - the table doesn't have multiple fragments (otherwise the table's
-  //   containing painting layer should initiate painting of the fragments).
-  bool should_paint_fragments_by_itself =
-      layout_table_section_.FirstFragment().NextFragment() &&
-      !layout_table_section_.HasSelfPaintingLayer() &&
-      !layout_table_section_.Table()->FirstFragment().NextFragment();
-
-  if (!should_paint_fragments_by_itself) {
-    PaintSection(paint_info);
-    return;
-  }
-
-  unsigned fragment_index = 0;
-  for (const auto* fragment = &layout_table_section_.FirstFragment(); fragment;
-       fragment = fragment->NextFragment()) {
-    PaintInfo fragment_paint_info = paint_info;
-    fragment_paint_info.SetFragmentID(fragment->FragmentID());
-    ScopedDisplayItemFragment scoped_display_item_fragment(
-        fragment_paint_info.context, fragment_index++);
-    PaintSection(fragment_paint_info);
-  }
-}
-
-void TableSectionPainter::PaintSection(const PaintInfo& paint_info) {
-  DCHECK(!layout_table_section_.NeedsLayout());
-  // avoid crashing on bugs that cause us to paint with dirty layout
-  if (layout_table_section_.NeedsLayout())
-    return;
-
-  unsigned total_rows = layout_table_section_.NumRows();
-  unsigned total_cols = layout_table_section_.Table()->NumEffectiveColumns();
-
-  if (!total_rows || !total_cols)
-    return;
-
-  ScopedPaintState paint_state(layout_table_section_, paint_info);
-  const auto& local_paint_info = paint_state.GetPaintInfo();
-  auto paint_offset = paint_state.PaintOffset();
-
-  if (local_paint_info.phase != PaintPhase::kSelfOutlineOnly) {
-    if (local_paint_info.phase != PaintPhase::kSelfBlockBackgroundOnly &&
-        local_paint_info.phase != PaintPhase::kMask) {
-      ScopedBoxContentsPaintState contents_paint_state(paint_state,
-                                                       layout_table_section_);
-      PaintObject(contents_paint_state.GetPaintInfo(),
-                  contents_paint_state.PaintOffset());
-    } else {
-      PaintObject(local_paint_info, paint_offset);
-    }
-  }
-
-  if (ShouldPaintSelfOutline(local_paint_info.phase)) {
-    ObjectPainter(layout_table_section_)
-        .PaintOutline(local_paint_info, paint_offset);
-  }
-}
-
-void TableSectionPainter::PaintCollapsedBorders(const PaintInfo& paint_info) {
-  // If the section has multiple fragments, it should repeatedly paint the
-  // fragments for collapsed borders by itself if the table doesn't have
-  // multiple fragments (otherwise the table's containing painting layer
-  // should initiate painting of the fragments). The condition here is
-  // different from that in Paint() because the table always initiate painting
-  // of collapsed borders regardless of self-painting status of the section.
-  bool should_paint_fragments_by_itself =
-      layout_table_section_.FirstFragment().NextFragment() &&
-      !layout_table_section_.Table()->FirstFragment().NextFragment();
-
-  if (!should_paint_fragments_by_itself) {
-    PaintCollapsedSectionBorders(paint_info);
-    return;
-  }
-
-  unsigned fragment_index = 0;
-  for (const auto* fragment = &layout_table_section_.FirstFragment(); fragment;
-       fragment = fragment->NextFragment()) {
-    PaintInfo fragment_paint_info = paint_info;
-    fragment_paint_info.SetFragmentID(fragment->FragmentID());
-    ScopedDisplayItemFragment scoped_display_item_fragment(
-        fragment_paint_info.context, fragment_index++);
-    PaintCollapsedSectionBorders(fragment_paint_info);
-  }
-}
-
-LayoutRect TableSectionPainter::TableAlignedRect(
-    const PaintInfo& paint_info,
-    const PhysicalOffset& paint_offset) {
-  PhysicalRect local_cull_rect(paint_info.GetCullRect().Rect());
-  local_cull_rect.offset -= paint_offset;
-
-  LayoutRect table_aligned_rect =
-      layout_table_section_.LogicalRectForWritingModeAndDirection(
-          local_cull_rect);
-  return table_aligned_rect;
-}
-
-void TableSectionPainter::PaintCollapsedSectionBorders(
-    const PaintInfo& paint_info) {
-  if (!layout_table_section_.NumRows() ||
-      !layout_table_section_.Table()->EffectiveColumns().size())
-    return;
-
-  ScopedPaintState paint_state(
-      layout_table_section_, paint_info,
-      /*painting_legacy_table_part_in_ancestor_layer*/ true);
-  absl::optional<ScopedBoxContentsPaintState> contents_paint_state;
-  if (paint_info.phase != PaintPhase::kMask)
-    contents_paint_state.emplace(paint_state, layout_table_section_);
-  const auto& local_paint_info = contents_paint_state
-                                     ? contents_paint_state->GetPaintInfo()
-                                     : paint_state.GetPaintInfo();
-  auto paint_offset = contents_paint_state ? contents_paint_state->PaintOffset()
-                                           : paint_state.PaintOffset();
-
-  CellSpan dirtied_rows;
-  CellSpan dirtied_columns;
-  layout_table_section_.DirtiedRowsAndEffectiveColumns(
-      TableAlignedRect(local_paint_info, paint_offset), dirtied_rows,
-      dirtied_columns);
-
-  if (dirtied_columns.Start() >= dirtied_columns.End())
-    return;
-
-  // Collapsed borders are painted from the bottom right to the top left so that
-  // precedence due to cell position is respected.
-  for (unsigned r = dirtied_rows.End(); r > dirtied_rows.Start(); r--) {
-    if (const auto* row = layout_table_section_.RowLayoutObjectAt(r - 1)) {
-      TableRowPainter(*row).PaintCollapsedBorders(local_paint_info,
-                                                  dirtied_columns);
-    }
-  }
-}
-
-void TableSectionPainter::PaintObject(const PaintInfo& paint_info,
-                                      const PhysicalOffset& paint_offset) {
-  CellSpan dirtied_rows;
-  CellSpan dirtied_columns;
-  layout_table_section_.DirtiedRowsAndEffectiveColumns(
-      TableAlignedRect(paint_info, paint_offset), dirtied_rows,
-      dirtied_columns);
-
-  PaintInfo paint_info_for_descendants = paint_info.ForDescendants();
-
-  if (ShouldPaintSelfBlockBackground(paint_info.phase)) {
-    PaintBoxDecorationBackground(paint_info, paint_offset, dirtied_rows,
-                                 dirtied_columns);
-  }
-
-  if (paint_info.phase == PaintPhase::kSelfBlockBackgroundOnly)
-    return;
-
-  if (ShouldPaintDescendantBlockBackgrounds(paint_info.phase)) {
-    for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
-      const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r);
-      // If a row has a layer, we'll paint row background though
-      // TableRowPainter::paint().
-      if (!row || row->HasSelfPaintingLayer())
-        continue;
-      TableRowPainter(*row).PaintBoxDecorationBackground(
-          paint_info_for_descendants, dirtied_columns);
-    }
-  }
-
-  // This is tested after background painting because during background painting
-  // we need to check validity of the previous background display item based on
-  // dirtyRows and dirtyColumns.
-  if (dirtied_rows.Start() >= dirtied_rows.End() ||
-      dirtied_columns.Start() >= dirtied_columns.End())
-    return;
-
-  const auto& visually_overflowing_cells =
-      layout_table_section_.VisuallyOverflowingCells();
-  if (visually_overflowing_cells.empty()) {
-    // This path is for 2 cases:
-    // 1. Normal partial paint, without overflowing cells;
-    // 2. Full paint, for small sections or big sections with many overflowing
-    //    cells.
-    // The difference between the normal partial paint and full paint is that
-    // whether dirtied_rows and dirtied_columns cover the whole section.
-    DCHECK(!layout_table_section_.HasVisuallyOverflowingCell() ||
-           (dirtied_rows == layout_table_section_.FullSectionRowSpan() &&
-            dirtied_columns ==
-                layout_table_section_.FullTableEffectiveColumnSpan()));
-
-    for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
-      const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r);
-      // TODO(crbug.com/577282): This painting order is inconsistent with other
-      // outlines.
-      if (row && !row->HasSelfPaintingLayer() &&
-          ShouldPaintSelfOutline(paint_info_for_descendants.phase)) {
-        TableRowPainter(*row).PaintOutline(paint_info_for_descendants);
-      }
-      for (unsigned c = dirtied_columns.Start(); c < dirtied_columns.End();
-           c++) {
-        if (const LayoutTableCell* cell =
-                layout_table_section_.OriginatingCellAt(r, c))
-          PaintCell(*cell, paint_info_for_descendants);
-      }
-    }
-  } else {
-    // This path paints section with a reasonable number of overflowing cells.
-    // This is the "partial paint path" for overflowing cells referred in
-    // LayoutTableSection::ComputeOverflowFromDescendants().
-    HeapVector<Member<const LayoutTableCell>> cells(visually_overflowing_cells);
-
-    HeapHashSet<Member<const LayoutTableCell>> spanning_cells;
-    for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
-      const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r);
-      // TODO(crbug.com/577282): This painting order is inconsistent with other
-      // outlines.
-      if (row && !row->HasSelfPaintingLayer() &&
-          ShouldPaintSelfOutline(paint_info_for_descendants.phase)) {
-        TableRowPainter(*row).PaintOutline(paint_info_for_descendants);
-      }
-      unsigned n_cols = layout_table_section_.NumCols(r);
-      for (unsigned c = dirtied_columns.Start();
-           c < n_cols && c < dirtied_columns.End(); c++) {
-        if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) {
-          if (!visually_overflowing_cells.Contains(cell))
-            cells.push_back(cell);
-        }
-      }
-    }
-
-    // Sort the dirty cells by paint order.
-    std::sort(cells.begin(), cells.end(), LayoutTableCell::CompareInDOMOrder);
-    for (const auto& cell : cells)
-      PaintCell(*cell, paint_info_for_descendants);
-  }
-}
-
-void TableSectionPainter::PaintBoxDecorationBackground(
-    const PaintInfo& paint_info,
-    const PhysicalOffset& paint_offset,
-    const CellSpan& dirtied_rows,
-    const CellSpan& dirtied_columns) {
-  bool may_have_background = layout_table_section_.Table()->HasColElements() ||
-                             layout_table_section_.StyleRef().HasBackground();
-  bool has_box_shadow = layout_table_section_.StyleRef().BoxShadow();
-  if (!may_have_background && !has_box_shadow)
-    return;
-
-  PaintResult paint_result =
-      dirtied_columns == layout_table_section_.FullTableEffectiveColumnSpan() &&
-              dirtied_rows == layout_table_section_.FullSectionRowSpan()
-          ? kFullyPainted
-          : kMayBeClippedByCullRect;
-  layout_table_section_.GetMutableForPainting().UpdatePaintResult(
-      paint_result, paint_info.GetCullRect());
-
-  if (DrawingRecorder::UseCachedDrawingIfPossible(
-          paint_info.context, layout_table_section_,
-          DisplayItem::kBoxDecorationBackground))
-    return;
-
-  BoxDrawingRecorder recorder(paint_info.context, layout_table_section_,
-                              DisplayItem::kBoxDecorationBackground,
-                              paint_offset);
-  PhysicalRect paint_rect(paint_offset, layout_table_section_.Size());
-
-  if (has_box_shadow) {
-    BoxPainterBase::PaintNormalBoxShadow(paint_info, paint_rect,
-                                         layout_table_section_.StyleRef());
-  }
-
-  if (may_have_background) {
-    PaintInfo paint_info_for_cells = paint_info.ForDescendants();
-    for (auto r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
-      absl::optional<ScopedPaintState> row_paint_state;
-      for (auto c = dirtied_columns.Start(); c < dirtied_columns.End(); c++) {
-        if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) {
-          if (!row_paint_state) {
-            row_paint_state.emplace(
-                *cell->Row(), paint_info_for_cells,
-                /*painting_legacy_table_part_in_ancestor_layer*/ true);
-          }
-          PaintBackgroundsBehindCell(*cell, row_paint_state->GetPaintInfo());
-        }
-      }
-    }
-  }
-
-  if (has_box_shadow) {
-    BoxPainterBase::PaintInsetBoxShadowWithInnerRect(
-        paint_info, paint_rect, layout_table_section_.StyleRef());
-  }
-}
-
-void TableSectionPainter::PaintBackgroundsBehindCell(
-    const LayoutTableCell& cell,
-    const PaintInfo& paint_info_for_cells) {
-  // We need to handle painting a stack of backgrounds. This stack (from bottom
-  // to top) consists of the column group, column, row group, row, and then the
-  // cell.
-
-  LayoutTable::ColAndColGroup col_and_col_group =
-      layout_table_section_.Table()->ColElementAtAbsoluteColumn(
-          cell.AbsoluteColumnIndex());
-  LayoutTableCol* column = col_and_col_group.col;
-  LayoutTableCol* column_group = col_and_col_group.colgroup;
-  TableCellPainter table_cell_painter(cell);
-
-  // Column groups and columns first.
-  // FIXME: Columns and column groups do not currently support opacity, and they
-  // are being painted "too late" in the stack, since we have already opened a
-  // transparency layer (potentially) for the table row group.  Note that we
-  // deliberately ignore whether or not the cell has a layer, since these
-  // backgrounds paint "behind" the cell.
-  if (column_group && column_group->StyleRef().HasBackground()) {
-    table_cell_painter.PaintContainerBackgroundBehindCell(paint_info_for_cells,
-                                                          *column_group);
-  }
-  if (column && column->StyleRef().HasBackground()) {
-    table_cell_painter.PaintContainerBackgroundBehindCell(paint_info_for_cells,
-                                                          *column);
-  }
-
-  // Paint the row group next.
-  if (layout_table_section_.StyleRef().HasBackground()) {
-    table_cell_painter.PaintContainerBackgroundBehindCell(
-        paint_info_for_cells, layout_table_section_);
-  }
-}
-
-void TableSectionPainter::PaintCell(const LayoutTableCell& cell,
-                                    const PaintInfo& paint_info_for_cells) {
-  if (!cell.HasSelfPaintingLayer() && !cell.Row()->HasSelfPaintingLayer())
-    cell.Paint(paint_info_for_cells);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/table_section_painter.h b/third_party/blink/renderer/core/paint/table_section_painter.h
deleted file mode 100644
index 996b7e91..0000000
--- a/third_party/blink/renderer/core/paint/table_section_painter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 The Chromium Authors
-// 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_CORE_PAINT_TABLE_SECTION_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_SECTION_PAINTER_H_
-
-#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/core/style/shadow_data.h"
-#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class CellSpan;
-class LayoutTableCell;
-class LayoutTableSection;
-struct PaintInfo;
-struct PhysicalOffset;
-
-class TableSectionPainter {
-  STACK_ALLOCATED();
-
- public:
-  TableSectionPainter(const LayoutTableSection& layout_table_section)
-      : layout_table_section_(layout_table_section) {}
-
-  void Paint(const PaintInfo&);
-  void PaintCollapsedBorders(const PaintInfo&);
-
- private:
-  void PaintObject(const PaintInfo&, const PhysicalOffset& paint_offset);
-
-  void PaintBoxDecorationBackground(const PaintInfo&,
-                                    const PhysicalOffset&,
-                                    const CellSpan& dirtied_rows,
-                                    const CellSpan& dirtied_columns);
-  void PaintBackgroundsBehindCell(const LayoutTableCell&, const PaintInfo&);
-  void PaintCell(const LayoutTableCell&, const PaintInfo&);
-
-  void PaintSection(const PaintInfo&);
-  void PaintCollapsedSectionBorders(const PaintInfo&);
-
-  LayoutRect TableAlignedRect(const PaintInfo& paint_info,
-                              const PhysicalOffset& paint_offset);
-
-  const LayoutTableSection& layout_table_section_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TABLE_SECTION_PAINTER_H_
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index a476a12..c9eeeb7 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2233,23 +2233,30 @@
   // `white-space` property may become a shorthand in future.
   // https://drafts.csswg.org/css-text-4/#white-space-property
   static bool DeprecatedAutoWrap(EWhiteSpace ws) {
-    return blink::ShouldWrapLine(ws);
+    return blink::ShouldWrapLine(ToTextWrap(ws));
   }
   static bool DeprecatedPreserveNewline(EWhiteSpace ws) {
-    return ShouldPreserveBreaks(ws);
+    return ShouldPreserveBreaks(ToWhiteSpaceCollapse(ws));
   }
   static bool DeprecatedCollapseWhiteSpace(EWhiteSpace ws) {
-    return blink::ShouldCollapseSpacesAndTabs(ws);
+    return blink::ShouldCollapseSpacesAndTabs(ToWhiteSpaceCollapse(ws));
   }
 
+  // This function may return values not defined as the enum values. See
+  // `EWhiteSpace`. Prefer using semantic functions below.
+  EWhiteSpace WhiteSpace() const {
+    return ToWhiteSpace(GetWhiteSpaceCollapse(), GetTextWrap());
+  }
+
+  // Semantic functions for the `white-space` property and its longhands.
   bool ShouldPreserveSpacesAndTabs() const {
-    return blink::ShouldPreserveSpacesAndTabs(WhiteSpace());
+    return blink::ShouldPreserveSpacesAndTabs(GetWhiteSpaceCollapse());
   }
   bool PreserveNewline() const {
-    return DeprecatedPreserveNewline(WhiteSpace());
+    return blink::ShouldPreserveBreaks(GetWhiteSpaceCollapse());
   }
   bool CollapseWhiteSpace() const {
-    return DeprecatedCollapseWhiteSpace(WhiteSpace());
+    return blink::ShouldCollapseSpacesAndTabs(GetWhiteSpaceCollapse());
   }
   bool IsCollapsibleWhiteSpace(UChar c) const {
     switch (c) {
@@ -2262,9 +2269,9 @@
     return false;
   }
 
-  bool ShouldWrapLine() const { return DeprecatedAutoWrap(WhiteSpace()); }
+  bool ShouldWrapLine() const { return blink::ShouldWrapLine(GetTextWrap()); }
   bool ShouldBreakSpaces() const {
-    return blink::ShouldBreakSpaces(WhiteSpace());
+    return blink::ShouldBreakSpaces(GetWhiteSpaceCollapse());
   }
   bool BreakOnlyAfterWhiteSpace() const {
     return (ShouldPreserveSpacesAndTabs() && ShouldWrapLine()) ||
@@ -3435,6 +3442,12 @@
     MutableInitialDataInternal() = std::move(data);
   }
 
+  EWhiteSpace WhiteSpace() const { return style_->WhiteSpace(); }
+  void SetWhiteSpace(EWhiteSpace whitespace) {
+    SetWhiteSpaceCollapse(ToWhiteSpaceCollapse(whitespace));
+    SetTextWrap(ToTextWrap(whitespace));
+  }
+
   // WritingMode
   WritingDirectionMode GetWritingDirection() const {
     return {GetWritingMode(), Direction()};
diff --git a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
index 79df808..097e5b32 100644
--- a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
+++ b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -45,15 +45,18 @@
     },
     {
         name: "DiffNeedsReshapeAndFullLayoutAndPaintInvalidation",
-        fields_to_diff: ["font"],
+        fields_to_diff: [
+            "font",
+            "white-space-collapse",
+        ],
         methods_to_diff: [
           {
             method: "TextTransform()",
             field_dependencies: ["text-transform"]
           },
           {
-            method: "WhiteSpace()",
-            field_dependencies: ["white-space"]
+            method: "ShouldWrapLine()",
+            field_dependencies: ["text-wrap"]
           },
           {
             method: "Direction()",
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
index 911fe65d..9e849f7 100644
--- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
+++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
@@ -19,22 +19,25 @@
 
 namespace {
 
-void LogToConsole(LocalFrame* frame,
-                  mojom::blink::ConsoleMessageLevel level,
-                  const String& message) {
-  if (!frame || !frame->IsMainFrame()) {
-    return;
-  }
-  LocalDOMWindow* window = frame->DomWindow();
-  if (!window) {
-    return;
-  }
+void LogAndTraceDetectedSoftNavigation(LocalFrame* frame,
+                                       LocalDOMWindow* window,
+                                       String url,
+                                       base::TimeTicks user_click_timestamp) {
+  CHECK(frame && frame->IsMainFrame());
+  CHECK(window);
   if (!RuntimeEnabledFeatures::SoftNavigationHeuristicsEnabled(window)) {
     return;
   }
   auto* console_message = MakeGarbageCollected<ConsoleMessage>(
-      mojom::blink::ConsoleMessageSource::kJavaScript, level, message);
+      mojom::blink::ConsoleMessageSource::kJavaScript,
+      mojom::blink::ConsoleMessageLevel::kInfo,
+      String("A soft navigation has been detected: ") + url);
   window->AddConsoleMessage(console_message);
+
+  TRACE_EVENT_INSTANT("scheduler,devtools.timeline,loading",
+                      "SoftNavigationHeuristics_SoftNavigationDetected",
+                      user_click_timestamp, "frame", ToTraceValue(frame), "url",
+                      url);
 }
 
 }  // namespace
@@ -200,10 +203,7 @@
   ResetPaintsIfNeeded(frame, window);
 
   ResetHeuristic();
-  LogToConsole(frame, mojom::blink::ConsoleMessageLevel::kInfo,
-               String("A soft navigation has been detected: ") + url_);
-  TRACE_EVENT_INSTANT("scheduler",
-                      "SoftNavigationHeuristics_SoftNavigationDetected");
+  LogAndTraceDetectedSoftNavigation(frame, window, url_, user_click_timestamp_);
   if (LocalFrameClient* frame_client = frame->Client()) {
     // This notifies UKM about this soft navigation.
     frame_client->DidObserveSoftNavigation(soft_navigation_count_);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index d00dfac..a0cb808c 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -3547,15 +3547,14 @@
   }
 
   // Step 2I from: http://www.w3.org/TR/accname-aam-1.1
-  name_from = ax::mojom::blink::NameFrom::kTitle;
-  const AtomicString& title = GetAttribute(kTitleAttr);
-  String titleText = text_alternative = TextAlternativeFromTitleAttribute(
-      title, name_from, name_sources, &found_text_alternative);
-  if (!title.empty()) {
+  String resulting_text = TextAlternativeFromTooltip(
+      name_from, name_sources, &found_text_alternative, &text_alternative,
+      related_objects);
+  if (!resulting_text.empty()) {
     if (name_sources) {
-      text_alternative = titleText;
+      text_alternative = resulting_text;
     } else {
-      return titleText;
+      return resulting_text;
     }
   }
 
@@ -3604,6 +3603,7 @@
     case ax::mojom::blink::NameFrom::kRelatedElement:
     case ax::mojom::blink::NameFrom::kTitle:
     case ax::mojom::blink::NameFrom::kValue:
+    case ax::mojom::blink::NameFrom::kPopoverAttribute:
       return true;
   }
   switch (name_from) {
@@ -3617,6 +3617,7 @@
     case ax::mojom::blink::NameFrom::kRelatedElement:
     case ax::mojom::blink::NameFrom::kTitle:
     case ax::mojom::blink::NameFrom::kValue:
+    case ax::mojom::blink::NameFrom::kPopoverAttribute:
       return true;
   }
 
@@ -4917,6 +4918,72 @@
   return AXObjectCache().ValidationMessageObjectIfInvalid(true);
 }
 
+String AXNodeObject::TextAlternativeFromTooltip(
+    ax::mojom::blink::NameFrom& name_from,
+    NameSources* name_sources,
+    bool* found_text_alternative,
+    String* text_alternative,
+    AXRelatedObjectVector* related_objects) const {
+  name_from = ax::mojom::blink::NameFrom::kTitle;
+  const AtomicString& title = GetAttribute(kTitleAttr);
+  String title_text = *text_alternative = TextAlternativeFromTitleAttribute(
+      title, name_from, name_sources, found_text_alternative);
+  if (!title_text.empty()) {
+    return title_text;
+  }
+
+  auto* form_control = DynamicTo<HTMLFormControlElement>(GetElement());
+  if (!form_control) {
+    return String();
+  }
+
+  auto popover_target = form_control->popoverTargetElement();
+  if (!popover_target.popover ||
+      popover_target.popover->PopoverType() != PopoverValueType::kHint) {
+    return String();
+  }
+
+  DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled());
+
+  name_from = ax::mojom::blink::NameFrom::kPopoverAttribute;
+  if (name_sources) {
+    name_sources->push_back(
+        NameSource(*found_text_alternative, html_names::kPopovertargetAttr));
+    name_sources->back().type = name_from;
+  }
+  AXObject* popover_ax_object =
+      AXObjectCache().GetOrCreate(popover_target.popover);
+
+  // Hint popovers are used for text if and only if all of the contents are
+  // plain, e.g. have no interesting semantic or interactive elements.
+  // Otherwise, the hint will be exposed via the kDetails relationship. The
+  // motivation for this is that by reusing the simple mechanism of titles,
+  // screen reader users can easily access the information of plain hints
+  // without having to navigate to it, making the content more accessible.
+  // However, in the case of rich hints, a kDetails relationship is required to
+  // ensure that users are able to access and interact with the hint as they can
+  // navigate to it using commands.
+  if (!popover_ax_object || !popover_ax_object->IsPlainContent()) {
+    return String();
+  }
+  AXObjectSet visited;
+  String popover_text =
+      RecursiveTextAlternative(*popover_ax_object, popover_ax_object, visited);
+  *text_alternative = popover_text;
+  if (related_objects) {
+    related_objects->push_back(MakeGarbageCollected<NameSourceRelatedObject>(
+        popover_ax_object, popover_text));
+  }
+
+  if (name_sources) {
+    NameSource& source = name_sources->back();
+    source.text = *text_alternative;
+    *found_text_alternative = true;
+  }
+
+  return popover_text;
+}
+
 String AXNodeObject::TextAlternativeFromTitleAttribute(
     const AtomicString& title,
     ax::mojom::blink::NameFrom& name_from,
@@ -5096,15 +5163,15 @@
       }
     }
 
-    // title attr
-    const AtomicString& title = input_element->getAttribute(kTitleAttr);
-    String titleText = text_alternative = TextAlternativeFromTitleAttribute(
-        title, name_from, name_sources, found_text_alternative);
-    if (!titleText.IsNull()) {
+    // title attr or popover
+    String resulting_text = TextAlternativeFromTooltip(
+        name_from, name_sources, found_text_alternative, &text_alternative,
+        related_objects);
+    if (!resulting_text.empty()) {
       if (name_sources) {
-        text_alternative = titleText;
+        text_alternative = resulting_text;
       } else {
-        return titleText;
+        return resulting_text;
       }
     }
 
@@ -5128,15 +5195,14 @@
   // 5.1 Text inputs - step 3 (placeholder attribute)
   if (html_element && html_element->IsTextControl()) {
     // title attr
-    name_from = ax::mojom::blink::NameFrom::kAttribute;
-    const AtomicString& title = html_element->getAttribute(kTitleAttr);
-    String titleText = text_alternative = TextAlternativeFromTitleAttribute(
-        title, name_from, name_sources, found_text_alternative);
-    if (!titleText.IsNull()) {
+    String resulting_text = TextAlternativeFromTooltip(
+        name_from, name_sources, found_text_alternative, &text_alternative,
+        related_objects);
+    if (!resulting_text.empty()) {
       if (name_sources) {
-        text_alternative = titleText;
+        text_alternative = resulting_text;
       } else {
-        return titleText;
+        return resulting_text;
       }
     }
 
@@ -5716,35 +5782,37 @@
 
   // For form controls that act as triggering elements for popovers of type
   // kHint, then set aria-describedby to the popover.
-  if (auto* form_control = DynamicTo<HTMLFormControlElement>(element)) {
-    auto popover_target = form_control->popoverTargetElement();
-    if (popover_target.popover &&
-        popover_target.popover->PopoverType() == PopoverValueType::kHint) {
-      DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled());
-      description_from = ax::mojom::blink::DescriptionFrom::kPopoverAttribute;
-      if (description_sources) {
-        description_sources->push_back(DescriptionSource(
-            found_description, html_names::kPopovertargetAttr));
-        description_sources->back().type = description_from;
-      }
-      AXObject* popover_ax_object =
-          AXObjectCache().GetOrCreate(popover_target.popover);
-      if (popover_ax_object) {
-        AXObjectSet visited;
-        description = RecursiveTextAlternative(*popover_ax_object,
-                                               popover_ax_object, visited);
-        if (related_objects) {
-          related_objects->push_back(
-              MakeGarbageCollected<NameSourceRelatedObject>(popover_ax_object,
-                                                            description));
-        }
+  if (name_from != ax::mojom::blink::NameFrom::kPopoverAttribute) {
+    if (auto* form_control = DynamicTo<HTMLFormControlElement>(element)) {
+      auto popover_target = form_control->popoverTargetElement();
+      if (popover_target.popover &&
+          popover_target.popover->PopoverType() == PopoverValueType::kHint) {
+        DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled());
+        description_from = ax::mojom::blink::DescriptionFrom::kPopoverAttribute;
         if (description_sources) {
-          DescriptionSource& source = description_sources->back();
-          source.related_objects = *related_objects;
-          source.text = description;
-          found_description = true;
-        } else {
-          return description;
+          description_sources->push_back(DescriptionSource(
+              found_description, html_names::kPopovertargetAttr));
+          description_sources->back().type = description_from;
+        }
+        AXObject* popover_ax_object =
+            AXObjectCache().GetOrCreate(popover_target.popover);
+        if (popover_ax_object) {
+          AXObjectSet visited;
+          description = RecursiveTextAlternative(*popover_ax_object,
+                                                 popover_ax_object, visited);
+          if (related_objects) {
+            related_objects->push_back(
+                MakeGarbageCollected<NameSourceRelatedObject>(popover_ax_object,
+                                                              description));
+          }
+          if (description_sources) {
+            DescriptionSource& source = description_sources->back();
+            source.related_objects = *related_objects;
+            source.text = description;
+            found_description = true;
+          } else {
+            return description;
+          }
         }
       }
     }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
index e63410c..3e000da 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -296,6 +296,22 @@
                                             const QualifiedName&) const;
 
   bool IsNativeCheckboxInMixedState() const;
+
+  // This function returns the text of a tooltip associated with the element.
+  // Although there are two ways of doing this, it is unlikely that an author
+  // would provide 2 overlapping types of tooltips. Order of precedence:
+  // 1. The title attribute is currently preferred if present.
+  // 2. The contents of a plain hint, which has no interesting semantic or
+  // interactive content, is used next.
+  // TODO(accessibility): Follow-up with standards discussion to determine
+  // whether a different order of precedence makes sense.
+  String TextAlternativeFromTooltip(
+      ax::mojom::blink::NameFrom& name_from,
+      NameSources* name_sources,
+      bool* found_text_alternative,
+      String* text_alternative,
+      AXRelatedObjectVector* related_objects) const;
+
   String TextAlternativeFromTitleAttribute(
       const AtomicString& title,
       ax::mojom::blink::NameFrom& name_from,
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 5fb1f5d..c2aa5e44 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -2315,6 +2315,18 @@
   }
 }
 
+bool AXObject::IsPlainContent() const {
+  if (!ui::IsPlainContentElement(role_)) {
+    return false;
+  }
+  for (const auto& child : ChildrenIncludingIgnored()) {
+    if (!child->IsPlainContent()) {
+      return false;
+    }
+  }
+  return true;
+}
+
 // Popover invoking elements should have details relationships with their
 // target popover, when that popover is a) open, and b) not the next element
 // in the DOM (depth first search order).
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h
index f059721..cc8cd85 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -466,6 +466,13 @@
   virtual bool IsVisible() const;
   virtual bool IsVisited() const;
 
+  // Returns true if the current element is text or an image, and all
+  // the children are also plain content by this definition.
+  // TODO(https://crbug.com/1426889): return false if there are "interesting"
+  // elements in the subtree, even within a deep descendant, possibly reusing
+  // CSS :has() in order to make a performant and flexible implementation.
+  bool IsPlainContent() const;
+
   // Check whether value can be modified.
   bool CanSetValueAttribute() const;
 
diff --git a/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc b/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
index 28e0ddc..64251f77 100644
--- a/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
+++ b/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
@@ -2201,6 +2201,11 @@
     const AuctionAdInterestGroup* group,
     double duration_seconds,
     ExceptionState& exception_state) {
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return ScriptPromise();
+  }
   RecordCommonFledgeUseCounters(navigator.DomWindow()->document());
   const ExecutionContext* context = ExecutionContext::From(script_state);
   if (!context->IsFeatureEnabled(
@@ -2292,6 +2297,11 @@
     Navigator& navigator,
     const AuctionAdInterestGroupKey* group_key,
     ExceptionState& exception_state) {
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return ScriptPromise();
+  }
   RecordCommonFledgeUseCounters(navigator.DomWindow()->document());
   ExecutionContext* context = ExecutionContext::From(script_state);
   if (!context->IsFeatureEnabled(
@@ -2317,6 +2327,11 @@
     ScriptState* script_state,
     Navigator& navigator,
     ExceptionState& exception_state) {
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return ScriptPromise();
+  }
   ExecutionContext* context = ExecutionContext::From(script_state);
   // According to the spec, implicit leave bypasses permission policy.
   return From(context, navigator)
@@ -2331,6 +2346,11 @@
 void NavigatorAuction::updateAdInterestGroups(ScriptState* script_state,
                                               Navigator& navigator,
                                               ExceptionState& exception_state) {
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return;
+  }
   RecordCommonFledgeUseCounters(navigator.DomWindow()->document());
   ExecutionContext* context = ExecutionContext::From(script_state);
   if (!context->IsFeatureEnabled(
@@ -2398,6 +2418,11 @@
                                              Navigator& navigator,
                                              const AuctionAdConfig* config,
                                              ExceptionState& exception_state) {
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return ScriptPromise();
+  }
   RecordCommonFledgeUseCounters(navigator.DomWindow()->document());
   const ExecutionContext* context = ExecutionContext::From(script_state);
   if (!context->IsFeatureEnabled(
@@ -2423,10 +2448,15 @@
     Navigator& navigator,
     uint16_t num_ad_components,
     ExceptionState& exception_state) {
+  Vector<String> out;
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return out;
+  }
   RecordCommonFledgeUseCounters(navigator.DomWindow()->document());
   const auto& ad_auction_components =
       navigator.DomWindow()->document()->Loader()->AdAuctionComponents();
-  Vector<String> out;
   if (!ad_auction_components) {
     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                       "This frame was not loaded with the "
@@ -2475,6 +2505,11 @@
     const V8UnionFencedFrameConfigOrUSVString* urn_or_config,
     bool send_reports,
     ExceptionState& exception_state) {
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return ScriptPromise();
+  }
   String uuid_url_string;
   switch (urn_or_config->GetContentType()) {
     case V8UnionFencedFrameConfigOrUSVString::ContentType::kUSVString:
@@ -2535,6 +2570,11 @@
     const V8UnionFencedFrameConfigOrUSVString* urn_or_config,
     const Vector<std::pair<String, String>>& replacements,
     ExceptionState& exception_state) {
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return ScriptPromise();
+  }
   String uuid_url_string;
   switch (urn_or_config->GetContentType()) {
     case V8UnionFencedFrameConfigOrUSVString::ContentType::kUSVString:
@@ -2603,6 +2643,11 @@
     Navigator& navigator,
     const AdRequestConfig* config,
     ExceptionState& exception_state) {
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return ScriptPromise();
+  }
   return From(ExecutionContext::From(script_state), navigator)
       .createAdRequest(script_state, config, exception_state);
 }
@@ -2663,6 +2708,11 @@
                                            const Ads* ads,
                                            const AuctionAdConfig* config,
                                            ExceptionState& exception_state) {
+  if (!navigator.DomWindow()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+                                      "The document has no window associated.");
+    return ScriptPromise();
+  }
   return From(ExecutionContext::From(script_state), navigator)
       .finalizeAd(script_state, ads, config, exception_state);
 }
@@ -2855,6 +2905,9 @@
 /* static */
 bool NavigatorAuction::canLoadAdAuctionFencedFrame(ScriptState* script_state,
                                                    Navigator& navigator) {
+  if (!navigator.DomWindow()) {
+    return false;
+  }
   return From(ExecutionContext::From(script_state), navigator)
       .canLoadAdAuctionFencedFrame(script_state);
 }
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_writer.cc b/third_party/blink/renderer/modules/clipboard/clipboard_writer.cc
index 480455bc..8618b429 100644
--- a/third_party/blink/renderer/modules/clipboard/clipboard_writer.cc
+++ b/third_party/blink/renderer/modules/clipboard/clipboard_writer.cc
@@ -64,8 +64,8 @@
     std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
         SegmentReader::CreateFromSkData(
             SkData::MakeWithoutCopy(png_data.Data(), png_data.DataLength())),
-        true, ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth,
-        ColorBehavior::Tag());
+        /*data_complete=*/true, ImageDecoder::kAlphaPremultiplied,
+        ImageDecoder::kDefaultBitDepth, ColorBehavior::Tag());
     sk_sp<SkImage> image = nullptr;
     // `decoder` is nullptr if `png_data` doesn't begin with the PNG signature.
     if (decoder) {
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.cc b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
index 5029b3d..517105f6 100644
--- a/third_party/blink/renderer/modules/imagecapture/image_capture.cc
+++ b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -1761,8 +1761,10 @@
     if (constraint_set->hasTorch()) {
       UseCounter::Count(context, WebFeature::kImageCaptureTorch);
     }
-    // TODO(eero.hakkinen@intel.com): count how many times backgroundBlur is
-    // used.
+    if (RuntimeEnabledFeatures::MediaCaptureBackgroundBlurEnabled(context) &&
+        constraint_set->hasBackgroundBlur()) {
+      UseCounter::Count(context, WebFeature::kImageCaptureBackgroundBlur);
+    }
   }
 
   if (!service_.is_bound()) {
diff --git a/third_party/blink/renderer/modules/ml/ml_context.cc b/third_party/blink/renderer/modules/ml/ml_context.cc
index b36828c..6ec2da8f 100644
--- a/third_party/blink/renderer/modules/ml/ml_context.cc
+++ b/third_party/blink/renderer/modules/ml/ml_context.cc
@@ -40,6 +40,16 @@
   return num_threads_;
 }
 
+void MLContext::LogConsoleWarning(const String& message) {
+  auto* execution_context = ml_->GetExecutionContext();
+  if (!execution_context) {
+    return;
+  }
+  execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+      mojom::blink::ConsoleMessageSource::kJavaScript,
+      mojom::blink::ConsoleMessageLevel::kWarning, message));
+}
+
 ML* MLContext::GetML() {
   return ml_.Get();
 }
diff --git a/third_party/blink/renderer/modules/ml/ml_context.h b/third_party/blink/renderer/modules/ml/ml_context.h
index 2509233..63bf31e23 100644
--- a/third_party/blink/renderer/modules/ml/ml_context.h
+++ b/third_party/blink/renderer/modules/ml/ml_context.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_device_preference.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_model_format.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_power_preference.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -37,6 +38,7 @@
   V8MLPowerPreference GetPowerPreference() const;
   V8MLModelFormat GetModelFormat() const;
   unsigned int GetNumThreads() const;
+  void LogConsoleWarning(const String& message);
 
   ML* GetML();
 
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
index 8e74b31..05f70f7 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
@@ -13,13 +13,12 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_gemm_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_leaky_relu_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_operand_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_ml_pad_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_pool_2d_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_resample_2d_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_transpose_options.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/modules/ml/buildflags.h"
-#include "third_party/blink/renderer/modules/ml/ml.h"
 #include "third_party/blink/renderer/modules/ml/ml_context.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_activation.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph.h"
@@ -1024,6 +1023,64 @@
       this, MLOperator::OperatorKind::kLeakyRelu, options);
 }
 
+MLOperand* MLGraphBuilder::pad(const MLOperand* input,
+                               const Vector<uint32_t>& beginningPadding,
+                               const Vector<uint32_t>& endingPadding,
+                               const MLPadOptions* options,
+                               ExceptionState& exception_state) {
+  const auto input_rank = input->Dimensions().size();
+  if (beginningPadding.size() != input_rank) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
+                                      "The length of beginningPadding must be "
+                                      "equal to the rank of the input tensor.");
+    return nullptr;
+  }
+  if (endingPadding.size() != input_rank) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
+                                      "The length of endingPadding must be "
+                                      "equal to the rank of the input tensor.");
+    return nullptr;
+  }
+
+  if (options->mode().AsEnum() != V8MLPaddingMode::Enum::kConstant &&
+      fabs(options->value() - 0.0f) > std::numeric_limits<float>::epsilon()) {
+    ml_context_->LogConsoleWarning(
+        "The pad value is ignored unless the options.mode is set to "
+        "constant.");
+  }
+
+  // Each dimension of the output tensor can be calculated as follow:
+  // output_size = beginning_padding + input_size + ending_padding.
+  Vector<uint32_t> output_shape(input_rank);
+  for (wtf_size_t i = 0; i < input_rank; i++) {
+    auto checked_output_size =
+        base::MakeCheckedNum<uint32_t>(input->Dimensions()[i]) +
+        beginningPadding[i] + endingPadding[i];
+    if (!checked_output_size.AssignIfValid(&output_shape[i])) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kDataError,
+          String::Format("The padding of dimension (%u) is too large.", i));
+      return nullptr;
+    }
+  }
+
+  auto* pad = MakeGarbageCollected<MLOperator>(
+      this, MLOperator::OperatorKind::kPad, options);
+  String error_message;
+  // According to WebNN spec
+  // https://www.w3.org/TR/webnn/#api-mlgraphbuilder-pad, the output
+  // tensor of pad has the same type as its input.
+  auto* output = MLOperand::ValidateAndCreateOutput(
+      this, input->Type(), std::move(output_shape), pad, error_message);
+  if (!output) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
+                                      error_message);
+    return nullptr;
+  }
+  pad->Connect({input}, {output});
+  return output;
+}
+
 MLOperand* MLGraphBuilder::averagePool2d(const MLOperand* input,
                                          const MLPool2dOptions* options,
                                          ExceptionState& exception_state) {
@@ -1190,17 +1247,9 @@
   Vector<uint32_t> output_shape(input_shape);
   if (options->hasSizes()) {
     if (options->hasScales()) {
-      auto* execution_context = GetContext()->GetML()->GetExecutionContext();
-      if (!execution_context) {
-        exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
-                                          "Execution context is invalid.");
-        return nullptr;
-      }
-      execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
-          mojom::blink::ConsoleMessageSource::kJavaScript,
-          mojom::blink::ConsoleMessageLevel::kWarning,
+      ml_context_->LogConsoleWarning(
           "When sizes and scales are both specified, scales argument is "
-          "ignored."));
+          "ignored.");
     }
     if (options->sizes().size() != 2) {
       exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h
index 69d7cfe..82486ec 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h
@@ -27,6 +27,7 @@
 class MLGemmOptions;
 class MLGraph;
 class MLLeakyReluOptions;
+class MLPadOptions;
 class MLPool2dOptions;
 class MLResample2dOptions;
 class MLTransposeOptions;
@@ -127,6 +128,12 @@
   MLActivation* leakyRelu(const MLLeakyReluOptions* options,
                           ExceptionState& exception_state);
 
+  MLOperand* pad(const MLOperand* input,
+                 const Vector<uint32_t>& beginningPadding,
+                 const Vector<uint32_t>& endingPadding,
+                 const MLPadOptions* options,
+                 ExceptionState& exception_state);
+
   // Pooling operations
   MLOperand* averagePool2d(const MLOperand* input,
                            const MLPool2dOptions* options,
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl
index db81dd52..0e83e97 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl
@@ -36,6 +36,18 @@
   float alpha = 0.01;
 };
 
+enum MLPaddingMode {
+  "constant",
+  "edge",
+  "reflection",
+  "symmetric"
+};
+
+dictionary MLPadOptions {
+  MLPaddingMode mode = "constant";
+  float value = 0;
+};
+
 enum MLRoundingType {
   "floor",
   "ceil"
@@ -103,6 +115,9 @@
   [RaisesException] MLOperand leakyRelu(MLOperand x, optional MLLeakyReluOptions options = {});
   [RaisesException] MLActivation leakyRelu(optional MLLeakyReluOptions options = {});
 
+  [RaisesException] MLOperand pad(MLOperand input, sequence<[EnforceRange] unsigned long> beginningPadding,
+                sequence<[EnforceRange] unsigned long> endingPadding, optional MLPadOptions options = {});
+
   // Pooling operations
   [RaisesException] MLOperand averagePool2d(MLOperand input, optional MLPool2dOptions options = {});
   [RaisesException] MLOperand maxPool2d(MLOperand input, optional MLPool2dOptions options = {});
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
index 5d683fe..03229d9f9 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
@@ -2565,6 +2565,93 @@
   }
 }
 
+MLOperand* BuildPad(V8TestingScope& scope,
+                    MLGraphBuilder* builder,
+                    const MLOperand* input,
+                    const Vector<uint32_t>& beginningPadding,
+                    const Vector<uint32_t>& endingPadding,
+                    const MLPadOptions* options) {
+  auto* output = builder->pad(input, beginningPadding, endingPadding, options,
+                              scope.GetExceptionState());
+  EXPECT_NE(output, nullptr);
+  EXPECT_EQ(output->Kind(), MLOperand::OperandKind::kOutput);
+  EXPECT_EQ(output->Type(), input->Type());
+  auto* pad = output->Operator();
+  EXPECT_NE(pad, nullptr);
+  EXPECT_EQ(pad->Kind(), MLOperator::OperatorKind::kPad);
+  EXPECT_EQ(pad->IsConnected(), true);
+  EXPECT_NE(pad->Options(), nullptr);
+  return output;
+}
+
+TEST_F(MLGraphBuilderTest, PadTest) {
+  V8TestingScope scope;
+  MLGraphBuilder* builder = CreateMLGraphBuilder(scope.GetExecutionContext());
+  {
+    // Test building pad with default options, beginningPadding = {1, 2} and
+    // endingPadding = {1, 2}.
+    auto* input =
+        BuildInput(builder, "input", {2, 3}, V8MLOperandType::Enum::kFloat32,
+                   scope.GetExceptionState());
+    auto* options = MLPadOptions::Create();
+    EXPECT_TRUE(options->hasMode());
+    EXPECT_EQ(options->mode(), V8MLPaddingMode::Enum::kConstant);
+    EXPECT_TRUE(options->hasValue());
+    EXPECT_EQ(options->value(), 0);
+    auto* output = BuildPad(scope, builder, input, {1, 2}, {1, 2}, options);
+    EXPECT_EQ(output->Dimensions(), Vector<uint32_t>({4, 7}));
+  }
+  {
+    // Test throwing error when the length of beginningPadding is not equal to
+    // the input rank.
+    auto* input =
+        BuildInput(builder, "input", {2, 3}, V8MLOperandType::Enum::kFloat32,
+                   scope.GetExceptionState());
+    auto* options = MLPadOptions::Create();
+    options->setMode(V8MLPaddingMode::Enum::kEdge);
+    auto* output =
+        builder->pad(input, {1}, {1, 2}, options, scope.GetExceptionState());
+    EXPECT_EQ(output, nullptr);
+    EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
+              DOMExceptionCode::kDataError);
+    EXPECT_EQ(scope.GetExceptionState().Message(),
+              "The length of beginningPadding must be equal to the rank of the "
+              "input tensor.");
+  }
+  {
+    // Test throwing error when the length of endingPadding is not equal to the
+    // input rank.
+    auto* input =
+        BuildInput(builder, "input", {2, 3}, V8MLOperandType::Enum::kFloat32,
+                   scope.GetExceptionState());
+    auto* options = MLPadOptions::Create();
+    options->setMode(V8MLPaddingMode::Enum::kReflection);
+    auto* output = builder->pad(input, {1, 0}, {1, 2, 0}, options,
+                                scope.GetExceptionState());
+    EXPECT_EQ(output, nullptr);
+    EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
+              DOMExceptionCode::kDataError);
+    EXPECT_EQ(scope.GetExceptionState().Message(),
+              "The length of endingPadding must be equal to the rank of the "
+              "input tensor.");
+  }
+  {
+    // Test throwing error when the padding of one dimension is too large.
+    auto* input =
+        BuildInput(builder, "input", {2, 3}, V8MLOperandType::Enum::kFloat32,
+                   scope.GetExceptionState());
+    auto* options = MLPadOptions::Create();
+    options->setMode(V8MLPaddingMode::Enum::kReflection);
+    auto* output = builder->pad(input, {2294967295, 0}, {3294967295, 2},
+                                options, scope.GetExceptionState());
+    EXPECT_EQ(output, nullptr);
+    EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
+              DOMExceptionCode::kDataError);
+    EXPECT_EQ(scope.GetExceptionState().Message(),
+              "The padding of dimension (0) is too large.");
+  }
+}
+
 TEST_F(MLGraphBuilderTest, Softmax) {
   V8TestingScope scope;
   MLGraphBuilder* builder = CreateMLGraphBuilder(scope.GetExecutionContext());
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.h b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.h
index cdf315686..cf40da3 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.h
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.h
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_gemm_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_leaky_relu_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_operand_type.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_ml_pad_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_pool_2d_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_resample_2d_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_transpose_options.h"
@@ -55,6 +56,13 @@
                                   const MLOperand* a,
                                   const MLOperand* b);
 
+MLOperand* BuildPad(V8TestingScope& scope,
+                    MLGraphBuilder* builder,
+                    const MLOperand* input,
+                    const Vector<uint32_t>& beginningPadding,
+                    const Vector<uint32_t>& endingPadding,
+                    const MLPadOptions* options = MLPadOptions::Create());
+
 enum class Pool2dKind { kAverage, kMax };
 
 MLOperand* BuildPool2d(
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_operator.cc b/third_party/blink/renderer/modules/ml/webnn/ml_operator.cc
index 5dd7d40..1353d7c 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_operator.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_operator.cc
@@ -40,6 +40,8 @@
       return "averagePool2d";
     case MLOperator::OperatorKind::kMaxPool2d:
       return "maxPool2d";
+    case MLOperator::OperatorKind::kPad:
+      return "pad";
     case MLOperator::OperatorKind::kRelu:
       return "relu";
     case MLOperator::OperatorKind::kReshape:
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_operator.h b/third_party/blink/renderer/modules/ml/webnn/ml_operator.h
index 4a84508b..fe725193 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_operator.h
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_operator.h
@@ -35,6 +35,7 @@
     kHardSwish,
     kAveragePool2d,
     kMaxPool2d,
+    kPad,
     kRelu,
     kReshape,
     kResample2d,
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_client.h b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_client.h
index d3615d4..da04e603 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_client.h
+++ b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_client.h
@@ -61,7 +61,7 @@
                                  is_remote_description);
   }
   MOCK_METHOD1(DidAddRemoteDataChannel,
-               void(scoped_refptr<webrtc::DataChannelInterface>));
+               void(rtc::scoped_refptr<webrtc::DataChannelInterface>));
   MOCK_METHOD1(DidNoteInterestingUsage, void(int));
   MOCK_METHOD0(UnregisterPeerConnectionHandler, void());
 
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
index 1a2b522..86cc0b1b 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
+++ b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
@@ -382,7 +382,7 @@
   return std::unique_ptr<RTCRtpTransceiverPlatform>(std::move(copy));
 }
 
-scoped_refptr<webrtc::DataChannelInterface>
+rtc::scoped_refptr<webrtc::DataChannelInterface>
 MockRTCPeerConnectionHandlerPlatform::CreateDataChannel(
     const String& label,
     const webrtc::DataChannelInit&) {
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h
index 13bdc81..b6858c5 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h
+++ b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.h
@@ -94,7 +94,7 @@
       const MediaStreamDescriptorVector&) override;
   webrtc::RTCErrorOr<std::unique_ptr<RTCRtpTransceiverPlatform>> RemoveTrack(
       RTCRtpSenderPlatform*) override;
-  scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
+  rtc::scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
       const String& label,
       const webrtc::DataChannelInit&) override;
   webrtc::PeerConnectionInterface* NativePeerConnection() override;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
index 26879ee..71f836f8 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
@@ -56,9 +56,9 @@
 namespace WTF {
 
 template <>
-struct CrossThreadCopier<scoped_refptr<webrtc::DataChannelInterface>>
+struct CrossThreadCopier<rtc::scoped_refptr<webrtc::DataChannelInterface>>
     : public CrossThreadCopierPassThrough<
-          scoped_refptr<webrtc::DataChannelInterface>> {
+          rtc::scoped_refptr<webrtc::DataChannelInterface>> {
   STATIC_ONLY(CrossThreadCopier);
 };
 
@@ -185,7 +185,7 @@
 }
 
 void SendOnSignalingThread(
-    const scoped_refptr<webrtc::DataChannelInterface> channel,
+    const rtc::scoped_refptr<webrtc::DataChannelInterface> channel,
     const webrtc::DataBuffer data_buffer) {
   // The Javascript API being synchronous, we cannot wait for the call on the
   // signaling thread to resolve from the JS main thread. So we make sure that
@@ -226,7 +226,7 @@
 RTCDataChannel::Observer::Observer(
     scoped_refptr<base::SingleThreadTaskRunner> main_thread,
     RTCDataChannel* blink_channel,
-    scoped_refptr<webrtc::DataChannelInterface> channel)
+    rtc::scoped_refptr<webrtc::DataChannelInterface> channel)
     : main_thread_(main_thread),
       blink_channel_(blink_channel),
       webrtc_channel_(channel) {}
@@ -236,7 +236,7 @@
   DCHECK(!webrtc_channel_.get()) << "Unregister hasn't been called.";
 }
 
-const scoped_refptr<webrtc::DataChannelInterface>&
+const rtc::scoped_refptr<webrtc::DataChannelInterface>&
 RTCDataChannel::Observer::channel() const {
   return webrtc_channel_;
 }
@@ -303,7 +303,7 @@
 
 RTCDataChannel::RTCDataChannel(
     ExecutionContext* context,
-    scoped_refptr<webrtc::DataChannelInterface> channel,
+    rtc::scoped_refptr<webrtc::DataChannelInterface> channel,
     RTCPeerConnectionHandler* peer_connection_handler)
     : ExecutionContextLifecycleObserver(context),
       state_(webrtc::DataChannelInterface::kConnecting),
@@ -331,7 +331,7 @@
       CrossThreadBindOnce(
           [](scoped_refptr<RTCDataChannel::Observer> observer,
              webrtc::DataChannelInterface::DataState current_state) {
-            scoped_refptr<webrtc::DataChannelInterface> channel =
+            rtc::scoped_refptr<webrtc::DataChannelInterface> channel =
                 observer->channel();
             channel->RegisterObserver(observer.get());
             if (channel->state() != current_state) {
@@ -713,8 +713,8 @@
   events.clear();
 }
 
-const scoped_refptr<webrtc::DataChannelInterface>& RTCDataChannel::channel()
-    const {
+const rtc::scoped_refptr<webrtc::DataChannelInterface>&
+RTCDataChannel::channel() const {
   return observer_->channel();
 }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
index 21bb393..6e70ac2aa 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
@@ -57,7 +57,7 @@
 
  public:
   RTCDataChannel(ExecutionContext*,
-                 scoped_refptr<webrtc::DataChannelInterface> channel,
+                 rtc::scoped_refptr<webrtc::DataChannelInterface> channel,
                  RTCPeerConnectionHandler* peer_connection_handler);
   ~RTCDataChannel() override;
 
@@ -126,13 +126,13 @@
    public:
     Observer(scoped_refptr<base::SingleThreadTaskRunner> main_thread,
              RTCDataChannel* blink_channel,
-             scoped_refptr<webrtc::DataChannelInterface> channel);
+             rtc::scoped_refptr<webrtc::DataChannelInterface> channel);
     ~Observer() override;
 
     // Returns a reference to |webrtc_channel_|. Typically called from the main
     // thread except for on observer registration, done in a synchronous call to
     // the signaling thread (safe because the call is synchronous).
-    const scoped_refptr<webrtc::DataChannelInterface>& channel() const;
+    const rtc::scoped_refptr<webrtc::DataChannelInterface>& channel() const;
 
     // Clears the |blink_channel_| reference, disassociates this observer from
     // the |webrtc_channel_| and releases the |webrtc_channel_| pointer. Must be
@@ -152,7 +152,7 @@
 
     const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
     WeakPersistent<RTCDataChannel> blink_channel_;
-    scoped_refptr<webrtc::DataChannelInterface> webrtc_channel_;
+    rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel_;
   };
 
   void OnStateChange(webrtc::DataChannelInterface::DataState state);
@@ -164,7 +164,7 @@
   void ScheduleDispatchEvent(Event*);
   void ScheduledEventTimerFired(TimerBase*);
 
-  const scoped_refptr<webrtc::DataChannelInterface>& channel() const;
+  const rtc::scoped_refptr<webrtc::DataChannelInterface>& channel() const;
   bool ValidateSendLength(size_t length, ExceptionState& exception_state);
   void SendRawData(const char* data, size_t length);
   void SendDataBuffer(webrtc::DataBuffer data_buffer);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
index ab4db7e78..a5a89e4 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
@@ -241,7 +241,7 @@
 }  // namespace
 
 TEST_F(RTCDataChannelTest, ChangeStateEarly) {
-  scoped_refptr<MockDataChannel> webrtc_channel(
+  rtc::scoped_refptr<MockDataChannel> webrtc_channel(
       new rtc::RefCountedObject<MockDataChannel>(signaling_thread()));
 
   // Change state on the webrtc channel before creating the blink channel.
@@ -250,7 +250,7 @@
   std::unique_ptr<MockPeerConnectionHandler> pc(
       new MockPeerConnectionHandler(signaling_thread()));
   auto* channel = MakeGarbageCollected<RTCDataChannel>(
-      execution_context_, webrtc_channel.get(), pc.get());
+      execution_context_, webrtc_channel, pc.get());
 
   // In RTCDataChannel::Create, the state change update is posted from the
   // signaling thread to the main thread. Wait for posted the task to be
@@ -262,12 +262,12 @@
 }
 
 TEST_F(RTCDataChannelTest, BufferedAmount) {
-  scoped_refptr<MockDataChannel> webrtc_channel(
+  rtc::scoped_refptr<MockDataChannel> webrtc_channel(
       new rtc::RefCountedObject<MockDataChannel>(signaling_thread()));
   std::unique_ptr<MockPeerConnectionHandler> pc(
       new MockPeerConnectionHandler(signaling_thread()));
   auto* channel = MakeGarbageCollected<RTCDataChannel>(
-      execution_context_, webrtc_channel.get(), pc.get());
+      execution_context_, webrtc_channel, pc.get());
   webrtc_channel->ChangeState(webrtc::DataChannelInterface::kOpen);
 
   String message(std::string(100, 'A').c_str());
@@ -279,12 +279,12 @@
 }
 
 TEST_F(RTCDataChannelTest, BufferedAmountLow) {
-  scoped_refptr<MockDataChannel> webrtc_channel(
+  rtc::scoped_refptr<MockDataChannel> webrtc_channel(
       new rtc::RefCountedObject<MockDataChannel>(signaling_thread()));
   std::unique_ptr<MockPeerConnectionHandler> pc(
       new MockPeerConnectionHandler(signaling_thread()));
   auto* channel = MakeGarbageCollected<RTCDataChannel>(
-      execution_context_, webrtc_channel.get(), pc.get());
+      execution_context_, webrtc_channel, pc.get());
   webrtc_channel->ChangeState(webrtc::DataChannelInterface::kOpen);
 
   channel->setBufferedAmountLowThreshold(1);
@@ -300,34 +300,34 @@
 }
 
 TEST_F(RTCDataChannelTest, Open) {
-  scoped_refptr<MockDataChannel> webrtc_channel(
+  rtc::scoped_refptr<MockDataChannel> webrtc_channel(
       new rtc::RefCountedObject<MockDataChannel>(signaling_thread()));
   std::unique_ptr<MockPeerConnectionHandler> pc(
       new MockPeerConnectionHandler(signaling_thread()));
   auto* channel = MakeGarbageCollected<RTCDataChannel>(
-      execution_context_, webrtc_channel.get(), pc.get());
+      execution_context_, webrtc_channel, pc.get());
   channel->OnStateChange(webrtc::DataChannelInterface::kOpen);
   EXPECT_EQ("open", channel->readyState());
 }
 
 TEST_F(RTCDataChannelTest, Close) {
-  scoped_refptr<MockDataChannel> webrtc_channel(
+  rtc::scoped_refptr<MockDataChannel> webrtc_channel(
       new rtc::RefCountedObject<MockDataChannel>(signaling_thread()));
   std::unique_ptr<MockPeerConnectionHandler> pc(
       new MockPeerConnectionHandler(signaling_thread()));
   auto* channel = MakeGarbageCollected<RTCDataChannel>(
-      execution_context_, webrtc_channel.get(), pc.get());
+      execution_context_, webrtc_channel, pc.get());
   channel->OnStateChange(webrtc::DataChannelInterface::kClosed);
   EXPECT_EQ("closed", channel->readyState());
 }
 
 TEST_F(RTCDataChannelTest, Message) {
-  scoped_refptr<MockDataChannel> webrtc_channel(
+  rtc::scoped_refptr<MockDataChannel> webrtc_channel(
       new rtc::RefCountedObject<MockDataChannel>(signaling_thread()));
   std::unique_ptr<MockPeerConnectionHandler> pc(
       new MockPeerConnectionHandler(signaling_thread()));
   auto* channel = MakeGarbageCollected<RTCDataChannel>(
-      execution_context_, webrtc_channel.get(), pc.get());
+      execution_context_, webrtc_channel, pc.get());
 
   std::unique_ptr<webrtc::DataBuffer> message(new webrtc::DataBuffer("A"));
   channel->OnMessage(std::move(message));
@@ -336,12 +336,12 @@
 }
 
 TEST_F(RTCDataChannelTest, SendAfterContextDestroyed) {
-  scoped_refptr<MockDataChannel> webrtc_channel(
+  rtc::scoped_refptr<MockDataChannel> webrtc_channel(
       new rtc::RefCountedObject<MockDataChannel>(signaling_thread()));
   std::unique_ptr<MockPeerConnectionHandler> pc(
       new MockPeerConnectionHandler(signaling_thread()));
   auto* channel = MakeGarbageCollected<RTCDataChannel>(
-      execution_context_, webrtc_channel.get(), pc.get());
+      execution_context_, webrtc_channel, pc.get());
   webrtc_channel->ChangeState(webrtc::DataChannelInterface::kOpen);
 
   channel->ContextDestroyed();
@@ -354,12 +354,12 @@
 }
 
 TEST_F(RTCDataChannelTest, CloseAfterContextDestroyed) {
-  scoped_refptr<MockDataChannel> webrtc_channel(
+  rtc::scoped_refptr<MockDataChannel> webrtc_channel(
       new rtc::RefCountedObject<MockDataChannel>(signaling_thread()));
   std::unique_ptr<MockPeerConnectionHandler> pc(
       new MockPeerConnectionHandler(signaling_thread()));
   auto* channel = MakeGarbageCollected<RTCDataChannel>(
-      execution_context_, webrtc_channel.get(), pc.get());
+      execution_context_, webrtc_channel, pc.get());
   webrtc_channel->ChangeState(webrtc::DataChannelInterface::kOpen);
 
   channel->ContextDestroyed();
@@ -374,12 +374,12 @@
   EXPECT_FALSE(scheduler->OptedOutFromAggressiveThrottlingForTest());
 
   // Creating an RTCDataChannel doesn't enable the opt-out.
-  scoped_refptr<MockDataChannel> webrtc_channel(
+  rtc::scoped_refptr<MockDataChannel> webrtc_channel(
       new rtc::RefCountedObject<MockDataChannel>(signaling_thread()));
   std::unique_ptr<MockPeerConnectionHandler> pc(
       new MockPeerConnectionHandler(signaling_thread()));
   auto* channel = MakeGarbageCollected<RTCDataChannel>(
-      scope.GetExecutionContext(), webrtc_channel.get(), pc.get());
+      scope.GetExecutionContext(), webrtc_channel, pc.get());
   EXPECT_EQ("connecting", channel->readyState());
   EXPECT_FALSE(scheduler->OptedOutFromAggressiveThrottlingForTest());
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index e5da225..1ac5983 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -2019,7 +2019,7 @@
   }
   // Further checks of DataChannelId are done in the webrtc layer.
 
-  scoped_refptr<webrtc::DataChannelInterface> webrtc_channel =
+  rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel =
       peer_handler_->CreateDataChannel(label, init);
   if (!webrtc_channel) {
     exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
@@ -2579,7 +2579,7 @@
 }
 
 void RTCPeerConnection::DidAddRemoteDataChannel(
-    scoped_refptr<webrtc::DataChannelInterface> channel) {
+    rtc::scoped_refptr<webrtc::DataChannelInterface> channel) {
   DCHECK(!closed_);
   DCHECK(GetExecutionContext()->IsContextThread());
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
index 25846c19..8f58dd1 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
@@ -303,7 +303,7 @@
                              Vector<uintptr_t>,
                              bool is_remote_description_or_rollback) override;
   void DidAddRemoteDataChannel(
-      scoped_refptr<webrtc::DataChannelInterface> channel) override;
+      rtc::scoped_refptr<webrtc::DataChannelInterface> channel) override;
   void DidNoteInterestingUsage(int usage_pattern) override;
   void UnregisterPeerConnectionHandler() override;
   void ClosePeerConnection() override;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
index 8c11323..9f8534b 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -794,8 +794,7 @@
         *main_thread_.get(), FROM_HERE,
         CrossThreadBindOnce(
             &RTCPeerConnectionHandler::Observer::OnDataChannelImpl,
-            WrapCrossThreadPersistent(this),
-            base::WrapRefCounted<DataChannelInterface>(data_channel.get())));
+            WrapCrossThreadPersistent(this), data_channel));
   }
 
   void OnNegotiationNeededEvent(uint32_t event_id) override {
@@ -905,10 +904,10 @@
             String::FromUTF8(url), error_code, String::FromUTF8(error_text)));
   }
 
-  void OnDataChannelImpl(scoped_refptr<DataChannelInterface> channel) {
+  void OnDataChannelImpl(rtc::scoped_refptr<DataChannelInterface> channel) {
     DCHECK(main_thread_->BelongsToCurrentThread());
     if (handler_)
-      handler_->OnDataChannel(std::move(channel));
+      handler_->OnDataChannel(channel);
   }
 
   void OnIceCandidateImpl(const String& sdp,
@@ -1978,7 +1977,8 @@
   }
 }
 
-scoped_refptr<DataChannelInterface> RTCPeerConnectionHandler::CreateDataChannel(
+rtc::scoped_refptr<DataChannelInterface>
+RTCPeerConnectionHandler::CreateDataChannel(
     const String& label,
     const webrtc::DataChannelInit& init) {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
@@ -1998,8 +1998,7 @@
         PeerConnectionTracker::kSourceLocal);
   }
 
-  return base::WrapRefCounted<DataChannelInterface>(
-      webrtc_channel.value().get());
+  return webrtc_channel.value();
 }
 
 void RTCPeerConnectionHandler::Close() {
@@ -2250,7 +2249,7 @@
 }
 
 void RTCPeerConnectionHandler::OnDataChannel(
-    scoped_refptr<DataChannelInterface> channel) {
+    rtc::scoped_refptr<DataChannelInterface> channel) {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
index 3c27a11c..2e18f11 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h
@@ -222,7 +222,7 @@
   virtual webrtc::RTCErrorOr<std::unique_ptr<RTCRtpTransceiverPlatform>>
   RemoveTrack(blink::RTCRtpSenderPlatform* web_sender);
 
-  virtual scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
+  virtual rtc::scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
       const String& label,
       const webrtc::DataChannelInit& init);
   virtual webrtc::PeerConnectionInterface* NativePeerConnection();
@@ -313,7 +313,7 @@
       std::vector<blink::RtpTransceiverState> transceiver_states,
       bool is_remote_description,
       bool is_rollback);
-  void OnDataChannel(scoped_refptr<webrtc::DataChannelInterface> channel);
+  void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> channel);
   void OnIceCandidate(const String& sdp,
                       const String& sdp_mid,
                       int sdp_mline_index,
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
index 5234f05..71214c4 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
@@ -1193,7 +1193,7 @@
   EXPECT_CALL(*mock_tracker_.Get(),
               TrackCreateDataChannel(pc_handler_.get(), testing::NotNull(),
                                      PeerConnectionTracker::kSourceLocal));
-  scoped_refptr<webrtc::DataChannelInterface> channel =
+  rtc::scoped_refptr<webrtc::DataChannelInterface> channel =
       pc_handler_->CreateDataChannel("d1", webrtc::DataChannelInit());
   EXPECT_TRUE(channel.get());
   EXPECT_EQ(label.Utf8(), channel->label());
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
index cc37a617..523036c6 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
@@ -55,18 +55,22 @@
       receiver_(std::move(receiver)),
       track_(track),
       streams_(std::move(streams)),
-      encoded_insertable_streams_(encoded_insertable_streams) {
+      encoded_insertable_streams_(encoded_insertable_streams),
+      encoded_audio_transformer_(
+          encoded_insertable_streams_ && kind() == MediaKind::kAudio
+              ? receiver_->GetEncodedAudioStreamTransformer()->GetBroker()
+              : nullptr),
+      encoded_video_transformer_(
+          encoded_insertable_streams_ && kind() == MediaKind::kVideo
+              ? receiver_->GetEncodedVideoStreamTransformer()->GetBroker()
+              : nullptr) {
   DCHECK(pc_);
   DCHECK(receiver_);
   DCHECK(track_);
-  if (encoded_insertable_streams_ && kind() == MediaKind::kAudio) {
-    encoded_audio_transformer_ =
-        receiver_->GetEncodedAudioStreamTransformer()->GetBroker();
+  if (encoded_audio_transformer_) {
     RegisterEncodedAudioStreamCallback();
   }
-  if (encoded_insertable_streams_ && kind() == MediaKind::kVideo) {
-    encoded_video_transformer_ =
-        receiver_->GetEncodedVideoStreamTransformer()->GetBroker();
+  if (encoded_video_transformer_) {
     RegisterEncodedVideoStreamCallback();
   }
 }
@@ -361,6 +365,8 @@
 }
 
 void RTCRtpReceiver::UnregisterEncodedAudioStreamCallback() {
+  // Threadsafe as this might be called from the realm to which a stream has
+  // been transferred.
   encoded_audio_transformer_->ResetTransformerCallback();
 }
 
@@ -477,6 +483,8 @@
 }
 
 void RTCRtpReceiver::UnregisterEncodedVideoStreamCallback() {
+  // Threadsafe as this might be called from the realm to which a stream has
+  // been transferred.
   encoded_video_transformer_->ResetTransformerCallback();
 }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h
index a0840e5e..6cf2e27 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h
@@ -130,6 +130,8 @@
   // use Encoded Insertable Streams.
   bool encoded_insertable_streams_;
 
+  THREAD_CHECKER(thread_checker_);
+
   // Insertable Streams support for audio.
   base::Lock audio_underlying_source_lock_;
   CrossThreadPersistent<RTCEncodedAudioUnderlyingSource>
@@ -139,7 +141,7 @@
   CrossThreadPersistent<RTCEncodedAudioUnderlyingSink>
       audio_to_decoder_underlying_sink_ GUARDED_BY(audio_underlying_sink_lock_);
   Member<RTCInsertableStreams> encoded_audio_streams_;
-  scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker>
+  const scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker>
       encoded_audio_transformer_;
 
   // Insertable Streams support for video.
@@ -151,10 +153,8 @@
   CrossThreadPersistent<RTCEncodedVideoUnderlyingSink>
       video_to_decoder_underlying_sink_ GUARDED_BY(video_underlying_sink_lock_);
   Member<RTCInsertableStreams> encoded_video_streams_;
-  scoped_refptr<blink::RTCEncodedVideoStreamTransformer::Broker>
+  const scoped_refptr<blink::RTCEncodedVideoStreamTransformer::Broker>
       encoded_video_transformer_;
-
-  THREAD_CHECKER(thread_checker_);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
index f6a18a6..61e94f75 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -563,18 +563,22 @@
       kind_(std::move(kind)),
       track_(track),
       streams_(std::move(streams)),
-      encoded_insertable_streams_(encoded_insertable_streams) {
+      encoded_insertable_streams_(encoded_insertable_streams),
+      encoded_audio_transformer_(
+          encoded_insertable_streams_ && kind_ == "audio"
+              ? sender_->GetEncodedAudioStreamTransformer()->GetBroker()
+              : nullptr),
+      encoded_video_transformer_(
+          encoded_insertable_streams_ && kind_ == "video"
+              ? sender_->GetEncodedVideoStreamTransformer()->GetBroker()
+              : nullptr) {
   DCHECK(pc_);
   DCHECK(sender_);
   DCHECK(!track || kind_ == track->kind());
-  if (encoded_insertable_streams_ && kind_ == "audio") {
-    encoded_audio_transformer_ =
-        sender_->GetEncodedAudioStreamTransformer()->GetBroker();
+  if (encoded_audio_transformer_) {
     RegisterEncodedAudioStreamCallback();
   }
-  if (encoded_insertable_streams_ && kind_ == "video") {
-    encoded_video_transformer_ =
-        sender_->GetEncodedVideoStreamTransformer()->GetBroker();
+  if (encoded_video_transformer_) {
     RegisterEncodedVideoStreamCallback();
   }
 }
@@ -1007,7 +1011,8 @@
 }
 
 void RTCRtpSender::UnregisterEncodedAudioStreamCallback() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  // Threadsafe as this might be called from the realm to which a stream has
+  // been transferred.
   encoded_audio_transformer_->ResetTransformerCallback();
 }
 
@@ -1124,7 +1129,8 @@
 }
 
 void RTCRtpSender::UnregisterEncodedVideoStreamCallback() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  // Threadsafe as this might be called from the realm to which a stream has
+  // been transferred.
   encoded_video_transformer_->ResetTransformerCallback();
 }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h
index c7a396f..f1f6351 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h
@@ -145,7 +145,7 @@
       audio_to_packetizer_underlying_sink_
           GUARDED_BY(audio_underlying_sink_lock_);
   Member<RTCInsertableStreams> encoded_audio_streams_;
-  scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker>
+  const scoped_refptr<blink::RTCEncodedAudioStreamTransformer::Broker>
       encoded_audio_transformer_;
 
   // Insertable Streams video support
@@ -158,7 +158,7 @@
       video_to_packetizer_underlying_sink_
           GUARDED_BY(video_underlying_sink_lock_);
   Member<RTCInsertableStreams> encoded_video_streams_;
-  scoped_refptr<blink::RTCEncodedVideoStreamTransformer::Broker>
+  const scoped_refptr<blink::RTCEncodedVideoStreamTransformer::Broker>
       encoded_video_transformer_;
 
   THREAD_CHECKER(thread_checker_);
diff --git a/third_party/blink/renderer/modules/shapedetection/shape_detector.cc b/third_party/blink/renderer/modules/shapedetection/shape_detector.cc
index 09c85fd..5e9108c 100644
--- a/third_party/blink/renderer/modules/shapedetection/shape_detector.cc
+++ b/third_party/blink/renderer/modules/shapedetection/shape_detector.cc
@@ -106,13 +106,14 @@
   }
 
   // GetSwSkImage() will make a raster copy of PaintImageForCurrentFrame()
-  // if needed, otherwise returning the original SkImage.
+  // if needed, otherwise returning the original SkImage. May return nullptr
+  // if resource allocation failed.
   const sk_sp<SkImage> sk_image =
       image->PaintImageForCurrentFrame().GetSwSkImage();
 
   SkBitmap sk_bitmap;
   SkBitmap n32_bitmap;
-  if (!sk_image->asLegacyBitmap(&sk_bitmap) ||
+  if (!sk_image || !sk_image->asLegacyBitmap(&sk_bitmap) ||
       !skia::SkBitmapToN32OpaqueOrPremul(sk_bitmap, &n32_bitmap)) {
     // TODO(mcasas): retrieve the pixels from elsewhere.
     NOTREACHED();
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_encoder_base.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_encoder_base.idl
index f77d74f..39a1422 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_render_encoder_base.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_render_encoder_base.idl
@@ -5,30 +5,30 @@
 // https://gpuweb.github.io/gpuweb/
 
 interface mixin GPURenderEncoderBase {
-    void setPipeline(GPURenderPipeline pipeline);
+    [NoAllocDirectCall] void setPipeline(GPURenderPipeline pipeline);
 
     void setIndexBuffer(GPUBuffer buffer,
                         GPUIndexFormat format,
                         optional GPUSize64 offset = 0,
                         optional GPUSize64 size);
 
-    void setVertexBuffer(GPUIndex32 slot,
-                         GPUBuffer buffer,
-                         optional GPUSize64 offset = 0,
-                         optional GPUSize64 size);
+    [NoAllocDirectCall] void setVertexBuffer(GPUIndex32 slot,
+                                             GPUBuffer buffer,
+                                             optional GPUSize64 offset = 0,
+                                             optional GPUSize64 size);
 
-    void draw(GPUSize32 vertexCount,
-              optional GPUSize32 instanceCount = 1,
-              optional GPUSize32 firstVertex = 0,
-              optional GPUSize32 firstInstance = 0);
-    void drawIndexed(GPUSize32 indexCount,
-                     optional GPUSize32 instanceCount = 1,
-                     optional GPUSize32 firstIndex = 0,
-                     optional GPUSignedOffset32 baseVertex = 0,
-                     optional GPUSize32 firstInstance = 0);
+    [NoAllocDirectCall] void draw(GPUSize32 vertexCount,
+                                  optional GPUSize32 instanceCount = 1,
+                                  optional GPUSize32 firstVertex = 0,
+                                  optional GPUSize32 firstInstance = 0);
+    [NoAllocDirectCall] void drawIndexed(GPUSize32 indexCount,
+                                         optional GPUSize32 instanceCount = 1,
+                                         optional GPUSize32 firstIndex = 0,
+                                         optional GPUSignedOffset32 baseVertex = 0,
+                                         optional GPUSize32 firstInstance = 0);
 
-    void drawIndirect(GPUBuffer indirectBuffer,
-                      GPUSize64 indirectOffset);
-    void drawIndexedIndirect(GPUBuffer indirectBuffer,
-                             GPUSize64 indirectOffset);
+    [NoAllocDirectCall] void drawIndirect(GPUBuffer indirectBuffer,
+                                          GPUSize64 indirectOffset);
+    [NoAllocDirectCall] void drawIndexedIndirect(GPUBuffer indirectBuffer,
+                                                 GPUSize64 indirectOffset);
 };
diff --git a/third_party/blink/renderer/platform/graphics/color.cc b/third_party/blink/renderer/platform/graphics/color.cc
index 7cf0d04..f63920e8 100644
--- a/third_party/blink/renderer/platform/graphics/color.cc
+++ b/third_party/blink/renderer/platform/graphics/color.cc
@@ -25,6 +25,7 @@
 
 #include "third_party/blink/renderer/platform/graphics/color.h"
 
+#include "base/check_op.h"
 #include "base/notreached.h"
 #include "build/build_config.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -224,7 +225,7 @@
 }
 
 // static
-Color Color::FromColorMix(Color::ColorInterpolationSpace interpolation_space,
+Color Color::FromColorMix(Color::ColorSpace interpolation_space,
                           absl::optional<HueInterpolationMethod> hue_method,
                           Color color1,
                           Color color2,
@@ -341,38 +342,8 @@
 }
 
 // static
-Color::ColorSpace Color::ColorInterpolationSpaceToColorSpace(
-    Color::ColorInterpolationSpace color_interpolation_space) {
-  switch (color_interpolation_space) {
-    case (ColorInterpolationSpace::kXYZD65):
-      return ColorSpace::kXYZD65;
-    case (ColorInterpolationSpace::kXYZD50):
-      return ColorSpace::kXYZD50;
-    case (ColorInterpolationSpace::kSRGBLinear):
-      return ColorSpace::kSRGBLinear;
-    case (ColorInterpolationSpace::kLab):
-      return ColorSpace::kLab;
-    case (ColorInterpolationSpace::kOklab):
-      return ColorSpace::kOklab;
-    case (ColorInterpolationSpace::kLch):
-      return ColorSpace::kLch;
-    case (ColorInterpolationSpace::kOklch):
-      return ColorSpace::kOklch;
-    case (ColorInterpolationSpace::kHSL):
-      return ColorSpace::kHSL;
-    case (ColorInterpolationSpace::kHWB):
-      return ColorSpace::kHWB;
-    case (ColorInterpolationSpace::kSRGBLegacy):
-      return ColorSpace::kSRGBLegacy;
-    case (ColorInterpolationSpace::kSRGB):
-    case (ColorInterpolationSpace::kNone):
-      return ColorSpace::kSRGB;
-  }
-}
-
-// static
 Color Color::InterpolateColors(
-    Color::ColorInterpolationSpace interpolation_space,
+    Color::ColorSpace interpolation_space,
     absl::optional<HueInterpolationMethod> hue_method,
     Color color1,
     Color color2,
@@ -382,9 +353,9 @@
   DCHECK(percentage >= 0.0f && percentage <= 1.0f);
 
   const auto color1_prev_color_space = color1.GetColorSpace();
-  color1.ConvertToColorInterpolationSpace(interpolation_space);
+  color1.ConvertToColorSpace(interpolation_space);
   const auto color2_prev_color_space = color2.GetColorSpace();
-  color2.ConvertToColorInterpolationSpace(interpolation_space);
+  color2.ConvertToColorSpace(interpolation_space);
 
   CarryForwardAnalogousMissingComponents(color1, color1_prev_color_space);
   CarryForwardAnalogousMissingComponents(color2, color2_prev_color_space);
@@ -420,8 +391,8 @@
       (color1.param0_is_none_ || color2.param0_is_none_)
           ? HandleNoneInterpolation(color1.param0_, color1.param0_is_none_,
                                     color2.param0_, color2.param0_is_none_)
-      : (interpolation_space == ColorInterpolationSpace::kHSL ||
-         interpolation_space == ColorInterpolationSpace::kHWB)
+      : (interpolation_space == ColorSpace::kHSL ||
+         interpolation_space == ColorSpace::kHWB)
           // TODO(aaronhk): Historically we store hue in the range [0, 6] for
           // hsl and hwb. This is so that primary and secondary colors are
           // integers. With the addition of lch and oklch, this makes less
@@ -442,8 +413,8 @@
       (color1.param2_is_none_ || color2.param2_is_none_)
           ? HandleNoneInterpolation(color1.param2_, color1.param2_is_none_,
                                     color2.param2_, color2.param2_is_none_)
-      : (interpolation_space == ColorInterpolationSpace::kLch ||
-         interpolation_space == ColorInterpolationSpace::kOklch)
+      : (interpolation_space == ColorSpace::kLch ||
+         interpolation_space == ColorSpace::kOklch)
           ? HueInterpolation(color1.param2_, color2.param2_, percentage,
                              hue_method.value())
           : blink::Blend(color1.param2_, color2.param2_, percentage);
@@ -456,10 +427,8 @@
           ? absl::optional<float>(absl::nullopt)
           : blink::Blend(alpha1.value(), alpha2.value(), percentage);
 
-  Color result;
-  ColorSpace result_color_space =
-      ColorInterpolationSpaceToColorSpace(interpolation_space);
-  result = FromColorSpace(result_color_space, param0, param1, param2, alpha);
+  Color result =
+      FromColorSpace(interpolation_space, param0, param1, param2, alpha);
 
   result.UnpremultiplyColor();
 
@@ -500,6 +469,9 @@
       auto [x, y, z] = gfx::OklabToXYZD65(l, a, b);
       return gfx::XYZD65ToD50(x, y, z);
     }
+    case ColorSpace::kNone:
+      NOTREACHED();
+      return std::tuple<float, float, float>();
     case ColorSpace::kHSL:
     case ColorSpace::kHWB:
       SkColor4f srgb_color = toSkColor4f();
@@ -507,15 +479,13 @@
   }
 }
 
-void Color::ConvertToColorInterpolationSpace(
-    Color::ColorInterpolationSpace interpolation_space) {
-  if (color_space_ ==
-      ColorInterpolationSpaceToColorSpace(interpolation_space)) {
+void Color::ConvertToColorSpace(Color::ColorSpace destination_color_space) {
+  if (color_space_ == destination_color_space) {
     return;
   }
 
-  switch (interpolation_space) {
-    case ColorInterpolationSpace::kXYZD65: {
+  switch (destination_color_space) {
+    case ColorSpace::kXYZD65: {
       if (color_space_ == ColorSpace::kOklab) {
         std::tie(param0_, param1_, param2_) =
             gfx::OklabToXYZD65(param0_, param1_, param2_);
@@ -526,18 +496,18 @@
       color_space_ = ColorSpace::kXYZD65;
       return;
     }
-    case ColorInterpolationSpace::kXYZD50: {
+    case ColorSpace::kXYZD50: {
       std::tie(param0_, param1_, param2_) = ExportAsXYZD50Floats();
       color_space_ = ColorSpace::kXYZD50;
       return;
     }
-    case ColorInterpolationSpace::kSRGBLinear: {
+    case ColorSpace::kSRGBLinear: {
       auto [x, y, z] = ExportAsXYZD50Floats();
       std::tie(param0_, param1_, param2_) = gfx::XYZD50TosRGBLinear(x, y, z);
       color_space_ = ColorSpace::kSRGBLinear;
       return;
     }
-    case ColorInterpolationSpace::kLab: {
+    case ColorSpace::kLab: {
       if (color_space_ == ColorSpace::kLch) {
         std::tie(param0_, param1_, param2_) =
             gfx::LchToLab(param0_, param1_, param2_);
@@ -548,11 +518,11 @@
       color_space_ = ColorSpace::kLab;
       return;
     }
-    case ColorInterpolationSpace::kOklab:
+    case ColorSpace::kOklab:
     // As per CSS Color 4 Spec, "If the host syntax does not define what color
     // space interpolation should take place in, it defaults to OKLab".
     // (https://www.w3.org/TR/css-color-4/#interpolation-space)
-    case ColorInterpolationSpace::kNone: {
+    case ColorSpace::kNone: {
       if (color_space_ == ColorSpace::kOklab) {
         return;
       }
@@ -577,7 +547,7 @@
       color_space_ = ColorSpace::kOklab;
       return;
     }
-    case ColorInterpolationSpace::kLch: {
+    case ColorSpace::kLch: {
       // Conversion to lch is done through lab.
       auto [l, a, b] = [&]() {
         if (color_space_ == ColorSpace::kLab) {
@@ -593,7 +563,7 @@
       color_space_ = ColorSpace::kLch;
       return;
     }
-    case ColorInterpolationSpace::kOklch: {
+    case ColorSpace::kOklch: {
       if (color_space_ == ColorSpace::kOklab) {
         std::tie(param0_, param1_, param2_) =
             gfx::LabToLch(param0_, param1_, param2_);
@@ -617,31 +587,38 @@
       color_space_ = ColorSpace::kOklch;
       return;
     }
-    case ColorInterpolationSpace::kSRGB:
-    case ColorInterpolationSpace::kSRGBLegacy: {
+    case ColorSpace::kSRGB:
+    case ColorSpace::kSRGBLegacy: {
       SkColor4f sRGB_color = toSkColor4f();
       param0_ = sRGB_color.fR;
       param1_ = sRGB_color.fG;
       param2_ = sRGB_color.fB;
-      color_space_ = (interpolation_space == ColorInterpolationSpace::kSRGB)
+      color_space_ = (destination_color_space == ColorSpace::kSRGB)
                          ? ColorSpace::kSRGB
                          : ColorSpace::kSRGBLegacy;
       return;
     }
-    case ColorInterpolationSpace::kHSL: {
+    case ColorSpace::kHSL: {
       SkColor4f sRGB_color = toSkColor4f();
       std::tie(param0_, param1_, param2_) =
           gfx::SRGBToHSL(sRGB_color.fR, sRGB_color.fG, sRGB_color.fB);
       color_space_ = ColorSpace::kHSL;
       return;
     }
-    case ColorInterpolationSpace::kHWB: {
+    case ColorSpace::kHWB: {
       SkColor4f sRGB_color = toSkColor4f();
       std::tie(param0_, param1_, param2_) =
           gfx::SRGBToHWB(sRGB_color.fR, sRGB_color.fG, sRGB_color.fB);
       color_space_ = ColorSpace::kHWB;
       return;
     }
+    // We do not yet interpolate in these spaces.
+    case ColorSpace::kDisplayP3:
+    case ColorSpace::kA98RGB:
+    case ColorSpace::kProPhotoRGB:
+    case ColorSpace::kRec2020:
+      NOTREACHED();
+      break;
   }
 }
 
@@ -829,6 +806,9 @@
       return "HSL";
     case Color::ColorSpace::kHWB:
       return "HWB";
+    case ColorSpace::kNone:
+      NOTREACHED();
+      return "None";
   }
 }
 
@@ -1188,59 +1168,66 @@
 // However, user agents may handle interpolation between legacy sRGB color
 // formats (hex colors, named colors, rgb(), hsl() or hwb() and the equivalent
 // alpha-including forms) in gamma-encoded sRGB space.
-Color::ColorInterpolationSpace Color::GetColorInterpolationSpace() const {
+Color::ColorSpace Color::GetColorInterpolationSpace() const {
   if (IsLegacyColor())
-    return ColorInterpolationSpace::kSRGB;
+    return ColorSpace::kSRGBLegacy;
 
-  return ColorInterpolationSpace::kOklab;
+  return ColorSpace::kOklab;
 }
 
 // static
-String Color::ColorInterpolationSpaceToString(
-    Color::ColorInterpolationSpace color_space,
+String Color::SerializeInterpolationSpace(
+    Color::ColorSpace color_space,
     Color::HueInterpolationMethod hue_interpolation_method) {
   StringBuilder result;
   switch (color_space) {
-    case Color::ColorInterpolationSpace::kLab:
+    case Color::ColorSpace::kLab:
       result.Append("lab");
       break;
-    case Color::ColorInterpolationSpace::kOklab:
+    case Color::ColorSpace::kOklab:
       result.Append("oklab");
       break;
-    case Color::ColorInterpolationSpace::kLch:
+    case Color::ColorSpace::kLch:
       result.Append("lch");
       break;
-    case Color::ColorInterpolationSpace::kOklch:
+    case Color::ColorSpace::kOklch:
       result.Append("oklch");
       break;
-    case Color::ColorInterpolationSpace::kSRGBLinear:
+    case Color::ColorSpace::kSRGBLinear:
       result.Append("srgb-linear");
       break;
-    case Color::ColorInterpolationSpace::kSRGB:
+    case Color::ColorSpace::kSRGB:
+    case Color::ColorSpace::kSRGBLegacy:
       result.Append("srgb");
       break;
-    case Color::ColorInterpolationSpace::kXYZD65:
+    case Color::ColorSpace::kXYZD65:
       result.Append("xyz-d65");
       break;
-    case Color::ColorInterpolationSpace::kXYZD50:
+    case Color::ColorSpace::kXYZD50:
       result.Append("xyz-d50");
       break;
-    case Color::ColorInterpolationSpace::kHSL:
+    case Color::ColorSpace::kHSL:
       result.Append("hsl");
       break;
-    case Color::ColorInterpolationSpace::kHWB:
+    case Color::ColorSpace::kHWB:
       result.Append("hwb");
       break;
-    case Color::ColorInterpolationSpace::kNone:
-    case Color::ColorInterpolationSpace::kSRGBLegacy:
+    case Color::ColorSpace::kNone:
       result.Append("none");
       break;
+    // These are not yet implemented as interpolation spaces.
+    case ColorSpace::kDisplayP3:
+    case ColorSpace::kA98RGB:
+    case ColorSpace::kProPhotoRGB:
+    case ColorSpace::kRec2020:
+      NOTREACHED();
+      break;
   }
 
-  if (color_space == Color::ColorInterpolationSpace::kLch ||
-      color_space == Color::ColorInterpolationSpace::kOklch ||
-      color_space == Color::ColorInterpolationSpace::kHSL ||
-      color_space == Color::ColorInterpolationSpace::kHWB) {
+  if (color_space == Color::ColorSpace::kLch ||
+      color_space == Color::ColorSpace::kOklch ||
+      color_space == Color::ColorSpace::kHSL ||
+      color_space == Color::ColorSpace::kHWB) {
     switch (hue_interpolation_method) {
       case Color::HueInterpolationMethod::kDecreasing:
         result.Append(" decreasing hue");
diff --git a/third_party/blink/renderer/platform/graphics/color.h b/third_party/blink/renderer/platform/graphics/color.h
index 9a8def1..b9e36c0 100644
--- a/third_party/blink/renderer/platform/graphics/color.h
+++ b/third_party/blink/renderer/platform/graphics/color.h
@@ -98,6 +98,8 @@
     // to 6.0, and the rest are in the rance from 0.0 to 1.0.
     // interval.
     kHWB,
+    // An uninitialized color.
+    kNone,
   };
 
   static bool IsColorFunction(ColorSpace color_space) {
@@ -193,28 +195,6 @@
                         absl::optional<float> b,
                         absl::optional<float> a);
 
-  enum class ColorInterpolationSpace : uint8_t {
-    // Linear in light intensity
-    kXYZD65,
-    kXYZD50,
-    kSRGBLinear,
-    // Perceptually uniform
-    kLab,
-    kOklab,
-    // Maximizing chroma
-    kLch,
-    kOklch,
-    // Standard RGB
-    kSRGB,
-    // Polar spaces
-    kHSL,
-    kHWB,
-    // Legacy RGB. Like kSRGB, but serialized differently.
-    kSRGBLegacy,
-    // Not specified
-    kNone,
-  };
-  ColorInterpolationSpace GetColorInterpolationSpace() const;
   enum class HueInterpolationMethod : uint8_t {
     kShorter,
     kLonger,
@@ -225,7 +205,7 @@
   // Creates a color with the Color-Mix method in CSS Color 5. This will produce
   // an interpolation between two colors, and apply an alpha multiplier if the
   // proportion was not 100% when parsing.
-  static Color FromColorMix(ColorInterpolationSpace interpolation_space,
+  static Color FromColorMix(ColorSpace interpolation_space,
                             absl::optional<HueInterpolationMethod> hue_method,
                             Color color1,
                             Color color2,
@@ -244,7 +224,7 @@
   // color1 and 1.0 returns color2. It is unbounded, so it is possible to
   // interpolate beyond these bounds with percentages outside the range [0, 1].
   static Color InterpolateColors(
-      ColorInterpolationSpace interpolation_space,
+      ColorSpace interpolation_space,
       absl::optional<HueInterpolationMethod> hue_method,
       Color color1,
       Color color2,
@@ -266,6 +246,12 @@
   // Canvas colors are serialized somewhat differently:
   // https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color
   String SerializeAsCanvasColor() const;
+  // For appending color interpolation spaces and hue interpolation methods to
+  // the serialization of gradients and color-mix functions.
+  static String SerializeInterpolationSpace(
+      Color::ColorSpace color_space,
+      Color::HueInterpolationMethod hue_interpolation_method =
+          Color::HueInterpolationMethod::kShorter);
 
   // Returns the color serialized as either #RRGGBB or #RRGGBBAA. The latter
   // format is not a valid CSS color, and should only be seen in DRT dumps.
@@ -347,20 +333,19 @@
   inline bool operator!=(const Color& other) const { return !(*this == other); }
 
   unsigned GetHash() const;
+  // Returns true if the color is of a type that predates CSS Color 4. Includes
+  // rgb(), rgba(), hex color, named color, hsl() and hwb() types. These colors
+  // are always assumed to be in the sRGB color space and interpolate and
+  // serialize differently from other color types.
   bool IsLegacyColor() const;
 
-  // For appending color interpolation spaces to the serialization of gradients
-  // and color-mix functions.
-  static String ColorInterpolationSpaceToString(
-      Color::ColorInterpolationSpace color_space,
-      Color::HueInterpolationMethod hue_interpolation_method =
-          Color::HueInterpolationMethod::kShorter);
+  // What colorspace space a color wants to interpolate in. This is not
+  // equivalent to the colorspace of the color itself.
+  // https://www.w3.org/TR/css-color-4/#interpolation
+  Color::ColorSpace GetColorInterpolationSpace() const;
 
   ColorSpace GetColorSpace() const { return color_space_; }
-  static ColorSpace ColorInterpolationSpaceToColorSpace(
-      Color::ColorInterpolationSpace color_interpolation_space);
-  void ConvertToColorInterpolationSpace(
-      ColorInterpolationSpace interpolation_space);
+  void ConvertToColorSpace(ColorSpace interpolation_space);
 
   FRIEND_TEST_ALL_PREFIXES(BlinkColor, ColorMixNone);
   FRIEND_TEST_ALL_PREFIXES(BlinkColor, ColorInterpolation);
diff --git a/third_party/blink/renderer/platform/graphics/color_test.cc b/third_party/blink/renderer/platform/graphics/color_test.cc
index 938c5a9..6837c51 100644
--- a/third_party/blink/renderer/platform/graphics/color_test.cc
+++ b/third_party/blink/renderer/platform/graphics/color_test.cc
@@ -42,7 +42,7 @@
 
 // Helper struct for testing purposes.
 struct ColorMixTest {
-  Color::ColorInterpolationSpace mix_space;
+  Color::ColorSpace mix_space;
   absl::optional<Color::HueInterpolationMethod> hue_method;
   Color color_left;
   Color color_right;
@@ -60,25 +60,25 @@
 
 TEST(BlinkColor, ColorMixSameColorSpace) {
   ColorMixTest color_mix_tests[] = {
-      {Color::ColorInterpolationSpace::kSRGB, absl::nullopt,
+      {Color::ColorSpace::kSRGB, absl::nullopt,
        CreateSRGBColor(1.0f, 0.0f, 0.0f, 1.0f),
        CreateSRGBColor(0.0f, 1.0f, 0.0f, 1.0f),
        /*percentage =*/0.5f, /*alpha_multiplier=*/1.0f,
        CreateSRGBColor(0.5f, 0.5f, 0.0f, 1.0f)},
-      {Color::ColorInterpolationSpace::kSRGB, absl::nullopt,
+      {Color::ColorSpace::kSRGB, absl::nullopt,
        Color::FromColorSpace(Color::ColorSpace::kRec2020, 0.7919771358198009f,
                              0.23097568481079767f, 0.07376147493817597f, 1.0f),
        Color::FromColorSpace(Color::ColorSpace::kLab, 87.81853633115202f,
                              -79.27108223854806f, 80.99459785152247f, 1.0f),
        /*percentage =*/0.5f, /*alpha_multiplier=*/1.0f,
        CreateSRGBColor(0.5f, 0.5f, 0.0f, 1.0f)},
-      {Color::ColorInterpolationSpace::kSRGB, absl::nullopt,
+      {Color::ColorSpace::kSRGB, absl::nullopt,
        CreateSRGBColor(1.0f, 0.0f, 0.0f, 1.0f),
        CreateSRGBColor(0.0f, 1.0f, 0.0f, 1.0f),
        /*percentage =*/0.25f, /*alpha_multiplier=*/0.5f,
        CreateSRGBColor(0.75f, 0.25f, 0.0f, 0.5f)},
       // Value obtained form the spec https://www.w3.org/TR/css-color-5/.
-      {Color::ColorInterpolationSpace::kSRGB, absl::nullopt,
+      {Color::ColorSpace::kSRGB, absl::nullopt,
        CreateSRGBColor(1.0f, 0.0f, 0.0f, 0.7f),
        CreateSRGBColor(0.0f, 1.0f, 0.0f, 0.2f),
        /*percentage =*/0.75f, /*alpha_multiplier=*/1.0f,
@@ -88,9 +88,7 @@
         color_mix_test.mix_space, color_mix_test.hue_method,
         color_mix_test.color_left, color_mix_test.color_right,
         color_mix_test.percentage_right, color_mix_test.alpha_multiplier);
-    EXPECT_EQ(
-        result.GetColorSpace(),
-        Color::ColorInterpolationSpaceToColorSpace(color_mix_test.mix_space));
+    EXPECT_EQ(result.GetColorSpace(), color_mix_test.mix_space);
     SkColor4f resultSkColor = result.toSkColor4f();
     SkColor4f expectedSkColor = color_mix_test.color_expected.toSkColor4f();
     EXPECT_NEAR(resultSkColor.fR, expectedSkColor.fR, 0.001f)
@@ -159,8 +157,8 @@
       Color::ColorSpace::kXYZD50, absl::nullopt, absl::nullopt, 0.7f, 1.0f);
 
   Color result = Color::FromColorMix(
-      Color::ColorInterpolationSpace::kXYZD50, /*hue_method=*/absl::nullopt,
-      color1, color2, /*percentage=*/0.5f, /*alpha_multiplier=*/1.0f);
+      Color::ColorSpace::kXYZD50, /*hue_method=*/absl::nullopt, color1, color2,
+      /*percentage=*/0.5f, /*alpha_multiplier=*/1.0f);
 
   EXPECT_EQ(result.param0_is_none_, true);
   EXPECT_EQ(result.param1_is_none_, false);
@@ -173,7 +171,7 @@
   struct ColorsTest {
     Color color1;
     Color color2;
-    Color::ColorInterpolationSpace space;
+    Color::ColorSpace space;
     absl::optional<Color::HueInterpolationMethod> hue_method;
     float percentage;
     Color expected;
@@ -186,41 +184,40 @@
                              0.98f, 1.0f),
        Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.62f, 0.26f, 0.64f,
                              1.0f),
-       Color::ColorInterpolationSpace::kSRGB, absl::nullopt, 0.5f,
+       Color::ColorSpace::kSRGB, absl::nullopt, 0.5f,
        Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.62f, 0.19f, 0.81f,
                              1.0f)},
       {Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.5f, absl::nullopt,
                              1.0f, 1.0f),
        Color::FromColorSpace(Color::ColorSpace::kSRGB, 1.0f, 0.5f, 0.0f, 1.0f),
-       Color::ColorInterpolationSpace::kSRGB, absl::nullopt, 0.5f,
+       Color::ColorSpace::kSRGB, absl::nullopt, 0.5f,
        Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.75f, 0.5f, 0.5f,
                              1.0f)},
       {Color::FromColorSpace(Color::ColorSpace::kSRGB, .5f, 0.0f, 0.0f,
                              absl::nullopt),
        Color::FromColorSpace(Color::ColorSpace::kSRGB, 1.f, 0.5f, 1.0f, 1.0f),
-       Color::ColorInterpolationSpace::kSRGB, absl::nullopt, 0.5f,
+       Color::ColorSpace::kSRGB, absl::nullopt, 0.5f,
        Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.75f, 0.25f, 0.5f,
                              1.0f)},
       {Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.24f, 0.12f, 0.98f,
                              0.4f),
        Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.62f, 0.26f, 0.64f,
                              0.6f),
-       Color::ColorInterpolationSpace::kSRGB, absl::nullopt, 0.5f,
+       Color::ColorSpace::kSRGB, absl::nullopt, 0.5f,
        Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.468f, 0.204f, 0.776f,
                              0.5f)},
       {Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.76f, 0.62f, 0.03f,
                              0.4f),
        Color::FromColorSpace(Color::ColorSpace::kDisplayP3, 0.84f, 0.19f, 0.72f,
                              0.6f),
-       Color::ColorInterpolationSpace::kLab, absl::nullopt, 0.5f,
+       Color::ColorSpace::kLab, absl::nullopt, 0.5f,
        Color::FromColorSpace(Color::ColorSpace::kLab, 58.873f, 51.552f, 7.108f,
                              0.5f)},
       {Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.76f, 0.62f, 0.03f,
                              0.4f),
        Color::FromColorSpace(Color::ColorSpace::kDisplayP3, 0.84f, 0.19f, 0.72f,
                              0.6f),
-       Color::ColorInterpolationSpace::kLch,
-       Color::HueInterpolationMethod::kShorter, 0.5f,
+       Color::ColorSpace::kLch, Color::HueInterpolationMethod::kShorter, 0.5f,
        // There is an issue with the spec where the hue is un-premultiplied even
        // though it shouldn't be.
        Color::FromColorSpace(Color::ColorSpace::kLch, 58.873f, 81.126f, 31.82f,
@@ -426,19 +423,13 @@
       {Color::ColorSpace::kHSL, 4.0f, 0.5f, 0.0f},
       {Color::ColorSpace::kHWB, 4.0f, 0.5f, 0.0f}};
 
-  Color::ColorInterpolationSpace color_interpolation_space[] = {
-      Color::ColorInterpolationSpace::kXYZD65,
-      Color::ColorInterpolationSpace::kXYZD50,
-      Color::ColorInterpolationSpace::kSRGBLinear,
-      Color::ColorInterpolationSpace::kLab,
-      Color::ColorInterpolationSpace::kOklab,
-      Color::ColorInterpolationSpace::kLch,
-      Color::ColorInterpolationSpace::kOklch,
-      Color::ColorInterpolationSpace::kSRGB,
-      Color::ColorInterpolationSpace::kSRGBLegacy,
-      Color::ColorInterpolationSpace::kHSL,
-      Color::ColorInterpolationSpace::kHWB,
-      Color::ColorInterpolationSpace::kNone};
+  Color::ColorSpace color_interpolation_space[] = {
+      Color::ColorSpace::kXYZD65,     Color::ColorSpace::kXYZD50,
+      Color::ColorSpace::kSRGBLinear, Color::ColorSpace::kLab,
+      Color::ColorSpace::kOklab,      Color::ColorSpace::kLch,
+      Color::ColorSpace::kOklch,      Color::ColorSpace::kSRGB,
+      Color::ColorSpace::kSRGBLegacy, Color::ColorSpace::kHSL,
+      Color::ColorSpace::kHWB,        Color::ColorSpace::kNone};
 
   for (auto& space : color_interpolation_space) {
     for (auto& color_function_value : color_function_values) {
@@ -453,37 +444,32 @@
           color_function_value.param1, color_function_value.param2, 1.0f);
 
       SkColor4f expected_output = input.toSkColor4f();
-      input.ConvertToColorInterpolationSpace(space);
+      input.ConvertToColorSpace(space);
       SkColor4f output = input.toSkColor4f();
 
       EXPECT_NEAR(expected_output.fR, output.fR, 0.01f)
           << "Converting from "
           << Color::ColorSpaceToString(color_function_value.color_space)
-          << " to " << Color::ColorInterpolationSpaceToString(space);
+          << " to " << Color::ColorSpaceToString(space);
       EXPECT_NEAR(expected_output.fG, output.fG, 0.01f)
           << "Converting from "
           << Color::ColorSpaceToString(color_function_value.color_space)
-          << " to " << Color::ColorInterpolationSpaceToString(space);
+          << " to " << Color::ColorSpaceToString(space);
       EXPECT_NEAR(expected_output.fB, output.fB, 0.01f)
           << "Converting from "
           << Color::ColorSpaceToString(color_function_value.color_space)
-          << " to " << Color::ColorInterpolationSpaceToString(space);
+          << " to " << Color::ColorSpaceToString(space);
     }
   }
 }
 
 TEST(BlinkColor, ExportAsXYZD50Floats) {
-  Color::ColorInterpolationSpace color_spaces[] = {
-      Color::ColorInterpolationSpace::kXYZD65,
-      Color::ColorInterpolationSpace::kXYZD50,
-      Color::ColorInterpolationSpace::kSRGBLinear,
-      Color::ColorInterpolationSpace::kLab,
-      Color::ColorInterpolationSpace::kOklab,
-      Color::ColorInterpolationSpace::kLch,
-      Color::ColorInterpolationSpace::kOklch,
-      Color::ColorInterpolationSpace::kSRGB,
-      Color::ColorInterpolationSpace::kHSL,
-      Color::ColorInterpolationSpace::kHWB};
+  Color::ColorSpace color_spaces[] = {
+      Color::ColorSpace::kXYZD65,     Color::ColorSpace::kXYZD50,
+      Color::ColorSpace::kSRGBLinear, Color::ColorSpace::kLab,
+      Color::ColorSpace::kOklab,      Color::ColorSpace::kLch,
+      Color::ColorSpace::kOklch,      Color::ColorSpace::kSRGB,
+      Color::ColorSpace::kHSL,        Color::ColorSpace::kHWB};
 
   struct FloatValues {
     float x;
@@ -505,18 +491,15 @@
       Color input = Color::FromColorSpace(
           Color::ColorSpace::kXYZD50, input_parameter.x, input_parameter.y,
           input_parameter.z, 1.0f);
-      input.ConvertToColorInterpolationSpace(space);
+      input.ConvertToColorSpace(space);
       auto [x, y, z] = input.ExportAsXYZD50Floats();
 
       EXPECT_NEAR(x, expected.param0_, 0.01f)
-          << "Converting through "
-          << Color::ColorInterpolationSpaceToString(space);
+          << "Converting through " << Color::ColorSpaceToString(space);
       EXPECT_NEAR(y, expected.param1_, 0.01f)
-          << "Converting through "
-          << Color::ColorInterpolationSpaceToString(space);
+          << "Converting through " << Color::ColorSpaceToString(space);
       EXPECT_NEAR(z, expected.param2_, 0.01f)
-          << "Converting through "
-          << Color::ColorInterpolationSpaceToString(space);
+          << "Converting through " << Color::ColorSpaceToString(space);
     }
   }
 }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
index cd0dc61..3cea2f1 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -563,15 +563,16 @@
     return;
   }
 
-  const ScrollPaintPropertyNode* parent_scroll_node = scroll_node.Parent();
-  // Look for the ScrollTranslation node corresponding to its parent scroll
-  // node.
-  const auto* parent_scroll_translation =
-      GetScrollTranslationNodeForParent(scroll_node, scroll_translation_node);
+  if (const auto* parent_scroll_translation = GetScrollTranslationNodeForParent(
+          scroll_node, scroll_translation_node)) {
+    // TODO(awogbemila): Figure out in exactly which cases
+    // GetScrollTranslationNodeForParent returns NULL.
+    const ScrollPaintPropertyNode* parent_scroll_node =
+        scroll_node.Parent();
 
-  DCHECK(parent_scroll_translation);
-  DCHECK_EQ(parent_scroll_node, parent_scroll_translation->ScrollNode());
-  EnsureCompositorScrollNode(*parent_scroll_node, *parent_scroll_translation);
+    DCHECK_EQ(parent_scroll_node, parent_scroll_translation->ScrollNode());
+    EnsureCompositorScrollNode(*parent_scroll_node, *parent_scroll_translation);
+  }
 
   int parent_id = scroll_node.Parent()->CcNodeId(new_sequence_number_);
   // Compositor transform nodes up to scroll_offset_translation must exist.
diff --git a/third_party/blink/renderer/platform/graphics/gradient.cc b/third_party/blink/renderer/platform/graphics/gradient.cc
index 0f51048..2c12920b 100644
--- a/third_party/blink/renderer/platform/graphics/gradient.cc
+++ b/third_party/blink/renderer/platform/graphics/gradient.cc
@@ -144,34 +144,34 @@
   SkGradientShader::Interpolation sk_interpolation;
 
   switch (color_space_interpolation_space_) {
-    case Color::ColorInterpolationSpace::kXYZD65:
-    case Color::ColorInterpolationSpace::kXYZD50:
-    case Color::ColorInterpolationSpace::kSRGBLinear:
+    case Color::ColorSpace::kXYZD65:
+    case Color::ColorSpace::kXYZD50:
+    case Color::ColorSpace::kSRGBLinear:
       sk_interpolation.fColorSpace = sk_colorspace::kSRGBLinear;
       break;
-    case Color::ColorInterpolationSpace::kLab:
+    case Color::ColorSpace::kLab:
       sk_interpolation.fColorSpace = sk_colorspace::kLab;
       break;
-    case Color::ColorInterpolationSpace::kOklab:
+    case Color::ColorSpace::kOklab:
       sk_interpolation.fColorSpace = sk_colorspace::kOKLab;
       break;
-    case Color::ColorInterpolationSpace::kLch:
+    case Color::ColorSpace::kLch:
       sk_interpolation.fColorSpace = sk_colorspace::kLCH;
       break;
-    case Color::ColorInterpolationSpace::kOklch:
+    case Color::ColorSpace::kOklch:
       sk_interpolation.fColorSpace = sk_colorspace::kOKLCH;
       break;
-    case Color::ColorInterpolationSpace::kSRGB:
-    case Color::ColorInterpolationSpace::kSRGBLegacy:
+    case Color::ColorSpace::kSRGB:
+    case Color::ColorSpace::kSRGBLegacy:
       sk_interpolation.fColorSpace = sk_colorspace::kSRGB;
       break;
-    case Color::ColorInterpolationSpace::kHSL:
+    case Color::ColorSpace::kHSL:
       sk_interpolation.fColorSpace = sk_colorspace::kHSL;
       break;
-    case Color::ColorInterpolationSpace::kHWB:
+    case Color::ColorSpace::kHWB:
       sk_interpolation.fColorSpace = sk_colorspace::kHWB;
       break;
-    case Color::ColorInterpolationSpace::kNone:
+    case Color::ColorSpace::kNone:
       if (HasNonLegacyColor()) {
         // If no colorspace is provided and the gradient is not entirely
         // composed of legacy colors, Oklab is the default interpolation space.
@@ -180,6 +180,14 @@
         // TODO(crbug.com/1379462): This should be kSRGB.
         sk_interpolation.fColorSpace = sk_colorspace::kDestination;
       }
+      break;
+    // We do not yet support interpolation in these spaces.
+    case Color::ColorSpace::kDisplayP3:
+    case Color::ColorSpace::kA98RGB:
+    case Color::ColorSpace::kProPhotoRGB:
+    case Color::ColorSpace::kRec2020:
+      NOTREACHED();
+      break;
   }
 
   switch (hue_interpolation_method_) {
diff --git a/third_party/blink/renderer/platform/graphics/gradient.h b/third_party/blink/renderer/platform/graphics/gradient.h
index 05e00d6..a88a150 100644
--- a/third_party/blink/renderer/platform/graphics/gradient.h
+++ b/third_party/blink/renderer/platform/graphics/gradient.h
@@ -117,7 +117,7 @@
                     const SkMatrix& local_matrix,
                     const ImageDrawOptions& draw_options);
   void SetColorInterpolationSpace(
-      Color::ColorInterpolationSpace color_space_interpolation_space,
+      Color::ColorSpace color_space_interpolation_space,
       Color::HueInterpolationMethod hue_interpolation_method) {
     color_space_interpolation_space_ = color_space_interpolation_space;
     hue_interpolation_method_ = hue_interpolation_method;
@@ -162,8 +162,7 @@
   mutable sk_sp<PaintShader> cached_shader_;
   mutable sk_sp<SkColorFilter> color_filter_;
 
-  Color::ColorInterpolationSpace color_space_interpolation_space_ =
-      Color::ColorInterpolationSpace::kNone;
+  Color::ColorSpace color_space_interpolation_space_ = Color::ColorSpace::kNone;
   Color::HueInterpolationMethod hue_interpolation_method_ =
       Color::HueInterpolationMethod::kShorter;
 };
diff --git a/third_party/blink/renderer/platform/graphics/image_frame_generator.cc b/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
index 7c2a5e7c..8a32b092 100644
--- a/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
+++ b/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
@@ -273,7 +273,7 @@
   if (yuv_decoding_failed_)
     return false;
   std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
-      data, true /* data_complete */, ImageDecoder::kAlphaPremultiplied,
+      data, /*data_complete=*/true, ImageDecoder::kAlphaPremultiplied,
       ImageDecoder::kDefaultBitDepth, decoder_color_behavior_);
   DCHECK(decoder);
 
diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
index 5d7ae49..f24e795 100644
--- a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
+++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
@@ -860,7 +860,9 @@
   static_assert(AVIF_PIXEL_FORMAT_YUV422 == AVIF_PIXEL_FORMAT_YUV444 + 1);
   static_assert(AVIF_PIXEL_FORMAT_YUV420 == AVIF_PIXEL_FORMAT_YUV422 + 1);
   static_assert(AVIF_PIXEL_FORMAT_YUV400 == AVIF_PIXEL_FORMAT_YUV420 + 1);
-  // Assert that container->yuvFormat is one of the four YUV formats in AV1.
+  // Assert that after avifDecoderParse() returns AVIF_RESULT_OK,
+  // decoder_->image->yuvFormat (the same as container->yuvFormat) is one of the
+  // four YUV formats in AV1.
   CHECK(container->yuvFormat >= AVIF_PIXEL_FORMAT_YUV444 &&
         container->yuvFormat <= AVIF_PIXEL_FORMAT_YUV400)
       << "Invalid YUV format: " << container->yuvFormat;
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h b/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h
index 61cb8f3..f072541 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h
@@ -83,7 +83,7 @@
       bool is_remote_description_or_rollback) = 0;
   virtual void DidModifySctpTransport(WebRTCSctpTransportSnapshot) = 0;
   virtual void DidAddRemoteDataChannel(
-      scoped_refptr<webrtc::DataChannelInterface>) = 0;
+      rtc::scoped_refptr<webrtc::DataChannelInterface>) = 0;
   virtual void DidNoteInterestingUsage(int usage_pattern) = 0;
   virtual void UnregisterPeerConnectionHandler() = 0;
   virtual void ClosePeerConnection();
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index d66abc1..8157274 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1161,7 +1161,6 @@
     {
       name: "CSSWhiteSpaceShorthand",
       depends_on: ["CSSTextWrap"],
-      status: "test",
     },
     {
       name: "Database",
@@ -1402,10 +1401,6 @@
       status: "stable",
     },
     {
-      name: "ElementSuperRareData",
-      status: "stable",
-    },
-    {
       // Experiment with preventing some instances of mutation XSS
       // by escaping "<" and ">" in attribute values.
       // See: crbug.com/1175016
diff --git a/third_party/blink/tools/blinkpy/common/net/results_fetcher.py b/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
index ccb961be..3b3c191 100644
--- a/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
+++ b/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
@@ -88,7 +88,8 @@
     def gather_results(self,
                        build: Build,
                        step_name: str,
-                       exclude_exonerated: bool = True) -> WebTestResults:
+                       exclude_exonerated: bool = True,
+                       only_unexpected: bool = True) -> WebTestResults:
         """Gather all web test results on a given build step from ResultDB."""
         assert build.build_id, '%s must set a build ID' % build
         suite = step_name
@@ -96,7 +97,11 @@
             suite = suite[:-len('(with patch)')].strip()
 
         test_result_predicate = {
-            'expectancy': 'VARIANTS_WITH_ONLY_UNEXPECTED_RESULTS',
+            # TODO(crbug.com/1428727): Using `read_mask` with
+            # `VARIANTS_WITH_ONLY_UNEXPECTED_RESULTS` throws an internal server
+            # error. Use `VARIANTS_WITH_UNEXPECTED_RESULTS` for now and filter
+            # results client-side.
+            'expectancy': 'VARIANTS_WITH_UNEXPECTED_RESULTS',
             'excludeExonerated': exclude_exonerated,
             'variant': {
                 'contains': {
@@ -106,19 +111,28 @@
                 },
             },
         }
+        read_mask = ['name', 'testId', 'tags', 'status', 'expected']
         test_results = self._resultdb_client.query_test_results(
-            [build.build_id], test_result_predicate)
+            [build.build_id], test_result_predicate, read_mask)
         test_results_by_name = self._group_test_results_by_test_name(
             test_results)
+        # TODO(crbug.com/1428727): Once the bug is fixed, use `expectancy` to
+        # filter results server-side instead.
+        if only_unexpected:
+            test_results_by_name = {
+                test: raw_results
+                for test, raw_results in test_results_by_name.items()
+                if not any(result.get('expected') for result in raw_results)
+            }
         artifacts = self._resultdb_client.query_artifacts(
             [build.build_id], {
                 'testResultPredicate': test_result_predicate,
                 'artifactIdRegexp': 'actual_.*'
             })
-        artifacts_by_name = self._group_artifacts_by_test_name(artifacts)
+        artifacts_by_run = self._group_artifacts_by_test_run(artifacts)
         return WebTestResults.from_rdb_responses(
             test_results_by_name,
-            artifacts_by_name,
+            artifacts_by_run,
             step_name=step_name,
             builder_name=build.builder_name)
 
@@ -132,20 +146,16 @@
             test_results_by_name[test_id_match['name']].append(test_result)
         return test_results_by_name
 
-    def _group_artifacts_by_test_name(self, artifacts):
-        artifact_name_pattern = re.compile(
-            r'invocations/[^/\s]+/tests/(?P<test_id>[^/\s]+)')
-        artifacts_by_name = collections.defaultdict(list)
+    def _group_artifacts_by_test_run(self, artifacts):
+        test_run_pattern = re.compile(
+            r'invocations/[^/\s]+/tests/[^/\s]+/results/[^/\s]+')
+        artifacts_by_run = collections.defaultdict(list)
         for artifact in artifacts:
-            artifact_name_match = artifact_name_pattern.match(artifact['name'])
-            if not artifact_name_match:
+            test_run_match = test_run_pattern.match(artifact['name'])
+            if not test_run_match:
                 continue
-            test_id = urllib.parse.unquote(artifact_name_match['test_id'])
-            test_id_match = self._test_id_pattern.fullmatch(test_id)
-            if not test_id_match:
-                continue
-            artifacts_by_name[test_id_match['name']].append(artifact)
-        return artifacts_by_name
+            artifacts_by_run[test_run_match[0]].append(artifact)
+        return artifacts_by_run
 
     def get_full_builder_url(self, url_base, builder_name):
         """ Returns the url for a builder directory in google storage.
diff --git a/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py b/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
index 0021b02..ab6ede4d 100644
--- a/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
+++ b/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
@@ -188,6 +188,10 @@
                 'ninja://:blink_web_tests/should-pass.html',
                 'status':
                 'FAIL',
+                'tags': [{
+                    'key': 'web_tests_actual_image_hash',
+                    'value': '3f765a7',
+                }],
             }, {
                 'name':
                 ('invocations/task-chromium-swarm.appspot.com-6139bb/'
@@ -218,23 +222,25 @@
                 ('invocations/task-chromium-swarm.appspot.com-6139bb/'
                  'tests/ninja:%2F%2F:blink_web_tests%2Fshould-pass.html/'
                  'results/033e-aaaa/'
-                 'artifacts/actual_text'),
+                 'artifacts/actual_image'),
                 'artifactId':
-                'actual_text',
+                'actual_image',
                 'fetchUrl':
-                'https://results.usercontent.cr.dev/actual_text',
+                'https://results.usercontent.cr.dev/actual_image',
             }],
         })
         results = self.fetcher.gather_results(Build('linux-rel', 9000, '1234'),
-                                              'blink_web_tests (with patch)')
+                                              'blink_web_tests (with patch)',
+                                              True, False)
 
         result = results.result_for_test('should-pass.html')
         self.assertEqual(result.actual_results(), ['FAIL', 'PASS'])
         self.assertFalse(result.did_run_as_expected())
         self.assertEqual(
             result.baselines_by_suffix(), {
-                'txt': [
-                    Artifact('https://results.usercontent.cr.dev/actual_text'),
+                'png': [
+                    Artifact('https://results.usercontent.cr.dev/actual_image',
+                             '3f765a7'),
                 ],
             })
 
diff --git a/third_party/blink/tools/blinkpy/common/net/rpc.py b/third_party/blink/tools/blinkpy/common/net/rpc.py
index b39d9cd..b03b113c 100644
--- a/third_party/blink/tools/blinkpy/common/net/rpc.py
+++ b/third_party/blink/tools/blinkpy/common/net/rpc.py
@@ -29,7 +29,7 @@
 import functools
 import logging
 import json
-from typing import Literal, NamedTuple, Optional
+from typing import List, Literal, NamedTuple, Optional
 from urllib.parse import urlunsplit
 
 import six
@@ -172,9 +172,7 @@
             https://source.chromium.org/chromium/infra/infra/+/master:go/src/go.chromium.org/luci/resultdb/proto/v1/resultdb.proto
         """
         entities = []
-        # Using 1e5 instead of 1000 max to reduce the rpc number
-        # Check https://source.chromium.org/chromium/infra/infra/+/master:go/src/go.chromium.org/luci/resultdb/internal/pagination/pagination.go
-        data['pageSize'] = count if count > 0 else 1e5
+        data['pageSize'] = count if count > 0 else 1000
         while data.get('pageToken', True) and (count == 0
                                                or count - len(entities) > 0):
             response = self._luci_rpc(method, data)
@@ -296,11 +294,17 @@
     def _get_invocations(self, build_ids):
         return ['invocations/build-%s' % build_id for build_id in build_ids]
 
-    def query_test_results(self, build_ids, predicate, count=0):
+    def query_test_results(self,
+                           build_ids,
+                           predicate,
+                           read_mask: Optional[List[str]] = None,
+                           count=0):
         request = {
             'invocations': self._get_invocations(build_ids),
             'predicate': predicate,
         }
+        if read_mask:
+            request['readMask'] = ','.join(read_mask)
         return self._luci_rpc_paginated('QueryTestResults',
                                         request,
                                         'testResults',
diff --git a/third_party/blink/tools/blinkpy/common/net/web_test_results.py b/third_party/blink/tools/blinkpy/common/net/web_test_results.py
index 6959dd3..9d3f6179 100644
--- a/third_party/blink/tools/blinkpy/common/net/web_test_results.py
+++ b/third_party/blink/tools/blinkpy/common/net/web_test_results.py
@@ -32,6 +32,7 @@
 
 from blinkpy.common.memoized import memoized
 from blinkpy.web_tests.layout_package import json_results_generator
+from blinkpy.web_tests.models.test_failures import FailureImage
 from blinkpy.web_tests.models.typ_types import ResultType
 
 
@@ -41,25 +42,27 @@
 
 
 class WebTestResult:
-    def __init__(self, test_name, result_dict):
+    def __init__(self, test_name, result_dict,
+                 artifacts: Dict[str, List[Artifact]]):
         self._test_name = test_name
         self._result_dict = result_dict
+        self._artifacts = artifacts
 
     def __repr__(self):
         return "WebTestResult(test_name=%s, result_dict=%s)" % \
             (repr(self._test_name), repr(self._result_dict))
 
     def baselines_by_suffix(self) -> Dict[str, List[Artifact]]:
-        artifacts = self._result_dict.get('artifacts', {})
-        baselines = collections.defaultdict(list)
+        baselines = {}
         # Add extensions for mismatches.
         for artifact_name, suffix in [
             ('actual_text', 'txt'),
             ('actual_image', 'png'),
             ('actual_audio', 'wav'),
         ]:
-            for url in artifacts.get(artifact_name, []):
-                baselines[suffix].append(Artifact(url))
+            artifacts = self._artifacts.get(artifact_name)
+            if artifacts:
+                baselines[suffix] = artifacts
         return baselines
 
     def test_name(self):
@@ -100,10 +103,9 @@
         baseline, including an implicit all-PASS testharness baseline (i.e. a
         previously all-PASS testharness test starts to fail)."""
         actual_results = self.actual_results()
-        artifact_names = self._result_dict.get('artifacts', {}).keys()
         return ('FAIL' in actual_results and any(
             artifact_name.startswith('actual')
-            for artifact_name in artifact_names))
+            for artifact_name in self._artifacts))
 
     def is_missing_baseline(self):
         return (self.is_missing_image() or self.is_missing_text()
@@ -143,10 +145,15 @@
     @classmethod
     def from_json(cls, json_dict, **kwargs) -> 'WebTestResults':
         sep = json_dict.get('sep', '/')
-        results = [
-            WebTestResult(test_name, fields) for test_name, fields in
-            _flatten_test_results_trie(json_dict['tests'], sep=sep)
-        ]
+        results = []
+        for test_name, fields in _flatten_test_results_trie(json_dict['tests'],
+                                                            sep=sep):
+            artifacts = {
+                artifact_name: [Artifact(path) for path in paths]
+                for artifact_name, paths in fields.get('artifacts',
+                                                       {}).items()
+            }
+            results.append(WebTestResult(test_name, fields, artifacts))
         kwargs.setdefault('interrupted', json_dict.get('interrupted', False))
         kwargs.setdefault('builder_name', json_dict.get('builder_name'))
         kwargs.setdefault('chromium_revision',
@@ -156,11 +163,11 @@
     @classmethod
     def from_rdb_responses(cls,
                            test_results_by_name,
-                           artifacts_by_name=None,
+                           artifacts_by_run=None,
                            **kwargs):
         """Creates a WebTestResults object from raw ResultDB RPC response data.
         """
-        artifacts_by_name = artifacts_by_name or collections.defaultdict(list)
+        artifacts_by_run = artifacts_by_run or collections.defaultdict(list)
         results = []
         for test_name, raw_results in test_results_by_name.items():
             actual = ' '.join(
@@ -168,15 +175,9 @@
                 for raw_result in raw_results)
             is_unexpected = any(not raw_result.get('expected')
                                 for raw_result in raw_results)
-            artifacts = collections.defaultdict(list)
-            for artifact in artifacts_by_name[test_name]:
-                artifacts[artifact['artifactId']].append(artifact['fetchUrl'])
-            trie_leaf = {
-                'actual': actual,
-                'is_unexpected': is_unexpected,
-                'artifacts': dict(artifacts),
-            }
-            results.append(WebTestResult(test_name, trie_leaf))
+            trie_leaf = {'actual': actual, 'is_unexpected': is_unexpected}
+            artifacts = _make_artifacts(raw_results, artifacts_by_run)
+            results.append(WebTestResult(test_name, trie_leaf, artifacts))
         return cls(results, **kwargs)
 
     _rdb_to_web_test_statuses = {
@@ -228,3 +229,25 @@
             result for result in self._results_by_name.values()
             if not result.did_run_as_expected()
         ]
+
+
+def _make_artifacts(raw_results, artifacts_by_run):
+    artifacts = collections.defaultdict(list)
+    for raw_result in raw_results:
+        test_run = raw_result.get('name')
+        if not test_run:
+            continue
+        for raw_artifact in artifacts_by_run.get(test_run, []):
+            artifact_id, digest = raw_artifact['artifactId'], None
+            if artifact_id == 'actual_image':
+                digest = _image_hash(raw_result)
+            artifacts[artifact_id].append(
+                Artifact(raw_artifact['fetchUrl'], digest))
+    return dict(artifacts)
+
+
+def _image_hash(raw_result) -> Optional[str]:
+    for tag in raw_result.get('tags', []):
+        if tag['key'] == FailureImage.ACTUAL_HASH_RDB_TAG:
+            return tag['value']
+    return None
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index 6e50094..934066f 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -704,6 +704,7 @@
             'ui::IsContainerWithSelectableChildren',
             'ui::IsDialog',
             'ui::IsHeading',
+            'ui::IsPlainContentElement',
             'ui::IsLandmark',
             'ui::IsPlatformDocument',
             'ui::IsPresentational',
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 836266ed..e6396e2bd 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
@@ -716,6 +716,8 @@
                 break
 
         assert expected_output
+        # TODO(crbug.com/1396136): Update the test_type to use a string array.
+        test_output.test_type = 'image'
 
         # Combine compare_text_result and test_result
         expected_output.text = expected_text_output.text
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c45ebf2..a8da64f 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1382,6 +1382,11 @@
 crbug.com/1219041 external/wpt/css/css-text/white-space/text-space-collapse-discard-001.xht [ Failure ]
 crbug.com/1219041 external/wpt/css/css-text/white-space/text-space-trim-trim-inner-001.xht [ Failure ]
 
+# Turning `white-space` to a shorthand, can be enabled by `CSSWhiteSpaceShorthand`.
+crbug.com/1417543 external/wpt/css/css-text/parsing/white-space-collapse-computed.html [ Failure ]
+crbug.com/1417543 external/wpt/css/css-text/parsing/white-space-collapse-valid.html [ Failure ]
+crbug.com/1417543 external/wpt/css/css-text/parsing/white-space-shorthand.html [ Failure ]
+
 # LayoutNG ref-tests that need to be updated (cannot be rebaselined).
 crbug.com/591099 [ Win ] virtual/text-antialias/ellipsis-with-self-painting-layer.html [ Failure ]
 crbug.com/1098801 virtual/text-antialias/whitespace/whitespace-in-pre.html [ Failure ]
@@ -2901,6 +2906,9 @@
 crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux ] virtual/keepalive-in-browser-migration/external/wpt/fetch/api/response/response-clone.any.serviceworker.html [ Timeout ]
+crbug.com/626703 [ Mac12 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/api/response/response-clone.any.serviceworker.html [ Timeout ]
+crbug.com/626703 [ Mac13 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/api/response/response-clone.any.serviceworker.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-transitions/transition-events-with-document-change.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-animations/animation-canceled-by-parent-details-element-being-closed.html [ Timeout ]
 crbug.com/626703 virtual/threaded/external/wpt/css/css-animations/animation-canceled-by-parent-details-element-being-closed.html [ Timeout ]
@@ -6578,7 +6586,6 @@
 
 # Flaky (sheriff 2022-12-15)
 crbug.com/1186788 [ Mac ] external/wpt/pointerevents/pointerevent_pointercapture_in_frame.html?pen [ Failure Pass Timeout ]
-crbug.com/1401318 [ Mac ] external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html [ Failure Pass Timeout ]
 
 # TODO(crbug.com/1401396): Re-enable this test
 external/wpt/webrtc/simulcast/setParameters-active.https.html [ Pass Timeout ]
@@ -6696,3 +6703,6 @@
 
 # Sheriff 2023-03-27
 crbug.com/1427936 external/wpt/js-self-profiling/function-expression-names.https.html [ Failure Pass ]
+
+# TODO(crbug.com/1428795): Re-enable this test
+crbug.com/1428795 [ Linux ] external/wpt/dom/events/Event-dispatch-on-disabled-elements.html [ Failure Pass ]
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index e8df5647..041c267 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -17750,6 +17750,266 @@
        {}
       ]
      ],
+     "monolithic-overflow-001-print.html": [
+      "f4121c3422582aad0bf12837270e696d06e68555",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-001-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-002-print.html": [
+      "8f76af16a9ea7a9a53d142d655d59c43100346d0",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-002-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-003-print.html": [
+      "76905b180a1232597b28c05ee3aac45690de13fa",
+      [
+       null,
+       [
+        [
+         "/css/printing/reference/monolithic-overflow-4-pages-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-004-print.html": [
+      "ea5a659bd8416a46fa3c2d1c69b68f7ea7f158bb",
+      [
+       null,
+       [
+        [
+         "/css/printing/reference/monolithic-overflow-4-pages-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-005-print.html": [
+      "bb0fc212fc0d8940363e7de9d1a3771fd90f2c57",
+      [
+       null,
+       [
+        [
+         "/css/printing/reference/monolithic-overflow-4-pages-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-006-print.html": [
+      "1cbcdbbe1e5a036a6eae8408731a15028aaae125",
+      [
+       null,
+       [
+        [
+         "/css/printing/reference/monolithic-overflow-4-pages-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-007-print.html": [
+      "14a6f051fec8489d957b14639bc3ccfcb0b644bd",
+      [
+       null,
+       [
+        [
+         "/css/printing/reference/monolithic-overflow-4-pages-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-008-print.html": [
+      "ff302dc30caa1999f9e09168feb5ac56c08af552",
+      [
+       null,
+       [
+        [
+         "/css/printing/reference/monolithic-overflow-4-pages-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-009-print.html": [
+      "bdff66e791c0fde0065578e1179085e76297d1d4",
+      [
+       null,
+       [
+        [
+         "/css/printing/reference/monolithic-overflow-4-pages-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-010-print.html": [
+      "a75c932d30b4133244ccfd7f695ff03a4870b3c3",
+      [
+       null,
+       [
+        [
+         "/css/printing/reference/monolithic-overflow-4-pages-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-011-print.html": [
+      "973a3aff4dccd49117247708413bf910b8406518",
+      [
+       null,
+       [
+        [
+         "/css/printing/reference/monolithic-overflow-4-pages-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-012-print.html": [
+      "53ed74bc7289cffacd1ec7f34b9d4e14060de6b5",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-012-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-013-print.html": [
+      "b9a174879d77d139688031724fa1b1a5093e78d3",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-013-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-014-print.html": [
+      "d12ddf4c6847ed3b6ac980e4c327ae4b77a7d148",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-014-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-015-print.html": [
+      "d52605605c93eece74a0c4e78669aeb5a8ffbbdb",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-015-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-016-print.html": [
+      "029523e924afb21bf190420f95062214127fae61",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-016-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-017-print.html": [
+      "c8ce9060fffcee8a79f265e1182e0c0cd9c2e7ae",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-017-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-018-print.html": [
+      "93da11dc62e73e2a98a275ec71f56579e1f1a604",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-018-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-019-print.html": [
+      "3740b5d5b0b954f403954e2120db6a0ca32ce1c5",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-019-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-020-print.html": [
+      "403d932d643b81a620df3eba64156d1431d14579",
+      [
+       null,
+       [
+        [
+         "/css/printing/monolithic-overflow-020-print-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "page-name-001-print.html": [
       "56281bb4ed5f8b3e34401420b10504ed6c0e00fd",
       [
@@ -85532,6 +85792,58 @@
         {}
        ]
       ],
+      "monolithic-overflow-001.tentative.html": [
+       "1171485181359f84e0f25ecda21b9655f5e0493a",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-002.tentative.html": [
+       "298f749a8d727784a4c452d4de02a661aecbe6bf",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-003.tentative.html": [
+       "ed223e809fb7e36e830dd83eafec350b8d4ae577",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-004.tentative.html": [
+       "ed7fea725c6261e4d34cc0e9686c315e6ab7464b",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "multi-line-column-flex-fragmentation-001.html": [
        "9f064d4ae40ea9e98f0b1a18c5b8fc143bbb6027",
        [
@@ -89693,6 +90005,110 @@
         ],
         {}
        ]
+      ],
+      "monolithic-overflow-001.tentative.html": [
+       "95660ec1068100e48fb489631fc7312b7937ff0c",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-002.tentative.html": [
+       "f487c3ded5fd86bf2992d45b593d7bc2d854e7aa",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-003.tentative.html": [
+       "c7a3903a09756f601fe24cd1c03a868628a88875",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-004.tentative.html": [
+       "208100619c37518bacb46abcc683947fea38cfd1",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-005.html": [
+       "069ffb5b212e4b3316485422a423c6aad7a878f8",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-006.html": [
+       "af4cfb1216b81fc4f4460ff20736e3e9e528f0a9",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-007.html": [
+       "906ad29fc16f54007a4032b5fa55d89b525ff25f",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-008.html": [
+       "6e2caf60ce825800d738a938a429a3e41fa0552e",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
       ]
      },
      "increase-fragmentainer-size-tall-border.html": [
@@ -89812,6 +90228,84 @@
        {}
       ]
      ],
+     "monolithic-overflow-001.tentative.html": [
+      "db285a929c8a7fa75b3c5546b127227ec6b2708d",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-002.tentative.html": [
+      "387af9c5016a315b9e23bd34f88f8b45a9dbfa82",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-003.tentative.html": [
+      "02210aee3d229b8c897951566961797f328e9cac",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-004.tentative.html": [
+      "9a190810af8daa9593c78237da9bb77320cbcafd",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-005.tentative.html": [
+      "f1667a15fd5cd73e8a9eb0824f910452454cb4f1",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "monolithic-overflow-006.tentative.html": [
+      "200f271dc48e6f63f242359cff31e1a21329eb60",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "monolithic-with-overflow-lr.html": [
       "cb9d0fbcfe60de8fc479159c233239e5bb272ed6",
       [
@@ -92049,6 +92543,84 @@
         {}
        ]
       ],
+      "monolithic-overflow-001.tentative.html": [
+       "34487c43279f3e6aa2ddbb41d703d938debc1981",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-002.tentative.html": [
+       "74b63fb68cbec730e898ad4a5e3b8338463714b8",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-003.tentative.html": [
+       "296a309335fa4bb2c109b6a96469843320fe3e95",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-004.tentative.html": [
+       "6f62f433e823698da207befa43ef26279d55a987",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-005.html": [
+       "7204359ad9b1d183c7e2fdf0035b973786920847",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "monolithic-overflow-006.html": [
+       "a8ebd11511969e82b739ea4c6b0948f177e4036f",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "oof-in-cell-with-alignment-001.html": [
        "7933012cb6aeccaf8d8a8cf1d35c8ee0d490a04f",
        [
@@ -133351,6 +133923,19 @@
         {}
        ]
       ],
+      "orthogonal-writing-mode-005.html": [
+       "d5bd17816104e40538303b8b637897c367c6af63",
+       [
+        null,
+        [
+         [
+          "/css/css-grid/subgrid/orthogonal-writing-mode-005-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "parent-repeat-auto-fit-001.html": [
        "8ecbccbea64320054f940d9c2e2d31dd028daa14",
        [
@@ -133417,7 +134002,7 @@
        ]
       ],
       "repeat-auto-fill-003.html": [
-       "3a1d2707c37c6861dc97cd6cdd5f2f3739a431c7",
+       "df14ed8350bce321e50c6f0721b91ad63714083c",
        [
         null,
         [
@@ -146786,7 +147371,7 @@
        ]
       ],
       "clip-path-shape-circle-003.svg": [
-       "f0110ee0a531842ce7d9239b8f9fb0de47fc69fa",
+       "0a0432c1166e867d6fdb89ef3567450c992bcc5f",
        [
         null,
         [
@@ -146795,11 +147380,27 @@
           "=="
          ]
         ],
-        {}
+        {
+         "fuzzy": [
+          [
+           null,
+           [
+            [
+             0,
+             64
+            ],
+            [
+             0,
+             184
+            ]
+           ]
+          ]
+         ]
+        }
        ]
       ],
       "clip-path-shape-circle-004.svg": [
-       "c3db6d662d88ce0958345ab30f41a082b04d60e9",
+       "044b2ecc9e16e5c617ede8915db6169cc4ab65d9",
        [
         null,
         [
@@ -146808,7 +147409,23 @@
           "=="
          ]
         ],
-        {}
+        {
+         "fuzzy": [
+          [
+           null,
+           [
+            [
+             0,
+             64
+            ],
+            [
+             0,
+             76
+            ]
+           ]
+          ]
+         ]
+        }
        ]
       ],
       "clip-path-shape-circle-005.svg": [
@@ -267469,6 +268086,16 @@
    }
   },
   "support": {
+   ".cache": {
+    "gitignore2.json": [
+     "ecbdb8818bea6bf22e9f15652dda95083d622c30",
+     []
+    ],
+    "mtime.json": [
+     "2b909a050abdc8ef21fa8b38bfd8491850e8fa40",
+     []
+    ]
+   },
    ".gitignore": [
     "d93e645d547894b50149d3726de2654957b6e06f",
     []
@@ -269785,6 +270412,28 @@
     "idlharness.https.any.worker-expected.txt": [
      "18bb5ee48b7d4801ff46676375cd3967bc2d9dab",
      []
+    ],
+    "non-fully-active.https-expected.txt": [
+     "6446290c8838fa98233c272d849a1cfe97f5b80e",
+     []
+    ],
+    "non-fully-active.https.html.ini": [
+     "82e4f77dfe5f2f09341e38a6b0daf6e3372b2604",
+     []
+    ],
+    "resources": {
+     "setAppBadge_iframe.html": [
+      "8738099658fbb2de893658e70242e855ecccd4b1",
+      []
+     ]
+    },
+    "setAppBadge_cross_origin.sub.https-expected.txt": [
+     "baeb69af9eb1ac22149c657fcf1e2b9605ccf276",
+     []
+    ],
+    "setAppBadge_cross_origin.sub.https.html.ini": [
+     "f268ea08cfd6998cb20d87c932329ed32347e2d7",
+     []
     ]
    },
    "battery-status": {
@@ -270209,6 +270858,10 @@
      []
     ],
     "resources": {
+     "check-topics-request-header-notify-parent.py": [
+      "98c77c2b0bd21591416d886d1ab013486a805550",
+      []
+     ],
      "check-topics-request-header.py": [
       "569b75449635c51e6581afecb582cdb818e6c120",
       []
@@ -270233,6 +270886,10 @@
       "c19efb5f2f3fe5469b63b5772c875d9e62fb47b5",
       []
      ],
+     "navigation-header-util.sub.js": [
+      "b3bec79651d0cfca140176a5527327d86d780ad5",
+      []
+     ],
      "permissions-policy-util.sub.js": [
       "e8bf45049c53ab23fee369c058ffe4904bed45ce",
       []
@@ -274532,7 +275189,7 @@
       []
      ],
      "cookie-helper.sub.js": [
-      "ff33ecb6bd2c025c58ec07924b8ac99d8529a461",
+      "3338cf0e800cba0d59b9a86c8270c262772b3d7b",
       []
      ],
      "cookie-test.js": [
@@ -302204,6 +302861,10 @@
        "aeb69155b6c08429934b1c8b10e83ea858a12dba",
        []
       ],
+      "orthogonal-writing-mode-005-ref.html": [
+       "f8fa0ab81b9fecee6d9efbb8f20e4af4cd1d89ad",
+       []
+      ],
       "parent-repeat-auto-fit-001-ref.html": [
        "2217497cd2bf1813ecb585564788b81488079b85",
        []
@@ -316530,6 +317191,18 @@
        "fa85c5c713b4f54eda0d838b667fe7698b036e08",
        []
       ],
+      "white-space-collapse-computed.html.ini": [
+       "6b697c30ef7df4d4e96ccdefa8f9da3c87806a96",
+       []
+      ],
+      "white-space-collapse-valid.html.ini": [
+       "6e8383f5c2f611f2e9899ff3c8ab567a228fa78a",
+       []
+      ],
+      "white-space-shorthand.html.ini": [
+       "7534924bfc5d82f6fa8188613a480f1cabdb310a",
+       []
+      ],
       "word-boundary-detection-computed-expected.txt": [
        "3af63b1ecf4ea2c53aa09cb7f55e33a216cc1441",
        []
@@ -317795,7 +318468,7 @@
        []
       ],
       "text-transform-capitalize-016.html.ini": [
-       "76a85b163aac3061e477a882d92419275450dbca",
+       "8c553195bbe814154a83dc3e691ec8bd234f44d5",
        []
       ],
       "text-transform-capitalize-018.html.ini": [
@@ -323544,6 +324217,10 @@
        "c3109afb3faa3d56f44ed019dfe2262ad57059fc",
        []
       ],
+      "kind-of-widget-fallback-color-input-border-bottom-left-radius-001.html.ini": [
+       "6f8cad0d45ca247eeff266835eb6a715958cc254",
+       []
+      ],
       "kind-of-widget-fallback-color-input-border-bottom-style-001.html.ini": [
        "781e3a390720e3062919d91b8b872054bbd0548f",
        []
@@ -323684,10 +324361,18 @@
        "640329ec198e4e4c6ee9447f580fc1454f6820e8",
        []
       ],
+      "kind-of-widget-fallback-input-search-border-top-right-radius-001.html.ini": [
+       "71e29e5563f053261425cc3d928a38ed0769ca39",
+       []
+      ],
       "kind-of-widget-fallback-input-search-text-background-clip-001.html.ini": [
        "5981cd7fe9796312b82645e87b2da6ad7f00ada1",
        []
       ],
+      "kind-of-widget-fallback-input-search-text-background-image-001.html.ini": [
+       "11937e99183f1e2bc3021880f525ee12bac9637c",
+       []
+      ],
       "kind-of-widget-fallback-input-search-text-border-block-end-style-001.html.ini": [
        "bf85076c27628a5885b91254e618404c279873a7",
        []
@@ -323713,7 +324398,7 @@
        []
       ],
       "kind-of-widget-fallback-input-search-text-border-end-end-radius-001.html.ini": [
-       "535207b8cf1feedfaa63c151a57a1ee3c61da3f4",
+       "697b05b022bee8c7b3d8ac9869f1593a5860b6ef",
        []
       ],
       "kind-of-widget-fallback-input-search-text-border-image-source-001.html.ini": [
@@ -324120,6 +324805,10 @@
        "9cc5c23ae55ff9a62be744e08d13d8e3c884f662",
        []
       ],
+      "kind-of-widget-fallback-textarea-border-block-start-style-001.html.ini": [
+       "3e272ca820ca4e776ba9e84ed695c92dd0cd44fc",
+       []
+      ],
       "kind-of-widget-fallback-textarea-border-bottom-color-001.html.ini": [
        "ab60e58a77d9675b81f14d905d3c84971d0901df",
        []
@@ -325576,11 +326265,11 @@
       []
      ],
      "calc-infinity-nan-serialize-length-expected.txt": [
-      "56ac7eedc3014f41277191537c026a91971e6f88",
+      "4c24f6998d43a5f13660febc6763eb27e1e11ac6",
       []
      ],
      "calc-infinity-nan-serialize-length.html.ini": [
-      "342fa6e1decb20d7eec24adbfc80ba8dd5eaa9ff",
+      "944e180f8d1ccbca7dc50952e92ff26bf580db6f",
       []
      ],
      "calc-infinity-nan-serialize-resolution-expected.txt": [
@@ -331915,6 +332604,50 @@
       "f4ea262fa5b4de4a0e30bdf9d89ed76f1da41242",
       []
      ],
+     "monolithic-overflow-001-print-ref.html": [
+      "9edc5d9ed0d97d40f734396ff54fe6fc69b0492b",
+      []
+     ],
+     "monolithic-overflow-002-print-ref.html": [
+      "5478362b066fe462959f5610b92c4415afb74fc4",
+      []
+     ],
+     "monolithic-overflow-012-print-ref.html": [
+      "e47ca880f93196bd9c1a488ed883a46839744a1c",
+      []
+     ],
+     "monolithic-overflow-013-print-ref.html": [
+      "e47ca880f93196bd9c1a488ed883a46839744a1c",
+      []
+     ],
+     "monolithic-overflow-014-print-ref.html": [
+      "a74e0d19a558a6c663b632ad88fb888ca42c707a",
+      []
+     ],
+     "monolithic-overflow-015-print-ref.html": [
+      "db44a3ee21e57cf4c0c11cf081a516ca150fcba8",
+      []
+     ],
+     "monolithic-overflow-016-print-ref.html": [
+      "a675fb966c56aa5db37731e382a54675dcb7cb20",
+      []
+     ],
+     "monolithic-overflow-017-print-ref.html": [
+      "45f839787e03f286e1cdca0a887a48297ea03294",
+      []
+     ],
+     "monolithic-overflow-018-print-ref.html": [
+      "cf31737d6c3f750524ad1c291281f6fcb777f786",
+      []
+     ],
+     "monolithic-overflow-019-print-ref.html": [
+      "f37740ae7e606b2f8acce89f4210bdd961c11edd",
+      []
+     ],
+     "monolithic-overflow-020-print-ref.html": [
+      "528c4980de590bc48c3017b246052b561f170bbd",
+      []
+     ],
      "page-name-001-print-ref.html": [
       "69c5c37b5a3cc4ed47fab1f8105e5f2351e2d07b",
       []
@@ -331939,6 +332672,12 @@
       "07107d1db7845f9d2186b558753818444d410318",
       []
      ],
+     "reference": {
+      "monolithic-overflow-4-pages-print-ref.html": [
+       "c115782d6ad862870235953e56474e7eae4902bc",
+       []
+      ]
+     },
      "transition-in-media-print-ref.html": [
       "2f25c06131e9372512e23ab9ff8428c594f74391",
       []
@@ -341172,7 +341911,7 @@
    "fledge": {
     "tentative": {
      "TODO": [
-      "d1d3930886b51f949ad0354278970b0c77c3c6e6",
+      "d50e49261164795e9f49e50100de04178bc5ff7f",
       []
      ],
      "join-leave-ad-interest-group.https.sub.window-expected.txt": [
@@ -341221,12 +341960,16 @@
        []
       ],
       "fledge-util.js": [
-       "738764f651962b10ffe956bd86a9f81da40193d2",
+       "ed09a6be87c257289e0bfca16f9908c4dea24f33",
        []
       ],
-      "request_tracker.py": [
+      "request-tracker.py": [
        "46da796f30102e0e32a82a4dab96fa9217154306",
        []
+      ],
+      "trusted-bidding-signals.py": [
+       "cdd7052a96ab42d9a143f9d47a7c71cb6910de72",
+       []
       ]
      },
      "send-report-to.https.sub.window-expected.txt": [
@@ -341236,6 +341979,14 @@
      "send-report-to.https.sub.window.js.ini": [
       "d3ca367206691d352d62c79cb310abb55ae0d02b",
       []
+     ],
+     "trusted-bidding-signals.https.sub.window-expected.txt": [
+      "e6173c948162b32052749c3164321ed565849a36",
+      []
+     ],
+     "trusted-bidding-signals.https.sub.window.js.ini": [
+      "ac9b4aa35922490a9c851f1539e5ac1b5fd8fdc1",
+      []
      ]
     }
    },
@@ -349488,7 +350239,7 @@
         []
        ],
        "access-to-coop-page-from-other_coop-ro_cross-origin.https.html.ini": [
-        "6226dd39080867feed6d6dae56cfcd2a605372d6",
+        "e6faede1dd00c0355c5e6d59abbe980c06cece27",
         []
        ],
        "property-blur.https.html.ini": [
@@ -355659,6 +356410,10 @@
       "event-propagate-disabled-keyboard.tentative.html.ini": [
        "239955eb76993f99e53bd3ca42c25c6df689bbb3",
        []
+      ],
+      "event-propagate-disabled.tentative.html.ini": [
+       "26dc9e859d973b4b44fa44e7ec817ed9125e3f55",
+       []
       ]
      },
      "document-metadata": {
@@ -357408,10 +358163,6 @@
          "0f7ab9ae2728fc5a18f684db506a82b71852162b",
          []
         ],
-        "viewport-change-expected.txt": [
-         "47b74410065abb0292f0139fa81685eadf9024a1",
-         []
-        ],
         "viewport-change.html.ini": [
          "d30a5060ff39fd365d1ce3102122ad938b7836c6",
          []
@@ -365283,7 +366034,7 @@
      []
     ],
     "cross-origin-iframe.sub.html.ini": [
-     "004f0b64c9b047e6dcbba796907f0ca31bef0a7e",
+     "fd7b32d74ea54735da38c1b2bec1dc4f9f47954b",
      []
     ],
     "idlharness.window-expected.txt": [
@@ -365963,6 +366714,10 @@
      []
     ],
     "tentative": {
+     "loaf-desired-exec-time.html.ini": [
+      "8e64d0a34431c6fcf2bc95fe1c7b06aa9be381ff",
+      []
+     ],
      "loaf-first-ui-event.html.ini": [
       "a3d3fb4e0bd5cacd8cb627501073eaf076b90af7",
       []
@@ -368189,11 +368944,11 @@
      []
     ],
     "MediaRecorder-stop-expected.txt": [
-     "7c23f51c570772666d23b252209ae29c4b680417",
+     "6bdc8e602b72e4eea7d708716c470d20cd6286be",
      []
     ],
     "MediaRecorder-stop.html.ini": [
-     "dbfef8ba42177efa952c2e2e27aeda55e0483ba6",
+     "91e6176ac3ea04c501d47389147e224c5baf313e",
      []
     ],
     "OWNERS": [
@@ -369131,6 +369886,10 @@
        []
       ]
      },
+     "defaultPrevented-window-stop-after-dispatch.html.ini": [
+      "63ad5f9ace5efb7503de159370d87b39e018a17c",
+      []
+     ],
      "intercept-and-navigate.html.ini": [
       "6f5f6250202cb58797af28017039f48c3eeddb05",
       []
@@ -379579,6 +380338,10 @@
       "7edc9ee8e187ba93a05a8b42a49744674a0ad4a4",
       []
      ],
+     "csp-script-src-strict-dynamic.html.ini": [
+      "6563cff979a6a2b6a097280b64097676ec223e8c",
+      []
+     ],
      "csp-script-src-unsafe-inline.html.ini": [
       "191ed7f745ff643f911ba24b76cda823a9fdace0",
       []
@@ -379740,12 +380503,16 @@
        "8dc382068a347990c91aeaafc8b509553cac8767",
        []
       ],
+      "csp-script-src-strict-dynamic.html": [
+       "00db373c47a4df58b7df5c7c53a427885f82c48c",
+       []
+      ],
       "csp-script-src-unsafe-inline.html": [
        "d2f010dc569d0908818a8d00d7020220c897b11a",
        []
       ],
       "csp-script-src.js": [
-       "52419f9b4c24240fe1f7f4594fc660e634cf34af",
+       "866acaa09ba78ed77026db4c083aa23bcbb0a9e2",
        []
       ],
       "dedicated-worker.https.html": [
@@ -380463,7 +381230,11 @@
      []
     ],
     "helpers.js": [
-     "f718f637cd964b4b2d3fc68879fa9d4a2035480d",
+     "01a9d9f0ce6fe67a3977e9a8c2e8b7fbb961f957",
+     []
+    ],
+    "requestStorageAccess-ABA.tentative.sub.https.window.js.ini": [
+     "71cdfe13d7c89ca67951dd83d9610dbe96974412",
      []
     ],
     "requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js.ini": [
@@ -380479,20 +381250,32 @@
      []
     ],
     "requestStorageAccess-nested-cross-origin-iframe.sub.https.window.js.ini": [
-     "4b233c658f17836f950eaeb891c17919b412597c",
+     "1107f8dcf3cdfc9c0e6b69579d04768788e5c111",
      []
     ],
     "requestStorageAccess-nested-cross-site-iframe.sub.https.window.js.ini": [
      "9e18caa7b4a53402ed0ec15c1ebaeab7a69e01b1",
      []
     ],
+    "requestStorageAccess-nested-same-origin-iframe.sub.https.window.js.ini": [
+     "8dee85dfd3240301dbb1efe2441b3a46150c61ad",
+     []
+    ],
+    "requestStorageAccess-same-site-iframe.sub.https.window.js.ini": [
+     "4ae9c4d9f9e067a8d47efa51467e94becb0fb3cd",
+     []
+    ],
+    "requestStorageAccess.sub.https.window.js.ini": [
+     "977d0cb17e106da34ba96cf63218211e43bf1cca",
+     []
+    ],
     "resources": {
      "echo-cookie-header.py": [
       "f1599e3a89919adfe0a0de60515ef1d44a898190",
       []
      ],
      "embedded_responder.js": [
-      "6d4209608e455873d50d31083ef5f46fcb68703e",
+      "ab1ab30f6964130e6c4d09655c77cca3095596a4",
       []
      ],
      "hasStorageAccess-ABA-iframe.https.html": [
@@ -380528,7 +381311,7 @@
       []
      ],
      "requestStorageAccess-iframe.https.html": [
-      "4880464a257c65e16d7a70471a31a571f8de4878",
+      "828af799e6cad6ce5e4901010db7d9af93ec3321",
       []
      ],
      "script-with-cookie-header.py": [
@@ -380614,7 +381397,7 @@
     },
     "readable-byte-streams": {
      "tee.any-expected.txt": [
-      "a804638a686da4e7bbf52fb3e49a65ce1f7c4bf8",
+      "dc28c93fc09b1fbbc30d24ad319aeb8964bd0133",
       []
      ],
      "tee.any.js.ini": [
@@ -380622,15 +381405,15 @@
       []
      ],
      "tee.any.serviceworker-expected.txt": [
-      "a804638a686da4e7bbf52fb3e49a65ce1f7c4bf8",
+      "dc28c93fc09b1fbbc30d24ad319aeb8964bd0133",
       []
      ],
      "tee.any.sharedworker-expected.txt": [
-      "a804638a686da4e7bbf52fb3e49a65ce1f7c4bf8",
+      "dc28c93fc09b1fbbc30d24ad319aeb8964bd0133",
       []
      ],
      "tee.any.worker-expected.txt": [
-      "a804638a686da4e7bbf52fb3e49a65ce1f7c4bf8",
+      "dc28c93fc09b1fbbc30d24ad319aeb8964bd0133",
       []
      ]
     },
@@ -380686,11 +381469,11 @@
       []
      ],
      "global-expected.txt": [
-      "8fe1616d6f418193104188a79187815c3f64ac36",
+      "e8a0733039a4a3bd5de68d99420461d907a83fbc",
       []
      ],
      "global.html.ini": [
-      "a996d8dd6284aa9d770bfe9d6dd7acae93c76973",
+      "4ddd919bee0b74c3c6d565f4594d535f51366148",
       []
      ],
      "patched-global.any-expected.txt": [
@@ -380713,25 +381496,9 @@
       "70f78cb71882cbccb0724a543a6bd79ae7a09066",
       []
      ],
-     "tee.any-expected.txt": [
-      "852f5d01860c2d0cc47ad4a08bc1e0063a00db83",
-      []
-     ],
      "tee.any.js.ini": [
       "0cdfaa7c399f1a619dc7ffed133d2b756494726a",
       []
-     ],
-     "tee.any.serviceworker-expected.txt": [
-      "852f5d01860c2d0cc47ad4a08bc1e0063a00db83",
-      []
-     ],
-     "tee.any.sharedworker-expected.txt": [
-      "852f5d01860c2d0cc47ad4a08bc1e0063a00db83",
-      []
-     ],
-     "tee.any.worker-expected.txt": [
-      "852f5d01860c2d0cc47ad4a08bc1e0063a00db83",
-      []
      ]
     },
     "resources": {
@@ -380799,6 +381566,16 @@
        []
       ]
      }
+    },
+    "transform-streams": {
+     "invalid-realm.window-expected.txt": [
+      "74422a3aef1e44100aaf68a6479cda7057e2afb4",
+      []
+     ],
+     "invalid-realm.window.js.ini": [
+      "2231a8b2a54783195948deaae1643ee8f0dbee62",
+      []
+     ]
     }
    },
    "subapps": {
@@ -382585,7 +383362,7 @@
      []
     ],
     "META.yml": [
-     "8cc6a43aa12617ff8738ce571814f954454b6666",
+     "04061ac0f66a849b4dd2f71c8abef40f47240a96",
      []
     ],
     "OWNERS": [
@@ -383603,7 +384380,7 @@
      []
     ],
     "README.md": [
-     "50a71bb482df9e21f6385973268f9e95b3464e7c",
+     "fa5e3b0dc72385a5a60125802d78c53e46e99058",
      []
     ],
     "a-element-origin-xhtml.xhtml.ini": [
@@ -383615,7 +384392,7 @@
      []
     ],
     "a-element-xhtml.xhtml.ini": [
-     "95c1d6ab9ca9f23e6ffb17c5128d0e779c56a7ff",
+     "ff38c9b3d6213794adc4c365f6286c9eeb871625",
      []
     ],
     "a-element-xhtml_include=javascript-expected.txt": [
@@ -383627,7 +384404,7 @@
      []
     ],
     "a-element.html.ini": [
-     "320c7d1790139fb6bee71baf6cb556370337a57e",
+     "3efb4ab2538aaa8d967717ce2c818143339b418a",
      []
     ],
     "a-element_include=javascript-expected.txt": [
@@ -383664,11 +384441,11 @@
       []
      ],
      "a-element-origin.js": [
-      "cb7d4a895c40c456c3f4c0ade050115319ad410c",
+      "de72988ea93c12b067d01f99bb39e451e312d837",
       []
      ],
      "a-element.js": [
-      "65c7e85281360fcea6aa24632d3063d55bf70a15",
+      "d87937d002b24ad70a53a535e32d40fbf4ab2523",
       []
      ],
      "percent-encoding.json": [
@@ -383688,7 +384465,7 @@
       []
      ],
      "urltestdata.json": [
-      "a3cf976534cce6d84bb6681330fe95fff7bf2dd1",
+      "beb4d9ca12b51dffaadca03bac2444f92e62b6bd",
       []
      ]
     },
@@ -383707,27 +384484,27 @@
      ]
     },
     "url-constructor.any.js.ini": [
-     "93bf975ec856449db62631b15a3d548a97470395",
+     "70d3d3411680336b5287bd5061ccc8f7dc7f5f50",
      []
     ],
     "url-constructor.any.worker_include=javascript-expected.txt": [
-     "c84000a727361ca3ce1aaf56675ce20e1ba5d6a9",
+     "f9c69865f4b9e9e5f06f40ea925292b86c2a7048",
      []
     ],
     "url-constructor.any.worker_include=mailto-expected.txt": [
-     "76ca25f42321e9fbb1143f13defe97d859a3ba4d",
+     "f33c01375de0d396e4f5b6dca71407b44bc63197",
      []
     ],
     "url-constructor.any_include=javascript-expected.txt": [
-     "c84000a727361ca3ce1aaf56675ce20e1ba5d6a9",
+     "f9c69865f4b9e9e5f06f40ea925292b86c2a7048",
      []
     ],
     "url-constructor.any_include=mailto-expected.txt": [
-     "76ca25f42321e9fbb1143f13defe97d859a3ba4d",
+     "f33c01375de0d396e4f5b6dca71407b44bc63197",
      []
     ],
     "url-origin.any.js.ini": [
-     "83629f0d695f8f93d53494536ad85893ca3fca39",
+     "837c7c2b264f0a8d2bdbda8ff05aee3ee6f9ec2d",
      []
     ],
     "url-setters-a-area.window.js.ini": [
@@ -384830,7 +385607,7 @@
       []
      ],
      "keyframe-utils.js": [
-      "8e6e5840f7f87221b87e6a31f7874a0863395f24",
+      "60fb9781a0c080791829abb0bad9e4a084fe2ba6",
       []
      ],
      "timing-override.js": [
@@ -389083,7 +389860,7 @@
        []
       ],
       "constructor.any.js.ini": [
-       "149394c10ca3822b9f8310c416d43db18cae49c0",
+       "06db16bc5e80dff6b8a642fb7a2bd2fa9485b944",
        []
       ],
       "constructor.any.serviceworker_wpt_flags=h2-expected.txt": [
@@ -392615,7 +393392,7 @@
      ]
     },
     "idlharness.https.window-expected.txt": [
-     "1751bf6f56abe5e1a494df1260a47f69a25b2b65",
+     "711123c1192b80646e0b9c4258567c4f9158d789",
      []
     ],
     "idlharness.https.window.js.ini": [
@@ -409568,6 +410345,20 @@
        "timeout": "long"
       }
      ]
+    ],
+    "non-fully-active.https.html": [
+     "d870e52273c0a310df3c3ab3f97693d7070a6cb7",
+     [
+      null,
+      {}
+     ]
+    ],
+    "setAppBadge_cross_origin.sub.https.html": [
+     "7e548879bcbf67c84a94a6b5d9dd276016d03ff0",
+     [
+      null,
+      {}
+     ]
     ]
    },
    "battery-status": {
@@ -416158,21 +416949,21 @@
    },
    "browsing-topics": {
     "browsing-topics-permissions-policy-default.tentative.https.sub.html": [
-     "a7c5a95cff33407b1ec172a8881964450e758a8f",
+     "884ad9276a1d087684d06ed1b03bbdc57d3f7d8c",
      [
       null,
       {}
      ]
     ],
     "browsing-topics-permissions-policy-none.tentative.https.sub.html": [
-     "7d33f3bdaee21e4c522d53cff14c258b2f9921ac",
+     "2f80daa27142c6a2ccd7b0e33005a4659180bf1b",
      [
       null,
       {}
      ]
     ],
     "browsing-topics-permissions-policy-self.tentative.https.sub.html": [
-     "7647998c8562cc70379e5238b440dec47fb6a665",
+     "601266794797ebf8b7a7bdacfd3b3c5cb1c92f2c",
      [
       null,
       {}
@@ -416220,6 +417011,20 @@
       {}
      ]
     ],
+    "iframe-topics-attribute-insecure-context.tentative.http.sub.html": [
+     "19c79e0d7f001b592a93214ee89dcdf15afbe5dc",
+     [
+      null,
+      {}
+     ]
+    ],
+    "iframe-topics-attribute.tentative.https.html": [
+     "b90f967146ce49235d216ef7a18056b1b282d263",
+     [
+      null,
+      {}
+     ]
+    ],
     "topics-not-allowed-for-service-worker-fetch.tentative.https.html": [
      "1bd578e9bf74fb942fa1bfcc6c001c0c096364bf",
      [
@@ -427864,6 +428669,15 @@
        ]
       ]
      },
+     "borders": {
+      "discrete-no-interpolation.html": [
+       "0268b675f362f09b6f1f1b3b6ebb25859fffa816",
+       [
+        null,
+        {}
+       ]
+      ]
+     },
      "floats": {
       "computed-float-position-absolute.html": [
        "ad9220b3a06085c458f7100c896100fb32f562e8",
@@ -427964,6 +428778,15 @@
        ]
       ]
      },
+     "floats-clear": {
+      "clear-no-interpolation.html": [
+       "05db269ec67e10172b441dedaa79df58974af11d",
+       [
+        null,
+        {}
+       ]
+      ]
+     },
      "linebox": {
       "animations": {
        "line-height-interpolation.html": [
@@ -428211,6 +429034,15 @@
         {}
        ]
       ]
+     },
+     "tables": {
+      "border-collapse-no-interpolation.html": [
+       "800cc68d0c33d0dc5bd2a8bb2101aeb5c49d3136",
+       [
+        null,
+        {}
+       ]
+      ]
      }
     },
     "compositing": {
@@ -430681,6 +431513,13 @@
         null,
         {}
        ]
+      ],
+      "discrete-no-interpolation.html": [
+       "d3d3421d5ebaabab57f0a9725dd799610c19d201",
+       [
+        null,
+        {}
+       ]
       ]
      },
      "background-331.html": [
@@ -430732,15 +431571,6 @@
        {}
       ]
      ],
-     "background-repeat": {
-      "background-repeat-no-interpolation.html": [
-       "a1a48d58e8c86f1c0c93d33ca588558f4cb561e8",
-       [
-        null,
-        {}
-       ]
-      ]
-     },
      "background-size-001.html": [
       "fee271de14a4664a0aff4f99b4511107b36beb77",
       [
@@ -431608,6 +432438,13 @@
     },
     "css-break": {
      "animation": {
+      "break-no-interpolation.html": [
+       "8a7bf7a68a3fd8338ffdd94068f74c9305869e9f",
+       [
+        null,
+        {}
+       ]
+      ],
       "orphans-interpolation.html": [
        "704c2737ce83a5c823bf5969d5f0de687c7d31a2",
        [
@@ -440914,7 +441751,7 @@
        ]
       ],
       "grid-template-columns-computed-nogrid.html": [
-       "11b0393a676c7f18ede6485fbb9dab7cf1d98067",
+       "b1f80a728c4295af3f6a98aa49284ff5ee4700f8",
        [
         null,
         {}
@@ -441065,7 +441902,7 @@
      },
      "subgrid": {
       "grid-template-computed-nogrid.html": [
-       "ccfe67a5c0f27a0aa00c47120a74e2b3dbff997b",
+       "1f37ce860acfd3eeec3f00dcd09819e00b15a5b9",
        [
         null,
         {}
@@ -441419,6 +442256,13 @@
      }
     },
     "css-inline": {
+     "alignment-baseline-no-interpolation.html": [
+      "57deaf8abe68d05bb1c95a779a9c2b6c2ddb57b5",
+      [
+       null,
+       {}
+      ]
+     ],
      "baseline-source": {
       "baseline-source-computed.html": [
        "e19f7ffca6d7c4ca504a6754874519d1c15a9835",
@@ -441476,6 +442320,13 @@
         {}
        ]
       ],
+      "baseline-source-no-interpolation.html": [
+       "86fede739fcd6cda3ff8736c349cba5aa8ecd822",
+       [
+        null,
+        {}
+       ]
+      ],
       "baseline-source-valid.html": [
        "6ca38566bbe008c615cd4ade71ca6ed77db7f625",
        [
@@ -441958,6 +442809,13 @@
       ]
      ],
      "animations": {
+      "caption-side-no-interpolation.html": [
+       "2eef093e46c751b4a12d36998c1d3d472fa112d7",
+       [
+        null,
+        {}
+       ]
+      ],
       "float-interpolation.html": [
        "c067f2f03ceb568154bee543f5f9b7a1989b940a",
        [
@@ -442555,6 +443413,15 @@
        ]
       ]
      },
+     "clip-rule": {
+      "clip-rule-no-interpolation.html": [
+       "066636c5e92e388311554010dad5e15d628039de",
+       [
+        null,
+        {}
+       ]
+      ]
+     },
      "hit-test": {
       "clip-path-element-objectboundingbox-001.html": [
        "22d4bc0b0d3feea9ea9355c90ddd3c714e995b0a",
@@ -446817,6 +447684,13 @@
        {}
       ]
      ],
+     "part-mutation-pseudo.html": [
+      "d0e0072d51e6521ab6b4daba9dfe0ce674970297",
+      [
+       null,
+       {}
+      ]
+     ],
      "part-name-idl.html": [
       "fc3282a6e944950548eeda66a78d453ec1a552f3",
       [
@@ -447731,6 +448605,13 @@
         {}
        ]
       ],
+      "box-sizing-no-interpolation.html": [
+       "d68844561ac913d48afa4194ce867ffb33cd8654",
+       [
+        null,
+        {}
+       ]
+      ],
       "height-composition.html": [
        "094e247dcf22d9bd665b244993b6239265ee73bb",
        [
@@ -451293,6 +452174,27 @@
         {}
        ]
       ],
+      "white-space-collapse-computed.html": [
+       "506e257cbe72c4c9469dc20d0e360c80e4367a5f",
+       [
+        null,
+        {}
+       ]
+      ],
+      "white-space-collapse-invalid copy.html": [
+       "6c18ecec21c5c83aa897c762c7bda8f5cabc37e1",
+       [
+        null,
+        {}
+       ]
+      ],
+      "white-space-collapse-valid.html": [
+       "2191167527bb12336c17e87208b33fa2b34a498a",
+       [
+        null,
+        {}
+       ]
+      ],
       "white-space-computed.html": [
        "a7c2ec12eb98e802cd8724b87bde68d6874ffb63",
        [
@@ -451307,6 +452209,20 @@
         {}
        ]
       ],
+      "white-space-shorthand-text-wrap.html": [
+       "0600b8249e5c17e3feee30eebe854043c60ccb49",
+       [
+        null,
+        {}
+       ]
+      ],
+      "white-space-shorthand.html": [
+       "518f81fdbf268d20e78b9f226391ecc9be46b69d",
+       [
+        null,
+        {}
+       ]
+      ],
       "white-space-valid.html": [
        "d872c0b6fbc3324836e7565d1b623e64032db1ab",
        [
@@ -451625,13 +452541,6 @@
         {}
        ]
       ],
-      "text-wrap-white-space-001.html": [
-       "0600b8249e5c17e3feee30eebe854043c60ccb49",
-       [
-        null,
-        {}
-       ]
-      ],
       "trailing-space-before-br-001.html": [
        "fcc2bdfa43633783151aaa8c0f65458d13e764f1",
        [
@@ -452213,6 +453122,13 @@
       ]
      ],
      "animation": {
+      "backface-visibility-no-interpolation.html": [
+       "b7b9f2d5f0034b30bf1b36eecc6775b756f0dc38",
+       [
+        null,
+        {}
+       ]
+      ],
       "composited-transform.html": [
        "182321b9d30807a3231ce894a58d41bcea2dc04e",
        [
@@ -455925,6 +456841,13 @@
         {}
        ]
       ],
+      "appearance-no-interpolation.html": [
+       "5ddfcd4f8d655e9a810ded73c9f07e956c908dfe",
+       [
+        null,
+        {}
+       ]
+      ],
       "caret-color-composition.html": [
        "6c69578677896e2463331deba85731e13fd94a25",
        [
@@ -456608,7 +457531,7 @@
       ]
      ],
      "calc-infinity-nan-serialize-length.html": [
-      "e08e050c6bdb6bdf9411c8e1fd51db9f71af3c69",
+      "f0ae43679b2be9a711b3bf05dab7d4e04fa868b6",
       [
        null,
        {}
@@ -464625,7 +465548,7 @@
       ]
      ],
      "Event-dispatch-on-disabled-elements.html": [
-      "361006a7240496e9be747faca5056fe2a62a2cff",
+      "e7d6b455bbcaab8c485c56fe63e309215dac31a8",
       [
        null,
        {
@@ -487707,7 +488630,7 @@
        ]
       ],
       "response-null-body.any.js": [
-       "7824a200067cf0ab01488274d1dbe8bc7b66bef0",
+       "bb058926572e82b4b04811579112e57c8f7742ca",
        [
         "fetch/api/basic/response-null-body.any.html",
         {
@@ -498533,7 +499456,7 @@
    "fledge": {
     "tentative": {
      "join-leave-ad-interest-group.https.sub.window.js": [
-      "e967d92618cfce83ad01c421202164bbe49f7a3a",
+      "3afc80eb68c3c567162b594c563859d066635385",
       [
        "fledge/tentative/join-leave-ad-interest-group.https.sub.window.html",
        {
@@ -498555,7 +499478,7 @@
       ]
      ],
      "no-winner.https.sub.window.js": [
-      "a944b860d0c77fad4784e9aee1dac62376de3a6b",
+      "8fd7df50cde0fb237deca7d3b9f1f3eedaff94e6",
       [
        "fledge/tentative/no-winner.https.sub.window.html",
        {
@@ -498582,7 +499505,7 @@
       ]
      ],
      "register-ad-beacon.https.sub.window.js": [
-      "3df6b408a57068aaee91b7f6bb772a523f94d82b",
+      "2284ac85b41f09fd884fc612c1941a13199b1c51",
       [
        "fledge/tentative/register-ad-beacon.https.sub.window.html",
        {
@@ -498609,7 +499532,7 @@
       ]
      ],
      "reporting-arguments.https.sub.window.js": [
-      "69b7d2fddda4e2a12f42b9549da8177c5dc0ccf3",
+      "262e0eb87e67b04fc9d61c0ba9c3d1b9f1dde70c",
       [
        "fledge/tentative/reporting-arguments.https.sub.window.html",
        {
@@ -498636,7 +499559,7 @@
       ]
      ],
      "send-report-to.https.sub.window.js": [
-      "bb0e7873a7024a562794d257441b038e5256f853",
+      "de22e827a33e195cf6122dc927ff4344de8b23b0",
       [
        "fledge/tentative/send-report-to.https.sub.window.html",
        {
@@ -498661,6 +499584,33 @@
         "timeout": "long"
        }
       ]
+     ],
+     "trusted-bidding-signals.https.sub.window.js": [
+      "0f8b2396392ab0f58e3c84d8900248c1b7fe2d8a",
+      [
+       "fledge/tentative/trusted-bidding-signals.https.sub.window.html",
+       {
+        "script_metadata": [
+         [
+          "script",
+          "/resources/testdriver.js"
+         ],
+         [
+          "script",
+          "/common/utils.js"
+         ],
+         [
+          "script",
+          "resources/fledge-util.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ]
      ]
     }
    },
@@ -535754,6 +536704,15 @@
          "timeout": "long"
         }
        ]
+      ],
+      "fieldset-event-propagation.tentative.html": [
+       "11822e4dd48db047212833a48a82b60c7e9cae72",
+       [
+        null,
+        {
+         "testdriver": true
+        }
+       ]
       ]
      },
      "document-metadata": {
@@ -543087,6 +544046,13 @@
          }
         ]
        ],
+       "selectmenu-pseudo-open-closed.tentative.html": [
+        "b1400e04265128ab3213a05a22de69ed106b2ac7",
+        [
+         null,
+         {}
+        ]
+       ],
        "selectmenu-required-attribute.tentative.html": [
         "ea6d1b215d721a3ebff22c965dd92c98fe8fb67e",
         [
@@ -548314,14 +549280,14 @@
         ]
        ],
        "disabled.html": [
-        "8808675eb69b17c7763b407ea7ce4458e9e08fda",
+        "f9600439298136e86a6c298e6ae002ab156b4234",
         [
          null,
          {}
         ]
        ],
        "enabled.html": [
-        "0ad0e1b402a2646d41f736271c65d413455a67e2",
+        "1948343c1866263e2d3edb7b6c35e3ab4155f3f0",
         [
          null,
          {}
@@ -558496,6 +559462,15 @@
        }
       ]
      ],
+     "loaf-pause-duration.html": [
+      "e70d0110348bc4a1cfc4a06ea2743a118ba54c72",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
+     ],
      "loaf-promise.html": [
       "5ead569c8aeed27745cb53445d32b58145c776bc",
       [
@@ -561573,7 +562548,7 @@
      ]
     ],
     "MediaRecorder-stop.html": [
-     "73eb2999adb238f49f886d5de0dbe8f5eebae63f",
+     "2b49a4cb6c4796e8645dd2d49e97702c9761da44",
      [
       null,
       {}
@@ -564202,6 +565177,20 @@
        ]
       ]
      },
+     "defaultPrevented-navigation-preempted.html": [
+      "1df4f56c5e4ec5bc48166bd804c9c514b699ae01",
+      [
+       null,
+       {}
+      ]
+     ],
+     "defaultPrevented-window-stop-after-dispatch.html": [
+      "da5de10ddd8ba5753265f7a2b2448915e31cd257",
+      [
+       null,
+       {}
+      ]
+     ],
      "event-constructor.html": [
       "065884240e092c59b3ce2178aa7a8162fdabe0c4",
       [
@@ -564649,6 +565638,20 @@
        {}
       ]
      ],
+     "replaceState-in-unload-then-remove-iframe.html": [
+      "e97b72b15717325b49594382931635574c76f65c",
+      [
+       null,
+       {}
+      ]
+     ],
+     "replaceState-inside-back-handler.html": [
+      "29409b5e2bc3e680cf99f54abea90bcdd5bfd1b2",
+      [
+       null,
+       {}
+      ]
+     ],
      "same-url-replace-cross-document.html": [
       "0a976cd51fdcb3205d2a71cc9dc1a9853e417eee",
       [
@@ -589076,6 +590079,13 @@
        {}
       ]
      ],
+     "animation-range-ignored.html": [
+      "f08659635ea77263aded03ee66a4a4c8c4702862",
+      [
+       null,
+       {}
+      ]
+     ],
      "animation-shorthand.html": [
       "7bd17b9919070006824fee9e77ec5b20e464315b",
       [
@@ -589308,21 +590318,21 @@
       ]
      ],
      "timeline-offset-in-keyframe-change-timeline.tentative.html": [
-      "6456e8aa779da7cec5c149a710ceb6e4a619740d",
+      "5ac54081845605b14ce0558d054a354e0c83fd3e",
       [
        null,
        {}
       ]
      ],
      "timeline-offset-keyframes-hidden-subject.html": [
-      "d3b124ba18e39d4f985895792232ebdea52e20c3",
+      "047acfed33f36adb3afca0655c99e75a707f3976",
       [
        null,
        {}
       ]
      ],
      "timeline-offset-keyframes-with-document-timeline.html": [
-      "95a0ea4eae0cbf1bbe6545047e7d544781fde289",
+      "03ee381fd9276fef5b43d8c519bb1c6af01a690e",
       [
        null,
        {}
@@ -589678,6 +590688,13 @@
        {}
       ]
      ],
+     "get-keyframes-with-timeline-offset.html": [
+      "02f910d04e3316feaaa3512101d12bc9dcfa40f5",
+      [
+       null,
+       {}
+      ]
+     ],
      "inline-view-timeline-current-time.tentative.html": [
       "5b37798fe89035a5eb459ae479fc94ac42a05689",
       [
@@ -589700,7 +590717,7 @@
       ]
      ],
      "view-timeline-get-set-range.html": [
-      "e80ef57afe025c3ff60cc7761c2cf91fe8518346",
+      "6de2d84df73bc7f4e729e342670c803e85e0c27a",
       [
        null,
        {}
@@ -597869,6 +598886,15 @@
        }
       ]
      ],
+     "csp-script-src-strict-dynamic.html": [
+      "5e08877a495578c04f86c6953787e5f64832378f",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
+     ],
      "csp-script-src-unsafe-inline.html": [
       "f6925f59f455df85434de4e582fab4c1c59552fa",
       [
@@ -599582,7 +600608,7 @@
      ]
     ],
     "requestStorageAccess.sub.https.window.js": [
-     "306bf462328acb2da80dd7118f0284aeca6c3e78",
+     "eb8870b774dd5fa7c191dec715c931f94f54cacc",
      [
       "storage-access-api/requestStorageAccess.sub.https.window.html",
       {
@@ -599593,6 +600619,10 @@
         ],
         [
          "script",
+         "/cookies/resources/cookie-helper.sub.js"
+        ],
+        [
+         "script",
          "/resources/testdriver.js"
         ],
         [
@@ -602506,6 +603536,13 @@
        }
       ]
      ],
+     "invalid-realm.window.js": [
+      "57cdfd94862dfe7832164e13eec7bcc4f302c3de",
+      [
+       "streams/transform-streams/invalid-realm.window.html",
+       {}
+      ]
+     ],
      "lipfuzz.any.js": [
       "f9f148aaf1c6a462afb7c93ebef775203315500a",
       [
@@ -607297,7 +608334,7 @@
      ]
     ],
     "Document-execCommand.tentative.html": [
-     "0fd7e644b9ee019d5efcb86dc50ea14de02aa3cf",
+     "7619133655f41f7c5cdcdcea115edaf1e338b977",
      [
       null,
       {}
@@ -607500,7 +608537,7 @@
      ]
     ],
     "TrustedTypePolicyFactory-getPropertyType.tentative.html": [
-     "9c65ef9821b8afd42954d0368a1a338240c20df5",
+     "21aba668ccdc3f10948c199259a848655ac0ae08",
      [
       null,
       {}
@@ -607544,7 +608581,7 @@
      ]
     ],
     "block-Document-execCommand.tentative.html": [
-     "e25b7dd28a2f646293d1abe879d525259db7d187",
+     "87759cdc19716c4c269d13a1bb6e6a4d995b4b7d",
      [
       null,
       {}
@@ -607628,7 +608665,7 @@
      ]
     ],
     "block-text-node-insertion-into-script-element.tentative.html": [
-     "819753652a975247415d85cb77b65ba9a358bfa5",
+     "08e3e695530302c8875d127bc4d36e2085a1a1d4",
      [
       null,
       {}
@@ -607835,7 +608872,7 @@
      ]
     ],
     "trusted-types-from-literal.tentative.html": [
-     "b59c46fe0fed6605d0ef6baf25833dc3e995b841",
+     "a7d5659e16a1471ac5cb900dce7b3a102a14af89",
      [
       null,
       {}
@@ -610296,7 +611333,7 @@
      ]
     ],
     "failure.html": [
-     "67873ea2115738285a74861149d9939352f7429f",
+     "8a408412668fd37408d5787799214aafb2ae0d3c",
      [
       null,
       {
@@ -610384,7 +611421,7 @@
      ]
     ],
     "url-constructor.any.js": [
-     "297b8ffd9eaf378ffebc2d604b73be7d645bb1ae",
+     "bea06d025b718820286d26ea1804fe98c559d2d9",
      [
       "url/url-constructor.any.html?exclude=(file|javascript|mailto)",
       {
@@ -610643,7 +611680,7 @@
      ]
     ],
     "url-origin.any.js": [
-     "9c1f97ed2e59493d807c5d3694ae48c6b6975f5a",
+     "599984c6c17dfe160269058c6780b900c23057ee",
      [
       "url/url-origin.any.html",
       {}
diff --git a/third_party/blink/web_tests/external/wpt/badging/non-fully-active.https-expected.txt b/third_party/blink/web_tests/external/wpt/badging/non-fully-active.https-expected.txt
new file mode 100644
index 0000000..6446290
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/badging/non-fully-active.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL badging a non-fully active document should reject with InvalidStateError assert_unreached: Should have rejected: undefined Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/badging/non-fully-active.https.html b/third_party/blink/web_tests/external/wpt/badging/non-fully-active.https.html
new file mode 100644
index 0000000..d870e52
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/badging/non-fully-active.https.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Badging: attempting to badge non-fully active document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body></body>
+<script>
+promise_test(async t => {
+  const iframe = document.createElement("iframe");
+  document.body.appendChild(iframe);
+  await new Promise(resolve => {
+    iframe.onload = resolve;
+    iframe.src = "about:blank";
+  });
+  const exceptionCtor = iframe.contentWindow.DOMException;
+  const {navigator: nav} = iframe.contentWindow;
+  iframe.remove();
+  return promise_rejects_dom(t, "InvalidStateError", exceptionCtor, nav.setAppBadge(1));
+}, "badging a non-fully active document should reject with InvalidStateError");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/badging/non-fully-active.https.html.ini b/third_party/blink/web_tests/external/wpt/badging/non-fully-active.https.html.ini
new file mode 100644
index 0000000..82e4f77d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/badging/non-fully-active.https.html.ini
@@ -0,0 +1,3 @@
+[non-fully-active.https.html]
+  [badging a non-fully active document should reject with InvalidStateError]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/badging/resources/setAppBadge_iframe.html b/third_party/blink/web_tests/external/wpt/badging/resources/setAppBadge_iframe.html
new file mode 100644
index 0000000..8738099
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/badging/resources/setAppBadge_iframe.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>setAppBadge iframe</title>
+<script>
+  async function callSetAppBadge() {
+    const postMessageData = { message: "callSetAppBadge" };
+
+    try {
+      await navigator.setAppBadge();
+      postMessageData.status = "success";
+    } catch (e) {
+      if (e instanceof DOMException) {
+        postMessageData.status = "error";
+        postMessageData.exceptionType = e.name;
+      } else {
+        postMessageData.status = "unknown_error";
+        postMessageData.error = e.toString();
+      }
+    } finally {
+      window.parent.postMessage(postMessageData, "*");
+    }
+  }
+
+  window.addEventListener("message", async (event) => {
+    switch (event.data) {
+      case "callSetAppBadge":
+        await callSetAppBadge();
+        break;
+      default:
+        throw new Error(`Unexpected message: ${event.data}`);
+    }
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/badging/setAppBadge_cross_origin.sub.https-expected.txt b/third_party/blink/web_tests/external/wpt/badging/setAppBadge_cross_origin.sub.https-expected.txt
new file mode 100644
index 0000000..baeb69a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/badging/setAppBadge_cross_origin.sub.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS Test that navigator.setAppBadge is available
+FAIL Test that calling setAppBadge in a cross-origin iframe throws a SecurityError assert_equals: setAppBadge should have rejected with an error expected "error" but got "success"
+PASS Test that calling setAppBadge in a same-origin iframe succeeds
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/badging/setAppBadge_cross_origin.sub.https.html b/third_party/blink/web_tests/external/wpt/badging/setAppBadge_cross_origin.sub.https.html
new file mode 100644
index 0000000..7e54887
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/badging/setAppBadge_cross_origin.sub.https.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Test cross-origin and same-origin use of setAppBadge</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe id="testIframe"></iframe>
+<script>
+  const iframe = document.getElementById("testIframe");
+
+  function sendMessageToIframe(message) {
+    return new Promise((resolve) => {
+      window.addEventListener("message", function listener(event) {
+        const { messageId } = event.data;
+        if (event.data.message !== message) return;
+        window.removeEventListener("message", listener);
+        resolve(event);
+      });
+      iframe.contentWindow.postMessage("callSetAppBadge", "*");
+    });
+  }
+
+  function loadIframe(src) {
+    return new Promise((resolve) => {
+      iframe.addEventListener("load", resolve);
+      iframe.src = src;
+    });
+  }
+
+  test(() => {
+    assert_true(
+      "setAppBadge" in navigator,
+      "navigator.setAppBadge should be available"
+    );
+  }, "Test that navigator.setAppBadge is available");
+
+  promise_test(async () => {
+    await loadIframe(
+      `https://{{hosts[][]}}:{{ports[https][1]}}/badging/resources/setAppBadge_iframe.html`
+    );
+    const event = await sendMessageToIframe("callSetAppBadge");
+    const { exceptionType, status } = event.data;
+    assert_equals(
+      status,
+      "error",
+      "setAppBadge should have rejected with an error"
+    );
+    assert_equals(
+      exceptionType,
+      "SecurityError",
+      "setAppBadge should throw a SecurityError when called in a cross-origin iframe"
+    );
+  }, "Test that calling setAppBadge in a cross-origin iframe throws a SecurityError");
+
+  promise_test(async () => {
+    await loadIframe("./resources/setAppBadge_iframe.html");
+    const event = await sendMessageToIframe("callSetAppBadge");
+    const { status } = event.data;
+    assert_equals(
+      status,
+      "success",
+      "setAppBadge should succeed when called in a same-origin iframe"
+    );
+  }, "Test that calling setAppBadge in a same-origin iframe succeeds");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/badging/setAppBadge_cross_origin.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/badging/setAppBadge_cross_origin.sub.https.html.ini
new file mode 100644
index 0000000..f268ea0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/badging/setAppBadge_cross_origin.sub.https.html.ini
@@ -0,0 +1,3 @@
+[setAppBadge_cross_origin.sub.https.html]
+  [Test that calling setAppBadge in a cross-origin iframe throws a SecurityError]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/scope-nesting.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/scope-nesting.html
index f9d8905..34a13a1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-cascade/scope-nesting.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/scope-nesting.html
@@ -117,4 +117,54 @@
   assert_equals(getComputedStyle(inner1).zIndex, 'auto');
   assert_equals(getComputedStyle(inner2).zIndex, '1');
 }, 'Nesting-selector in the scope\'s <stylesheet>');
+</script>
+
+<template id=test_parent_in_pseudo_scope>
+  <div>
+    <style>
+      @scope (#div) {
+        :scope {
+          z-index: 1;
+          & {
+            z-index: 2;
+          }
+        }
+      }
+    </style>
+    <div id=div></div>
+  </div>
+</template>
+<script>
+test((t) => {
+  t.add_cleanup(() => main.replaceChildren());
+  main.append(test_parent_in_pseudo_scope.content.cloneNode(true));
+
+  assert_equals(getComputedStyle(div).zIndex, '2');
+}, 'Nesting-selector within :scope rule');
+</script>
+
+<template id=test_parent_in_pseudo_scope_double>
+  <div>
+    <style>
+      @scope (#div) {
+        :scope {
+          z-index: 1;
+          & {
+            & {
+              z-index: 2;
+            }
+          }
+        }
+      }
+    </style>
+    <div id=div></div>
+  </div>
+</template>
+<script>
+test((t) => {
+  t.add_cleanup(() => main.replaceChildren());
+  main.append(test_parent_in_pseudo_scope_double.content.cloneNode(true));
+
+  assert_equals(getComputedStyle(div).zIndex, '2');
+}, 'Nesting-selector within :scope rule (double nested)');
 </script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path-svg-content/clip-path-shape-circle-003.svg b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path-svg-content/clip-path-shape-circle-003.svg
index f0110ee..0a0432c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path-svg-content/clip-path-shape-circle-003.svg
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path-svg-content/clip-path-shape-circle-003.svg
@@ -5,10 +5,11 @@
 	<html:link rel="help" href="http://www.w3.org/TR/css-masking-1/#svg-clipping-paths"/>
 	<html:link rel="help" href="http://www.w3.org/TR/css-masking-1/#the-clip-path"/>
 	<html:link rel="match" href="reference/clip-path-circle-001-ref.svg" />
+	<html:meta name="fuzzy" content="maxDifference=0-64; totalPixels=0-184"/>
 	<metadata class="flags">svg</metadata>
 	<desc class="assert">A basic shape function circle() applied to an SVG
 	rectangle. The specified keyword fill-box defines the reference box
 	(here objectBoundingBox). You should see a full green circle.</desc>
 </g>
 <rect width="100" height="100" fill="green" stroke="green" stroke-width="10" style="clip-path: circle() fill-box;"/>
-</svg>
\ No newline at end of file
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path-svg-content/clip-path-shape-circle-004.svg b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path-svg-content/clip-path-shape-circle-004.svg
index c3db6d6..044b2ecc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path-svg-content/clip-path-shape-circle-004.svg
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path-svg-content/clip-path-shape-circle-004.svg
@@ -5,10 +5,11 @@
 	<html:link rel="help" href="http://www.w3.org/TR/css-masking-1/#svg-clipping-paths"/>
 	<html:link rel="help" href="http://www.w3.org/TR/css-masking-1/#the-clip-path"/>
 	<html:link rel="match" href="reference/clip-path-circle-001-ref.svg" />
+	<html:meta name="fuzzy" content="maxDifference=0-64; totalPixels=0-76"/>
 	<metadata class="flags">svg</metadata>
 	<desc class="assert">A basic shape function circle() applied to an SVG
 	rectangle. The specified keyword stroke-box defines the reference box
 	stroking bounding box. You should see a full green circle.</desc>
 </g>
 <rect x="10" y="10" width="80" height="80" fill="green" stroke="green" stroke-width="20" style="clip-path: circle() stroke-box;"/>
-</svg>
\ No newline at end of file
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/part-mutation-pseudo.html b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/part-mutation-pseudo.html
new file mode 100644
index 0000000..d0e0072d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/part-mutation-pseudo.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Shadow Parts - Invalidation Change Part Name on pseudo</title>
+<link rel="help" href="https://drafts.csswg.org/css-shadow-parts/">
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/shadow-helper.js"></script>
+<style>#c-e::part(partp)::before { color: red; }</style>
+<script>installCustomElement("custom-element", "custom-element-template");</script>
+<template id="custom-element-template">
+  <style>span::before { content: ""; color: green; }</style>
+  <span id="part" part="partp">This text</span>
+</template>
+The following text should be green:
+<div><custom-element id="c-e"></custom-element></div>
+<script>
+  "use strict";
+  test(function() {
+    const part = getElementByShadowIds(document, ["c-e", "part"]);
+    const before = getComputedStyle(part, "::before").color;
+    part.setAttribute("part", "somethingelse");
+    const after = getComputedStyle(part, "::before").color;
+    assert_not_equals(before, after);
+  }, "Part in selected host changed color");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-computed.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-computed.html
new file mode 100644
index 0000000..506e257
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-computed.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Text: getComputedStyle().whiteSpace</title>
+<link rel="help" href="https://www.w3.org/TR/css-text-3/#propdef-white-space">
+<meta name="assert" content="white-space computed value is specified keyword.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_computed_value("white-space-collapse", "collapse");
+test_computed_value("white-space-collapse", "preserve");
+test_computed_value("white-space-collapse", "preserve-breaks");
+test_computed_value("white-space-collapse", "break-spaces");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-computed.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-computed.html.ini
new file mode 100644
index 0000000..6b697c30
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-computed.html.ini
@@ -0,0 +1,12 @@
+[white-space-collapse-computed.html]
+  [Property white-space-collapse value 'break-spaces']
+    expected: FAIL
+
+  [Property white-space-collapse value 'collapse']
+    expected: FAIL
+
+  [Property white-space-collapse value 'preserve']
+    expected: FAIL
+
+  [Property white-space-collapse value 'preserve-breaks']
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-invalid copy.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-invalid copy.html
new file mode 100644
index 0000000..6c18ece
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-invalid copy.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Text Module Test: parsing text-wrap with invalid values</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap">
+<meta name="assert" content="text-wrap supports only the grammar 'wrap | nowrap | balance | stable | pretty'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value("white-space-collapse", "auto");
+test_invalid_value("white-space-collapse", "none");
+test_invalid_value("white-space-collapse", "collapse preserve");
+test_invalid_value("white-space-collapse", "preserve preserve-breaks");
+test_invalid_value("white-space-collapse", "delicious collapse");
+test_invalid_value("white-space-collapse", "5px");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-valid.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-valid.html
new file mode 100644
index 0000000..2191167
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-valid.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Text Module Test: parsing text-wrap with valid values</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap">
+<meta name="assert" content="text-wrap supports the full grammar 'wrap | nowrap | balance | stable | pretty'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value("white-space-collapse", "collapse");
+test_valid_value("white-space-collapse", "preserve");
+test_valid_value("white-space-collapse", "preserve-breaks");
+test_valid_value("white-space-collapse", "break-spaces");
+test_valid_value("white-space-collapse", "initial");
+test_valid_value("white-space-collapse", "inherit");
+test_valid_value("white-space-collapse", "unset");
+test_valid_value("white-space-collapse", "revert");
+test_valid_value("white-space-collapse", "revert-layer");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-valid.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-valid.html.ini
new file mode 100644
index 0000000..6e8383f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-collapse-valid.html.ini
@@ -0,0 +1,27 @@
+[white-space-collapse-valid.html]
+  [e.style['white-space-collapse'\] = "break-spaces" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space-collapse'\] = "collapse" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space-collapse'\] = "inherit" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space-collapse'\] = "initial" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space-collapse'\] = "preserve" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space-collapse'\] = "preserve-breaks" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space-collapse'\] = "revert" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space-collapse'\] = "revert-layer" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space-collapse'\] = "unset" should set the property value]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-white-space-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand-text-wrap.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-white-space-001.html
rename to third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand-text-wrap.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html
new file mode 100644
index 0000000..518f81fd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<title>CSS Text Module Test: parsing white-space as a shorthand</title>
+<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#propdef-white-space">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+<div id="target"></div>
+<script>
+function test_valid_and_computed_value(property, specified, serialized) {
+  test_valid_value(property, specified, serialized);
+  test_computed_value(property, specified, serialized);
+}
+
+test_valid_and_computed_value("white-space", "collapse", "normal");
+test_valid_and_computed_value("white-space", "wrap", "normal");
+test_valid_and_computed_value("white-space", "collapse wrap", "normal");
+test_valid_and_computed_value("white-space", "wrap collapse", "normal");
+
+test_valid_and_computed_value("white-space", "preserve nowrap", "pre");
+test_valid_and_computed_value("white-space", "nowrap preserve", "pre");
+
+test_valid_and_computed_value("white-space", "nowrap", "nowrap");
+test_valid_and_computed_value("white-space", "collapse nowrap", "nowrap");
+test_valid_and_computed_value("white-space", "nowrap collapse", "nowrap");
+
+test_valid_and_computed_value("white-space", "preserve", "pre-wrap");
+test_valid_and_computed_value("white-space", "preserve wrap", "pre-wrap");
+test_valid_and_computed_value("white-space", "wrap preserve", "pre-wrap");
+
+test_valid_and_computed_value("white-space", "break-spaces", "break-spaces");
+test_valid_and_computed_value("white-space", "break-spaces wrap", "break-spaces");
+test_valid_and_computed_value("white-space", "wrap break-spaces", "break-spaces");
+
+test_valid_and_computed_value("white-space", "preserve-breaks", "pre-line");
+test_valid_and_computed_value("white-space", "preserve-breaks wrap", "pre-line");
+test_valid_and_computed_value("white-space", "wrap preserve-breaks", "pre-line");
+
+// Combinations of existing values that are not pre-defined.
+test_valid_and_computed_value("white-space", "preserve-breaks nowrap", "preserve-breaks nowrap");
+test_valid_and_computed_value("white-space", "nowrap preserve-breaks", "preserve-breaks nowrap");
+
+// Values not used in the pre-defined set.
+test_valid_and_computed_value("white-space", "balance", "balance");
+test_valid_and_computed_value("white-space", "collapse balance", "balance");
+test_valid_and_computed_value("white-space", "balance collapse", "balance");
+test_valid_and_computed_value("white-space", "preserve balance", "preserve balance");
+test_valid_and_computed_value("white-space", "balance preserve", "preserve balance");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html.ini
new file mode 100644
index 0000000..7534924
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html.ini
@@ -0,0 +1,138 @@
+[white-space-shorthand.html]
+  [Property white-space value 'balance collapse']
+    expected: FAIL
+
+  [Property white-space value 'balance preserve']
+    expected: FAIL
+
+  [Property white-space value 'balance']
+    expected: FAIL
+
+  [Property white-space value 'break-spaces wrap']
+    expected: FAIL
+
+  [Property white-space value 'collapse balance']
+    expected: FAIL
+
+  [Property white-space value 'collapse nowrap']
+    expected: FAIL
+
+  [Property white-space value 'collapse wrap']
+    expected: FAIL
+
+  [Property white-space value 'collapse']
+    expected: FAIL
+
+  [Property white-space value 'nowrap collapse']
+    expected: FAIL
+
+  [Property white-space value 'nowrap preserve']
+    expected: FAIL
+
+  [Property white-space value 'nowrap preserve-breaks']
+    expected: FAIL
+
+  [Property white-space value 'preserve balance']
+    expected: FAIL
+
+  [Property white-space value 'preserve nowrap']
+    expected: FAIL
+
+  [Property white-space value 'preserve wrap']
+    expected: FAIL
+
+  [Property white-space value 'preserve']
+    expected: FAIL
+
+  [Property white-space value 'preserve-breaks nowrap']
+    expected: FAIL
+
+  [Property white-space value 'preserve-breaks wrap']
+    expected: FAIL
+
+  [Property white-space value 'preserve-breaks']
+    expected: FAIL
+
+  [Property white-space value 'wrap break-spaces']
+    expected: FAIL
+
+  [Property white-space value 'wrap collapse']
+    expected: FAIL
+
+  [Property white-space value 'wrap preserve']
+    expected: FAIL
+
+  [Property white-space value 'wrap preserve-breaks']
+    expected: FAIL
+
+  [Property white-space value 'wrap']
+    expected: FAIL
+
+  [e.style['white-space'\] = "balance collapse" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "balance preserve" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "balance" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "break-spaces wrap" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "collapse balance" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "collapse nowrap" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "collapse wrap" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "collapse" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "nowrap collapse" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "nowrap preserve" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "nowrap preserve-breaks" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "preserve balance" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "preserve nowrap" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "preserve wrap" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "preserve" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "preserve-breaks nowrap" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "preserve-breaks wrap" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "preserve-breaks" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "wrap break-spaces" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "wrap collapse" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "wrap preserve" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "wrap preserve-breaks" should set the property value]
+    expected: FAIL
+
+  [e.style['white-space'\] = "wrap" should set the property value]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-016.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-016.html.ini
index 76a85b1..8c55319 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-016.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-016.html.ini
@@ -1,4 +1,5 @@
 [text-transform-capitalize-016.html]
   expected:
-    if (product == "content_shell") and (os == "mac"): FAIL
-    if (product == "content_shell") and (os == "linux"): FAIL
+    if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
+    if product == "chrome": PASS
+    FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-bottom-left-radius-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-bottom-left-radius-001.html.ini
new file mode 100644
index 0000000..6f8cad0d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-bottom-left-radius-001.html.ini
@@ -0,0 +1,3 @@
+[kind-of-widget-fallback-color-input-border-bottom-left-radius-001.html]
+  expected:
+    if (product == "content_shell") and (os == "linux"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-right-radius-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-right-radius-001.html.ini
new file mode 100644
index 0000000..71e29e55
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-right-radius-001.html.ini
@@ -0,0 +1,3 @@
+[kind-of-widget-fallback-input-search-border-top-right-radius-001.html]
+  expected:
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-background-image-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-background-image-001.html.ini
new file mode 100644
index 0000000..11937e9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-background-image-001.html.ini
@@ -0,0 +1,3 @@
+[kind-of-widget-fallback-input-search-text-background-image-001.html]
+  expected:
+    if (product == "content_shell") and (os == "linux"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-border-end-end-radius-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-border-end-end-radius-001.html.ini
index 535207b..697b05b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-border-end-end-radius-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-border-end-end-radius-001.html.ini
@@ -1,3 +1,4 @@
 [kind-of-widget-fallback-input-search-text-border-end-end-radius-001.html]
   expected:
     if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL
+    if (product == "content_shell") and (os == "linux"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-block-start-style-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-block-start-style-001.html.ini
new file mode 100644
index 0000000..3e272ca8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-block-start-style-001.html.ini
@@ -0,0 +1,3 @@
+[kind-of-widget-fallback-textarea-border-block-start-style-001.html]
+  expected:
+    if (product == "content_shell") and (os == "mac"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length-expected.txt
index 56ac7ee..4c24f699 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length-expected.txt
@@ -33,5 +33,9 @@
 PASS 'calc(1px * clamp(0, NaN, 10))' as a specified value should serialize as 'calc(NaN * 1px)'.
 PASS 'calc(1px * clamp(-Infinity, 0, infinity))' as a specified value should serialize as 'calc(0px)'.
 PASS 'calc(1px * clamp(-inFinity, infinity, 10))' as a specified value should serialize as 'calc(10px)'.
+FAIL 'calc(1 * min(NaN * 1pt, NaN * 1cm))' as a specified value should serialize as 'calc(NaN * 1px)'. assert_equals: 'calc(1 * min(NaN * 1pt, NaN * 1cm))' and 'calc(NaN * 1px)' should serialize the same in specified values. expected "calc(NaN * 1px)" but got "calc(1 * min(NaN * 1pt, NaN * 1cm))"
+FAIL 'calc(1 * max(NaN * 1cm, NaN * 2Q))' as a specified value should serialize as 'calc(NaN * 1px)'. assert_equals: 'calc(1 * max(NaN * 1cm, NaN * 2Q))' and 'calc(NaN * 1px)' should serialize the same in specified values. expected "calc(NaN * 1px)" but got "calc(1 * max(NaN * 1cm, NaN * 1q))"
+FAIL 'calc(1 * min(NaN * 2px, NaN * 4em))' as a specified value should serialize as 'min(NaN * 1px, NaN * 1em)'. assert_equals: 'calc(1 * min(NaN * 2px, NaN * 4em))' and 'min(NaN * 1px, NaN * 1em)' should serialize the same in specified values. expected "min(NaN * 1px, NaN * 1em)" but got "calc(1 * min(NaN * 1px, NaN * 1em))"
+FAIL 'calc(1 * clamp(NaN * 2em, NaN * 4px, NaN * 8pt))' as a specified value should serialize as 'clamp(NaN * 1em, NaN * 1px, NaN * 1px)'. assert_equals: 'calc(1 * clamp(NaN * 2em, NaN * 4px, NaN * 8pt))' and 'clamp(NaN * 1em, NaN * 1px, NaN * 1px)' should serialize the same in specified values. expected "clamp(NaN * 1em, NaN * 1px, NaN * 1px)" but got "calc(1 * clamp(NaN * 1em, NaN * 1px, NaN * 1pt))"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length.html b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length.html
index e08e050..f0ae4367 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length.html
@@ -51,6 +51,11 @@
 
     "1px * clamp(-Infinity, 0, infinity)"           :"calc(0px)",
     "1px * clamp(-inFinity, infinity, 10)"          :"calc(10px)",
+
+    "1 * min(NaN * 1pt, NaN * 1cm)"                 :"calc(NaN * 1px)",
+    "1 * max(NaN * 1cm, NaN * 2Q)"                  :"calc(NaN * 1px)",
+    "1 * min(NaN * 2px, NaN * 4em)"                 :"min(NaN * 1px, NaN * 1em)",
+    "1 * clamp(NaN * 2em, NaN * 4px, NaN * 8pt)"    :"clamp(NaN * 1em, NaN * 1px, NaN * 1px)",
 };
 
 for (var exp in test_map) {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length.html.ini b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length.html.ini
index 342fa6e1..944e180f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-length.html.ini
@@ -2,12 +2,24 @@
   ['calc(1 * clamp(-INFINITY*20px, 0px, infiniTY*10px))' as a specified value should serialize as 'calc(0px)'.]
     expected: FAIL
 
+  ['calc(1 * clamp(NaN * 2em, NaN * 4px, NaN * 8pt))' as a specified value should serialize as 'clamp(NaN * 1em, NaN * 1px, NaN * 1px)'.]
+    expected: FAIL
+
   ['calc(1 * max(INFinity*3px, 0px))' as a specified value should serialize as 'calc(infinity * 1px)'.]
     expected: FAIL
 
+  ['calc(1 * max(NaN * 1cm, NaN * 2Q))' as a specified value should serialize as 'calc(NaN * 1px)'.]
+    expected: FAIL
+
   ['calc(1 * max(nAn*2px, 0px))' as a specified value should serialize as 'calc(NaN * 1px)'.]
     expected: FAIL
 
+  ['calc(1 * min(NaN * 1pt, NaN * 1cm))' as a specified value should serialize as 'calc(NaN * 1px)'.]
+    expected: FAIL
+
+  ['calc(1 * min(NaN * 2px, NaN * 4em))' as a specified value should serialize as 'min(NaN * 1px, NaN * 1em)'.]
+    expected: FAIL
+
   ['calc(1 * min(inFInity*4px, 0px))' as a specified value should serialize as 'calc(0px)'.]
     expected: FAIL
 
@@ -29,29 +41,5 @@
   ['calc(1pt * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'.]
     expected: FAIL
 
-  ['calc(1px * clamp(-Infinity, 0, infinity))' as a specified value should serialize as 'calc(0px)'.]
-    expected: FAIL
-
-  ['calc(1px * clamp(-inFinity, infinity, 10))' as a specified value should serialize as 'calc(10px)'.]
-    expected: FAIL
-
-  ['calc(1px * clamp(0, 10, NaN))' as a specified value should serialize as 'calc(NaN * 1px)'.]
-    expected: FAIL
-
-  ['calc(1px * clamp(0, NaN, 10))' as a specified value should serialize as 'calc(NaN * 1px)'.]
-    expected: FAIL
-
-  ['calc(1px * clamp(NaN, 0, 10))' as a specified value should serialize as 'calc(NaN * 1px)'.]
-    expected: FAIL
-
-  ['calc(1px * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN * 1px)'.]
-    expected: FAIL
-
-  ['calc(1px * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN * 1px)'.]
-    expected: FAIL
-
-  ['calc(1px * max(NaN, min(0,10)))' as a specified value should serialize as 'calc(NaN * 1px)'.]
-    expected: FAIL
-
   ['calc(1q * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'.]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-001-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-001-print-ref.html
new file mode 100644
index 0000000..9edc5d9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-001-print-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="height:150vh;"></div>
+This text should be at the middle of the second page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-001-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-001-print.html
new file mode 100644
index 0000000..f4121c3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-001-print.html
@@ -0,0 +1,9 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-001-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="height:150vh; contain:size;"></div>
+This text should be at the middle of the second page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-002-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-002-print-ref.html
new file mode 100644
index 0000000..5478362b0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-002-print-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="height:250vh;"></div>
+This text should be at the middle of the third page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-002-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-002-print.html
new file mode 100644
index 0000000..8f76af1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-002-print.html
@@ -0,0 +1,9 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-002-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="height:250vh; contain:size;"></div>
+This text should be at the middle of the third page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-003-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-003-print.html
new file mode 100644
index 0000000..76905b180
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-003-print.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=1402540">
+<link rel="match" href="reference/monolithic-overflow-4-pages-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="background:yellow;">
+  <div style="contain:size; width:50px; height:350vh; background:hotpink;"></div>
+  Yellow background, page 4.
+</div>
+White background, page 4. There should be a hotpink rectangle inside a yellow
+block, starting at the first page, and ending right before the first piece of
+text.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-004-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-004-print.html
new file mode 100644
index 0000000..ea5a659b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-004-print.html
@@ -0,0 +1,16 @@
+<!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=1402540">
+<link rel="match" href="reference/monolithic-overflow-4-pages-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="height:390vh;">
+  <div style="background:yellow;">
+    <div style="contain:size; width:50px; height:350vh; background:hotpink;"></div>
+    Yellow background, page 4.
+  </div>
+  White background, page 4. There should be a hotpink rectangle inside a yellow
+  block, starting at the first page, and ending right before the first piece of
+  text.
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-005-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-005-print.html
new file mode 100644
index 0000000..bb0fc21
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-005-print.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=1402540">
+<link rel="match" href="reference/monolithic-overflow-4-pages-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:flex; flex-flow:column; background:yellow;">
+  <div style="contain:size; height:350vh; width:50px; background:hotpink;"></div>
+  Yellow background, page 4.
+</div>
+White background, page 4. There should be a hotpink rectangle inside a yellow
+block, starting at the first page, and ending right before the first piece of
+text.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-006-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-006-print.html
new file mode 100644
index 0000000..1cbcdbbe
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-006-print.html
@@ -0,0 +1,16 @@
+<!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=1402540">
+<link rel="match" href="reference/monolithic-overflow-4-pages-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:flex; flex-flow:column; background:yellow;">
+  <div>
+    <div style="contain:size; height:350vh; width:50px; background:hotpink;"></div>
+    Yellow background, page 4.
+  </div>
+</div>
+White background, page 4. There should be a hotpink rectangle inside a yellow
+block, starting at the first page, and ending right before the first piece of
+text.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-007-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-007-print.html
new file mode 100644
index 0000000..14a6f051
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-007-print.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=1402540">
+<link rel="match" href="reference/monolithic-overflow-4-pages-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:grid; background:yellow;">
+  <div style="contain:size; height:350vh; width:50px; background:hotpink;"></div>
+  Yellow background, page 4.
+</div>
+White background, page 4. There should be a hotpink rectangle inside a yellow
+block, starting at the first page, and ending right before the first piece of
+text.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-008-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-008-print.html
new file mode 100644
index 0000000..ff302dc
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-008-print.html
@@ -0,0 +1,16 @@
+<!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=1402540">
+<link rel="match" href="reference/monolithic-overflow-4-pages-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:grid; background:yellow;">
+  <div>
+    <div style="contain:size; height:350vh; width:50px; background:hotpink;"></div>
+    Yellow background, page 4.
+  </div>
+</div>
+White background, page 4. There should be a hotpink rectangle inside a yellow
+block, starting at the first page, and ending right before the first piece of
+text.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-009-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-009-print.html
new file mode 100644
index 0000000..bdff66e7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-009-print.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=1402540">
+<link rel="match" href="reference/monolithic-overflow-4-pages-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:table; width:100%; background:yellow;">
+  <div style="contain:size; height:350vh; width:50px; background:hotpink;"></div>
+  Yellow background, page 4.
+</div>
+White background, page 4. There should be a hotpink rectangle inside a yellow
+block, starting at the first page, and ending right before the first piece of
+text.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-010-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-010-print.html
new file mode 100644
index 0000000..a75c932
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-010-print.html
@@ -0,0 +1,16 @@
+<!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=1402540">
+<link rel="match" href="reference/monolithic-overflow-4-pages-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:table; width:100%; background:yellow;">
+  <div style="display:table-row;">
+    <div style="contain:size; height:350vh; width:50px; background:hotpink;"></div>
+  </div>
+  Yellow background, page 4.
+</div>
+White background, page 4. There should be a hotpink rectangle inside a yellow
+block, starting at the first page, and ending right before the first piece of
+text.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-011-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-011-print.html
new file mode 100644
index 0000000..973a3aff
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-011-print.html
@@ -0,0 +1,16 @@
+<!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=1402540">
+<link rel="match" href="reference/monolithic-overflow-4-pages-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:table; width:100%; background:yellow;">
+  <div style="display:table-row-group;">
+    <div style="contain:size; height:350vh; width:50px; background:hotpink;"></div>
+  </div>
+  Yellow background, page 4.
+</div>
+White background, page 4. There should be a hotpink rectangle inside a yellow
+block, starting at the first page, and ending right before the first piece of
+text.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-012-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-012-print-ref.html
new file mode 100644
index 0000000..e47ca880
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-012-print-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="background:yellow;">
+  <div style="width:50px; height:350vh; background:hotpink;"></div>
+  This text should be at the middle of the fourth page.
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-012-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-012-print.html
new file mode 100644
index 0000000..53ed74bc
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-012-print.html
@@ -0,0 +1,11 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-012-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="float:left; width:100%; background:yellow;">
+  <div style="contain:size; width:50px; height:350vh; background:hotpink;"></div>
+  This text should be at the middle of the fourth page.
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-013-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-013-print-ref.html
new file mode 100644
index 0000000..e47ca880
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-013-print-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="background:yellow;">
+  <div style="width:50px; height:350vh; background:hotpink;"></div>
+  This text should be at the middle of the fourth page.
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-013-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-013-print.html
new file mode 100644
index 0000000..b9a1748
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-013-print.html
@@ -0,0 +1,11 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-013-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="position:absolute; width:100%; background:yellow;">
+  <div style="contain:size; width:50px; height:350vh; background:hotpink;"></div>
+  This text should be at the middle of the fourth page.
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-014-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-014-print-ref.html
new file mode 100644
index 0000000..a74e0d19
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-014-print-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:flow-root; background:yellow;">
+  <div style="float:left; width:50px; height:350vh; background:hotpink;"></div>
+  &nbsp;On the first page
+</div>
+This text should be at the middle of the fourth page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-014-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-014-print.html
new file mode 100644
index 0000000..d12ddf4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-014-print.html
@@ -0,0 +1,12 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-014-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="background:yellow;">
+  <div style="display:inline-block; vertical-align:top; width:50px; height:350vh; background:hotpink;"></div>
+  On the first page
+</div>
+This text should be at the middle of the fourth page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-015-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-015-print-ref.html
new file mode 100644
index 0000000..db44a3e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-015-print-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="width:50px; height:350vh; background:hotpink;"></div>
+This text should be at the middle of the fourth page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-015-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-015-print.html
new file mode 100644
index 0000000..d526056
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-015-print.html
@@ -0,0 +1,9 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-015-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:inline-block; vertical-align:top; width:50px; height:350vh; background:hotpink;"></div><br>
+This text should be at the middle of the fourth page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-016-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-016-print-ref.html
new file mode 100644
index 0000000..a675fb96
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-016-print-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body {
+    margin: 0;
+    line-height: 20px;
+  }
+</style>
+<div style="position:absolute; top:100vh;">header</div>
+<div style="position:absolute; top:200vh;">header</div>
+<div style="position:absolute; top:300vh;">header</div>
+<div style="position:absolute; bottom:0;">footer</div>
+<div style="position:absolute; bottom:-100vh;">footer</div>
+<div style="position:absolute; bottom:-200vh;">footer</div>
+<div style="width:80%; padding-bottom:5px; background:hotpink;">
+  header
+  <div style="height:320vh; padding:3px; background:cyan;"></div>
+  On the fourth page, right after a cyan box.<br>
+  footer
+</div>
+Right after the hotpink box. Still fourth page.<br>
+Each page should have a header and footer.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-016-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-016-print.html
new file mode 100644
index 0000000..029523e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-016-print.html
@@ -0,0 +1,18 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-016-print-ref.html">
+<style>
+  body {
+    margin: 0;
+    line-height: 20px;
+  }
+</style>
+<div style="display:table; width:80%; padding-bottom:5px; background:hotpink;">
+  <div style="display:table-header-group; break-inside:avoid;">header</div>
+  <div style="display:table-footer-group; break-inside:avoid;">footer</div>
+  <div style="contain:size; height:320vh; padding:3px; background:cyan;"></div>
+  On the fourth page, right after a cyan box.
+</div>
+Right after the hotpink box. Still fourth page.<br>
+Each page should have a header and footer.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-017-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-017-print-ref.html
new file mode 100644
index 0000000..45f8397
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-017-print-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="line-height:20px;">
+  <div style="position:absolute; width:100%; bottom:0; background:hotpink;">footer</div>
+  <div style="position:absolute; width:100%; bottom:-100vh; background:hotpink;">footer</div>
+  <div style="position:absolute; width:100%; bottom:-200vh; background:hotpink;">footer</div>
+  <div style="height:calc(300vh - 25px); background:black;"></div>
+  <div style="break-before:page;">PASS</div>
+  <div style="background:hotpink;">
+    footer
+  </div>
+</div>
+There should be a footer on every page, and the word PASS should be seen here,
+on the fourth page, just above the final footer.<br>
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-017-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-017-print.html
new file mode 100644
index 0000000..c8ce906
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-017-print.html
@@ -0,0 +1,15 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-017-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="display:table; width:100%; line-height:20px;">
+  <div style="display:table-footer-group; break-inside:avoid; background:hotpink;">footer</div>
+  <!-- Monolithic content that ends 5px above the table footer on the third page. -->
+  <div style="contain:size; height:calc(300vh - 25px); background:black;"></div>
+  PASS
+</div>
+There should be a footer on every page, and the word PASS should be seen here,
+on the fourth page, just above the final footer.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-018-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-018-print-ref.html
new file mode 100644
index 0000000..cf31737
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-018-print-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="width:20px; height:280vh; background:blue;"></div>
+<div style="break-before:page; width:50vh; height:50vh; background:green;"></div>
+There should be four pages. There should be something blue on the first three,
+and a green square on the fourth. No red anywhere.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-018-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-018-print.html
new file mode 100644
index 0000000..93da11d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-018-print.html
@@ -0,0 +1,13 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-018-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="contain:size; width:20px; height:280vh; background:blue;"></div>
+<div style="width:50vh; background:red;">
+  <div style="contain:size; height:50vh; background:green;"></div>
+</div>
+There should be four pages. There should be something blue on the first three,
+and a green square on the fourth. No red anywhere.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-019-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-019-print-ref.html
new file mode 100644
index 0000000..f37740a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-019-print-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="height:50vh; border:solid; background:yellow;">
+  <div style="width:50%; height:350vh; background:cyan;"></div>
+  This text should be at the middle of the fourth page.
+</div>
+This text should be at the middle of the first page, overlapping with stuff.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-019-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-019-print.html
new file mode 100644
index 0000000..3740b5d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-019-print.html
@@ -0,0 +1,12 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-019-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<div style="height:50vh; border:solid; background:yellow;">
+  <div style="contain:size; width:50%; height:350vh; background:cyan;"></div>
+  This text should be at the middle of the fourth page.
+</div>
+This text should be at the middle of the first page, overlapping with stuff.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-020-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-020-print-ref.html
new file mode 100644
index 0000000..528c498
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-020-print-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="float:right; width:20%; border:3px solid;">
+  <div style="width:50%; height:calc(100vh - 3px); background:brown;"></div>
+  <div style="width:50%; height:100vh; background:blue;"></div>
+  <div style="width:50%; height:50vh; background:cyan;"></div>
+</div>
+<div style="background:yellow;">
+  <div style="width:20%; height:225vh; background:hotpink;"></div>
+  <div style="height:75vh;"></div>
+</div>
+This text should start on the fourth page. The first three pages should have a
+yellow background. On the left hand side there should be a hotpink rectangle,
+starting at the beginning on the first page, and ending 25% from the top of the
+third page. On the right hand side there should a figure with a black border. It
+should end around the middle of the third page. Inside there should be a brown
+rectangle on the first page, a blue rectangle on the second page, and a cyan
+rectangle on the third page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-020-print.html b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-020-print.html
new file mode 100644
index 0000000..403d932
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/monolithic-overflow-020-print.html
@@ -0,0 +1,25 @@
+<!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=1402540">
+<link rel="match" href="monolithic-overflow-020-print-ref.html">
+<style>
+  body { margin: 0; }
+</style>
+<!-- Check that monolithic overflow doesn't disrupt layout of a sibling
+     float. -->
+<div style="float:right; width:20%; border:3px solid;">
+  <div style="width:50%; height:calc(100vh - 3px); background:brown;"></div>
+  <div style="width:50%; height:100vh; background:blue;"></div>
+  <div style="width:50%; height:50vh; background:cyan;"></div>
+</div>
+<div style="background:yellow;">
+  <div style="contain:size; width:20%; height:225vh; background:hotpink;"></div>
+  <div style="height:75vh;"></div>
+</div>
+This text should start on the fourth page. The first three pages should have a
+yellow background. On the left hand side there should be a hotpink rectangle,
+starting at the beginning on the first page, and ending 25% from the top of the
+third page. On the right hand side there should a figure with a black border. It
+should end around the middle of the third page. Inside there should be a brown
+rectangle on the first page, a blue rectangle on the second page, and a cyan
+rectangle on the third page.
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/reference/monolithic-overflow-4-pages-print-ref.html b/third_party/blink/web_tests/external/wpt/css/printing/reference/monolithic-overflow-4-pages-print-ref.html
new file mode 100644
index 0000000..c115782
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/printing/reference/monolithic-overflow-4-pages-print-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<style>
+  body { margin: 0; }
+</style>
+<div style="background:yellow;">
+  <div style="width:50px; height:350vh; background:hotpink;"></div>
+  Yellow background, page 4.
+</div>
+White background, page 4. There should be a hotpink rectangle inside a yellow
+block, starting at the first page, and ending right before the first piece of
+text.
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/fledge-util.js b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/fledge-util.js
index 3e47af8..ed09a6be 100644
--- a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/fledge-util.js
+++ b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/fledge-util.js
@@ -11,7 +11,7 @@
 // exercise it use a fixed URL string. Special keys and interest group names
 // control the response.
 const TRUSTED_BIDDING_SIGNALS_URL =
-    `${BASE_URL}resources/trusted_bidding_signals.py`;
+    `${BASE_URL}resources/trusted-bidding-signals.py`;
 
 // Creates a URL that will be sent to the URL request tracker script.
 // `uuid` is used to identify the stash shard to use.
@@ -19,7 +19,7 @@
 // `id` can be used to uniquely identify tracked requests. It has no effect
 //     on behavior of the script; it only serves to make the URL unique.
 function createTrackerUrl(origin, uuid, dispatch, id = null) {
-  let url = new URL(`${origin}${BASE_PATH}resources/request_tracker.py`);
+  let url = new URL(`${origin}${BASE_PATH}resources/request-tracker.py`);
   url.searchParams.append('uuid', uuid);
   url.searchParams.append('dispatch', dispatch);
   if (id)
@@ -91,7 +91,7 @@
 
     // Fail on errors reported by the tracker script.
     if (trackerData.errors.length > 0) {
-      throw 'Errors reported by request_tracker.py:' +
+      throw 'Errors reported by request-tracker.py:' +
           JSON.stringify(trackerData.errors);
     }
 
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/request_tracker.py b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/request-tracker.py
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/fledge/tentative/resources/request_tracker.py
rename to third_party/blink/web_tests/external/wpt/fledge/tentative/resources/request-tracker.py
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted_bidding_signals.py b/third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-bidding-signals.py
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted_bidding_signals.py
rename to third_party/blink/web_tests/external/wpt/fledge/tentative/resources/trusted-bidding-signals.py
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/trusted-bidding-signals.https.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/fledge/tentative/trusted-bidding-signals.https.sub.window.js.ini
new file mode 100644
index 0000000..ac9b4aa3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fledge/tentative/trusted-bidding-signals.https.sub.window.js.ini
@@ -0,0 +1,138 @@
+[trusted-bidding-signals.https.sub.window.html]
+  [No trustedBiddingSignalsKeys or trustedBiddingSignalsUrl.]
+    expected: FAIL
+
+  [Trusted bidding signals receives empty interest group name.]
+    expected: FAIL
+
+  [Trusted bidding signals receives empty string key.]
+    expected: FAIL
+
+  [Trusted bidding signals receives escaped interest group name.]
+    expected: FAIL
+
+  [Trusted bidding signals receives escaped key.]
+    expected: FAIL
+
+  [Trusted bidding signals receives hostname field.]
+    expected: FAIL
+
+  [Trusted bidding signals receives interest group name.]
+    expected: FAIL
+
+  [Trusted bidding signals receives null key.]
+    expected: FAIL
+
+  [Trusted bidding signals response does not allow fledge.]
+    expected: FAIL
+
+  [Trusted bidding signals response has Data-Version and no trustedBiddingSignalsKeys.]
+    expected: FAIL
+
+  [Trusted bidding signals response has Data-Version with leading 0.]
+    expected: FAIL
+
+  [Trusted bidding signals response has a number value for key.]
+    expected: FAIL
+
+  [Trusted bidding signals response has array value for key.]
+    expected: FAIL
+
+  [Trusted bidding signals response has decimal in Data-Version.]
+    expected: FAIL
+
+  [Trusted bidding signals response has hex Data-Version.]
+    expected: FAIL
+
+  [Trusted bidding signals response has key not in trustedBiddingSignalsKeys.]
+    expected: FAIL
+
+  [Trusted bidding signals response has max Data-Version.]
+    expected: FAIL
+
+  [Trusted bidding signals response has min Data-Version.]
+    expected: FAIL
+
+  [Trusted bidding signals response has multiple keys.]
+    expected: FAIL
+
+  [Trusted bidding signals response has negative Data-Version.]
+    expected: FAIL
+
+  [Trusted bidding signals response has no X-Allow-FLEDGE header.]
+    expected: FAIL
+
+  [Trusted bidding signals response has no body.]
+    expected: FAIL
+
+  [Trusted bidding signals response has no content-type.]
+    expected: FAIL
+
+  [Trusted bidding signals response has no data-version.]
+    expected: FAIL
+
+  [Trusted bidding signals response has no keys object.]
+    expected: FAIL
+
+  [Trusted bidding signals response has no keys.]
+    expected: FAIL
+
+  [Trusted bidding signals response has numeric Data-Version.]
+    expected: FAIL
+
+  [Trusted bidding signals response has object value for key.]
+    expected: FAIL
+
+  [Trusted bidding signals response has space in Data-Version.]
+    expected: FAIL
+
+  [Trusted bidding signals response has string value for key.]
+    expected: FAIL
+
+  [Trusted bidding signals response has too large Data-Version.]
+    expected: FAIL
+
+  [Trusted bidding signals response has wrong X-Allow-FLEDGE header.]
+    expected: FAIL
+
+  [Trusted bidding signals response has wrong content-type.]
+    expected: FAIL
+
+  [Trusted bidding signals response in invalid JSON object.]
+    expected: FAIL
+
+  [Trusted bidding signals response is HTTP 404 error.]
+    expected: FAIL
+
+  [Trusted bidding signals response is a JSON array.]
+    expected: FAIL
+
+  [Trusted bidding signals response is not JSON.]
+    expected: FAIL
+
+  [Trusted bidding signals response keys is incorrectly an array.]
+    expected: FAIL
+
+  [Trusted bidding signals response null value for key.]
+    expected: FAIL
+
+  [Trusted bidding signals response with Data-Version and JSON array body.]
+    expected: FAIL
+
+  [Trusted bidding signals response with Data-Version and double JSON object body.]
+    expected: FAIL
+
+  [Trusted bidding signals response with Data-Version and empty body.]
+    expected: FAIL
+
+  [Trusted bidding signals response with Data-Version and invalid keys entry]
+    expected: FAIL
+
+  [trustedBiddingSignalsKeys but no trustedBiddingSignalsUrl.]
+    expected: FAIL
+
+  [trustedBiddingSignalsUrl closes the connection without sending anything.]
+    expected: FAIL
+
+  [trustedBiddingSignalsUrl without trustedBiddingSignalsKeys.]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro_cross-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro_cross-origin.https.html.ini
index 6226dd3..e6faede1 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro_cross-origin.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro_cross-origin.https.html.ini
@@ -1,6 +1,6 @@
 [access-to-coop-page-from-other_coop-ro_cross-origin.https.html]
   expected:
-    if product == "chrome": OK
+    if product == "chrome": [ERROR, OK]
     ERROR
   [access-to-coop-page-from-other (COOP-RO)]
     expected:
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/disabled-elements/event-propagate-disabled.tentative.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/disabled-elements/event-propagate-disabled.tentative.html.ini
new file mode 100644
index 0000000..26dc9e8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/disabled-elements/event-propagate-disabled.tentative.html.ini
@@ -0,0 +1,28 @@
+[event-propagate-disabled.tentative.html]
+  [Trusted click on <fieldset disabled=""><span class="target">Span</span></fieldset>, observed from <body>]
+    expected:
+      if product == "chrome": FAIL
+
+  [Trusted click on <fieldset disabled=""><span class="target">Span</span></fieldset>, observed from <fieldset>]
+    expected:
+      if product == "chrome": FAIL
+
+  [Trusted click on <fieldset disabled=""><span class="target">Span</span></fieldset>, observed from <span>]
+    expected:
+      if product == "chrome": FAIL
+
+  [Trusted click on <fieldset disabled="">Text</fieldset>, observed from <body>]
+    expected:
+      if product == "chrome": FAIL
+
+  [Trusted click on <fieldset disabled="">Text</fieldset>, observed from <fieldset>]
+    expected:
+      if product == "chrome": FAIL
+
+  [click() on <fieldset disabled="">Text</fieldset>, observed from <body>]
+    expected:
+      if product == "chrome": FAIL
+
+  [click() on <fieldset disabled="">Text</fieldset>, observed from <fieldset>]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini b/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini
index 004f0b6..fd7b32d7 100644
--- a/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini
@@ -1,22 +1,23 @@
 [cross-origin-iframe.sub.html]
   [First rAF]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
       if (product == "content_shell") and (os == "mac"): FAIL
+      if (product == "content_shell") and (os == "win"): FAIL
 
   [iframeDocument.scrollingElement.scrollTop = 250]
     expected:
-      if (product == "content_shell") and (os == "linux") and (flag_specific == ""): FAIL
-      if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL
-      if (product == "content_shell") and (os == "mac"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS
+      if product == "chrome": PASS
+      FAIL
 
   [topDocument.scrollingElement.scrollTop = 100]
     expected:
-      if (product == "content_shell") and (os == "win"): FAIL
-      if (product == "content_shell") and (os == "mac"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
+      if (product == "content_shell") and (os == "mac"): FAIL
 
   [topDocument.scrollingElement.scrollTop = 200]
     expected:
-      if (product == "content_shell") and (os == "mac"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL]
       FAIL
diff --git a/third_party/blink/web_tests/external/wpt/long-animation-frame/tentative/loaf-desired-exec-time.html.ini b/third_party/blink/web_tests/external/wpt/long-animation-frame/tentative/loaf-desired-exec-time.html.ini
new file mode 100644
index 0000000..8e64d0a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/long-animation-frame/tentative/loaf-desired-exec-time.html.ini
@@ -0,0 +1,8 @@
+[loaf-desired-exec-time.html]
+  [desiredExecutionStart for setTimeout should be the setup time + delay]
+    expected:
+      if product == "chrome": [PASS, FAIL]
+
+  [event-listener entries desiredExecutionStart is the eventTimestamp]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-record/MediaRecorder-stop.html.ini b/third_party/blink/web_tests/external/wpt/mediacapture-record/MediaRecorder-stop.html.ini
index dbfef8b..91e6176 100644
--- a/third_party/blink/web_tests/external/wpt/mediacapture-record/MediaRecorder-stop.html.ini
+++ b/third_party/blink/web_tests/external/wpt/mediacapture-record/MediaRecorder-stop.html.ini
@@ -1,7 +1,6 @@
 [MediaRecorder-stop.html]
-  expected: TIMEOUT
   [MediaRecorder will fire start event even if a track is removed synchronously]
-    expected: TIMEOUT
+    expected: FAIL
 
   [MediaRecorder will fire start event even if stopped synchronously]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/navigation-api/navigate-event/defaultPrevented-window-stop-after-dispatch.html.ini b/third_party/blink/web_tests/external/wpt/navigation-api/navigate-event/defaultPrevented-window-stop-after-dispatch.html.ini
new file mode 100644
index 0000000..63ad5f9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/navigation-api/navigate-event/defaultPrevented-window-stop-after-dispatch.html.ini
@@ -0,0 +1,3 @@
+[defaultPrevented-window-stop-after-dispatch.html]
+  expected:
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-get-set-range.html b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-get-set-range.html
index e80ef57..6de2d84 100644
--- a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-get-set-range.html
+++ b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-get-set-range.html
@@ -60,14 +60,14 @@
     container.scrollLeft = 750;
     await waitForNextFrame();
 
-    // auto ==> cover 0% to cover 100%
+    // normal ==> cover 0% to cover 100%
     // cover 0% @ 600px
     // cover 100% @ 900px
     // expected opacity = (750 - 600) / (900 - 600) = 0.5
-    assert_equals(anim.rangeStart, 'auto', 'Initial value for rangeStart');
-    assert_equals(anim.rangeEnd, 'auto', 'Initial value for rangeEnd');
+    assert_equals(anim.rangeStart, 'normal', 'Initial value for rangeStart');
+    assert_equals(anim.rangeEnd, 'normal', 'Initial value for rangeEnd');
     assert_equals(getComputedStyle(target).opacity, '0.5',
-                  'Opacity with range set to [auto, auto]');
+                  'Opacity with range set to [normal, normal]');
 
     // contain 0% @ 700px
     // cover 100% @ 900px
@@ -103,18 +103,18 @@
         parseFloat(getComputedStyle(target).opacity), 0.739130, 1e-6,
         'opacity with range set to [entry -20px, exit-crossing 10%]');
 
-    // auto [start] @ 600px
+    // normal [start] @ 600px
     // contain 100% @ 800px
     // expected opacity = (750 - 600) / (800 - 600) = 0.75
-    anim.rangeStart = "auto";
+    anim.rangeStart = "normal";
     anim.rangeEnd = "contain calc(60% + 40%)";
-    assert_equals(anim.rangeStart, 'auto','rangeStart set to auto');
+    assert_equals(anim.rangeStart, 'normal','rangeStart set to normal');
     assert_timeline_offset(
         anim.rangeEnd,
         { rangeName: 'contain', offset: CSS.percent(100) },
         'rangeEnd set to contain 100%');
     assert_equals(getComputedStyle(target).opacity, '0.75',
-                  'opacity with range set to [auto, contain 100%]');
+                  'opacity with range set to [normal, contain 100%]');
   }, 'Getting and setting the animation range');
 </script>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-script-src-strict-dynamic.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-script-src-strict-dynamic.html.ini
new file mode 100644
index 0000000..6563cff9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-script-src-strict-dynamic.html.ini
@@ -0,0 +1,6 @@
+[csp-script-src-strict-dynamic.html]
+  expected:
+    if product == "chrome": TIMEOUT
+  [Test if CSP script-src strict-dynamic allows inline speculationrules injected from the permitted scripts.]
+    expected:
+      if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window.js.ini b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window.js.ini
new file mode 100644
index 0000000..71cdfe1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window.js.ini
@@ -0,0 +1,3 @@
+[requestStorageAccess-ABA.tentative.sub.https.window.html]
+  expected:
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-nested-cross-origin-iframe.sub.https.window.js.ini b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-nested-cross-origin-iframe.sub.https.window.js.ini
index 4b233c6..1107f8d 100644
--- a/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-nested-cross-origin-iframe.sub.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-nested-cross-origin-iframe.sub.https.window.js.ini
@@ -1,4 +1,6 @@
 [requestStorageAccess-nested-cross-origin-iframe.sub.https.window.html]
+  expected:
+    if product == "chrome": ERROR
   [[nested-cross-origin-frame\] document.requestStorageAccess() should be rejected with a NotAllowedError with denied permission]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window.js.ini b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window.js.ini
new file mode 100644
index 0000000..8dee85d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window.js.ini
@@ -0,0 +1,3 @@
+[requestStorageAccess-nested-same-origin-iframe.sub.https.window.html]
+  expected:
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window.js.ini b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window.js.ini
new file mode 100644
index 0000000..4ae9c4d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window.js.ini
@@ -0,0 +1,3 @@
+[requestStorageAccess-same-site-iframe.sub.https.window.html]
+  expected:
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess.sub.https.window.js.ini b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess.sub.https.window.js.ini
new file mode 100644
index 0000000..977d0cb1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess.sub.https.window.js.ini
@@ -0,0 +1,3 @@
+[requestStorageAccess.sub.https.window.html]
+  expected:
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-streams/global.html.ini b/third_party/blink/web_tests/external/wpt/streams/readable-streams/global.html.ini
index a996d8d..4ddd919 100644
--- a/third_party/blink/web_tests/external/wpt/streams/readable-streams/global.html.ini
+++ b/third_party/blink/web_tests/external/wpt/streams/readable-streams/global.html.ini
@@ -1,3 +1,6 @@
 [global.html]
   [Cancel promise is created in same global as stream]
     expected: FAIL
+
+  [Reader objects in correct global]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/streams/transform-streams/invalid-realm.window.js.ini b/third_party/blink/web_tests/external/wpt/streams/transform-streams/invalid-realm.window.js.ini
new file mode 100644
index 0000000..2231a8b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/streams/transform-streams/invalid-realm.window.js.ini
@@ -0,0 +1,3 @@
+[invalid-realm.window.html]
+  [TransformStream: write in detached realm should succeed]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/url/README.md b/third_party/blink/web_tests/external/wpt/url/README.md
index 50a71bb..fa5e3b0d 100644
--- a/third_party/blink/web_tests/external/wpt/url/README.md
+++ b/third_party/blink/web_tests/external/wpt/url/README.md
@@ -1,31 +1,29 @@
 ## urltestdata.json
 
-These tests are for browsers, but the data for
-`a-element.html`, `url-constructor.html`, `a-element-xhtml.xhtml`, and `failure.html`
-is in `resources/urltestdata.json` and can be re-used by non-browser implementations.
-This file contains a JSON array of comments as strings and test cases as objects.
-The keys for each test case are:
+`resources/urltestdata.json` contains URL parsing tests suitable for any URL parser implementation.
 
-* `base`: an absolute URL as a string whose [parsing] without a base of its own must succeed.
-  This key is always present,
-  and may have a value like `"about:blank"` when `input` is an absolute URL.
-* `input`: an URL as a string to be [parsed][parsing] with `base` as its base URL.
-* Either:
-  * `failure` with the value `true`, indicating that parsing `input` should return failure,
-  * or `href`, `origin`, `protocol`, `username`, `password`, `host`, `hostname`, `port`,
-    `pathname`, `search`, and `hash` with string values;
-    indicating that parsing `input` should return an URL record
-    and that the getters of each corresponding attribute in that URL’s [API]
-    should return the corresponding value.
+It's used as a source of tests by `a-element.html`, `failure.html`, `url-constructor.any.js`, and
+other test files in this directory.
 
-    The `origin` key may be missing.
-    In that case, the API’s `origin` attribute is not tested.
+The format of `resources/urltestdata.json` is a JSON array of comments as strings and test cases as
+objects. The keys for each test case are:
 
-In addition to testing that parsing `input` against `base` gives the result, a test harness for the
-`URL` constructor (or similar APIs) should additionally test the following pattern: if `failure` is
-true, parsing `about:blank` against `input` must give failure. This tests that the logic for
-converting base URLs into strings properly fails the whole parsing algorithm if the base URL cannot
-be parsed.
+* `input`: a string to be parsed as URL.
+* `base`: null or a serialized URL (i.e., does not fail parsing).
+* Then either
+
+  * `failure` whose value is `true`, indicating that parsing `input` relative to `base` returns
+    failure
+  * `relativeTo` whose value is "`non-opaque-path-base`" (input does parse against a non-null base
+    URL without an opaque path) or "`any-base`" (input parses against any non-null base URL), or is
+    omitted in its entirety (input never parses successfully)
+
+  or `href`, `origin`, `protocol`, `username`, `password`, `host`, `hostname`, `port`,
+  `pathname`, `search`, and `hash` with string values; indicating that parsing `input` should return
+  an URL record and that the getters of each corresponding attribute in that URL’s [API] should
+  return the corresponding value.
+
+  The `origin` key may be missing. In that case, the API’s `origin` attribute is not tested.
 
 ## setters_tests.json
 
diff --git a/third_party/blink/web_tests/external/wpt/url/a-element-xhtml.xhtml.ini b/third_party/blink/web_tests/external/wpt/url/a-element-xhtml.xhtml.ini
index 95c1d6a..ff38c9b 100644
--- a/third_party/blink/web_tests/external/wpt/url/a-element-xhtml.xhtml.ini
+++ b/third_party/blink/web_tests/external/wpt/url/a-element-xhtml.xhtml.ini
@@ -59,6 +59,9 @@
   [Parsing: <> against <non-spec:/..//p>]
     expected: FAIL
 
+  [Parsing: <?> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <?i> against <sc:///pa/pa>]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/url/a-element.html.ini b/third_party/blink/web_tests/external/wpt/url/a-element.html.ini
index 320c7d1..3efb4ab 100644
--- a/third_party/blink/web_tests/external/wpt/url/a-element.html.ini
+++ b/third_party/blink/web_tests/external/wpt/url/a-element.html.ini
@@ -59,6 +59,9 @@
   [Parsing: <> against <non-spec:/..//p>]
     expected: FAIL
 
+  [Parsing: <?> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <?i> against <sc:///pa/pa>]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/url/failure.html b/third_party/blink/web_tests/external/wpt/url/failure.html
index 67873ea..8a40841 100644
--- a/third_party/blink/web_tests/external/wpt/url/failure.html
+++ b/third_party/blink/web_tests/external/wpt/url/failure.html
@@ -9,14 +9,15 @@
 promise_test(() => fetch("resources/urltestdata.json").then(res => res.json()).then(runTests), "Loading data…")
 
 function runTests(testData) {
-  for(const test of testData) {
-    if (typeof test === "string" || !test.failure || test.base !== "about:blank") {
-      continue
+  for (const test of testData) {
+    if (typeof test === "string" || !test.failure || test.base !== null) {
+      continue;
     }
 
     const name = test.input + " should throw"
 
-    self.test(() => { // URL's constructor's first argument is tested by url-constructor.html
+    self.test(() => {
+      // URL's constructor's first argument is tested by url-constructor.html
       // If a URL fails to parse with any valid base, it must also fail to parse with no base, i.e.
       // when used as a base URL itself.
       assert_throws_js(TypeError, () => new URL("about:blank", test.input));
@@ -30,7 +31,7 @@
     // The following use cases resolve the URL input relative to the current
     // document's URL. If this test input could be construed as a valid URL
     // when resolved against a base URL, skip these cases.
-    if (!test.inputCanBeRelative) {
+    if (test.relativeTo === undefined) {
       self.test(() => {
         const client = new XMLHttpRequest()
         assert_throws_dom("SyntaxError", () => client.open("GET", test.input))
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/a-element-origin.js b/third_party/blink/web_tests/external/wpt/url/resources/a-element-origin.js
index cb7d4a8..de72988 100644
--- a/third_party/blink/web_tests/external/wpt/url/resources/a-element-origin.js
+++ b/third_party/blink/web_tests/external/wpt/url/resources/a-element-origin.js
@@ -5,23 +5,28 @@
 }
 
 function bURL(url, base) {
-  base = base || "about:blank"
-  setBase(base)
-  var a = document.createElement("a")
-  a.setAttribute("href", url)
-  return a
+  setBase(base);
+  const a = document.createElement("a");
+  a.setAttribute("href", url);
+  return a;
 }
 
-function runURLTests(urltests) {
-  for(var i = 0, l = urltests.length; i < l; i++) {
-    var expected = urltests[i]
-    if (typeof expected === "string" || !("origin" in expected)) continue
-    // skip without base because you cannot unset the baseURL of a document
-    if (expected.base === null) continue;
+function runURLTests(urlTests) {
+  for (const expected of urlTests) {
+    // Skip comments and tests without "origin" expectation
+    if (typeof expected === "string" || !("origin" in expected))
+      continue;
+
+    // Fragments are relative against "about:blank" (this might always be redundant due to requiring "origin" in expected)
+    if (expected.base === null && expected.input.startsWith("#"))
+      continue;
+
+    // We cannot use a null base for HTML tests
+    const base = expected.base === null ? "about:blank" : expected.base;
 
     test(function() {
-      var url = bURL(expected.input, expected.base)
+      var url = bURL(expected.input, base)
       assert_equals(url.origin, expected.origin, "origin")
-    }, "Parsing origin: <" + expected.input + "> against <" + expected.base + ">")
+    }, "Parsing origin: <" + expected.input + "> against <" + base + ">")
   }
 }
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/a-element.js b/third_party/blink/web_tests/external/wpt/url/resources/a-element.js
index 65c7e85..d87937d 100644
--- a/third_party/blink/web_tests/external/wpt/url/resources/a-element.js
+++ b/third_party/blink/web_tests/external/wpt/url/resources/a-element.js
@@ -1,23 +1,28 @@
 promise_test(() => fetch("resources/urltestdata.json").then(res => res.json()).then(runURLTests), "Loading data…");
 
 function setBase(base) {
-  document.getElementById("base").href = base
+  document.getElementById("base").href = base;
 }
 
 function bURL(url, base) {
-  base = base || "about:blank"
-  setBase(base)
-  var a = document.createElement("a")
-  a.setAttribute("href", url)
-  return a
+  setBase(base);
+  const a = document.createElement("a");
+  a.setAttribute("href", url);
+  return a;
 }
 
-function runURLTests(urltests) {
-  for(var i = 0, l = urltests.length; i < l; i++) {
-    var expected = urltests[i]
-    if (typeof expected === "string") continue // skip comments
-    // skip without base because you cannot unset the baseURL of a document
-    if (expected.base === null) continue;
+function runURLTests(urlTests) {
+  for (const expected of urlTests) {
+    // Skip comments
+    if (typeof expected === "string")
+      continue;
+
+    // Fragments are relative against "about:blank"
+    if (expected.relativeTo === "any-base")
+      continue;
+
+    // We cannot use a null base for HTML tests
+    const base = expected.base === null ? "about:blank" : expected.base;
 
     function getKey(expected) {
       if (expected.protocol) {
@@ -30,7 +35,7 @@
     }
 
     subsetTestByKey(getKey(expected), test, function() {
-      var url = bURL(expected.input, expected.base)
+      var url = bURL(expected.input, base)
       if(expected.failure) {
         if(url.protocol !== ':') {
           assert_unreached("Expected URL to fail parsing")
@@ -49,6 +54,6 @@
       assert_equals(url.pathname, expected.pathname, "pathname")
       assert_equals(url.search, expected.search, "search")
       assert_equals(url.hash, expected.hash, "hash")
-    }, "Parsing: <" + expected.input + "> against <" + expected.base + ">")
+    }, "Parsing: <" + expected.input + "> against <" + base + ">")
   }
 }
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json b/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json
index a3cf976..beb4d9c 100644
--- a/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json
+++ b/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json
@@ -1,5 +1,5 @@
 [
-  "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/segments.js",
+  "See ../README.md for a description of the format.",
   {
     "input": "http://example\t.\norg",
     "base": "http://example.org/foo/bar",
@@ -32,7 +32,7 @@
   },
   {
     "input": "https://test:@test",
-    "base": "about:blank",
+    "base": null,
     "href": "https://test@test/",
     "origin": "https://test",
     "protocol": "https:",
@@ -47,7 +47,7 @@
   },
   {
     "input": "https://:@test",
-    "base": "about:blank",
+    "base": null,
     "href": "https://test/",
     "origin": "https://test",
     "protocol": "https:",
@@ -62,7 +62,7 @@
   },
   {
     "input": "non-special://test:@test/x",
-    "base": "about:blank",
+    "base": null,
     "href": "non-special://test@test/x",
     "origin": "null",
     "protocol": "non-special:",
@@ -77,7 +77,7 @@
   },
   {
     "input": "non-special://:@test/x",
-    "base": "about:blank",
+    "base": null,
     "href": "non-special://test/x",
     "origin": "null",
     "protocol": "non-special:",
@@ -167,7 +167,7 @@
   },
   {
     "input": "lolscheme:x x#x x",
-    "base": "about:blank",
+    "base": null,
     "href": "lolscheme:x x#x%20x",
     "protocol": "lolscheme:",
     "username": "",
@@ -1075,22 +1075,22 @@
   },
   {
     "input": "file://example:1/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "file://example:test/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "file://example%/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "file://[example]/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
@@ -1754,7 +1754,7 @@
   "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/path.js",
   {
     "input": "http://example.com/././foo",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1769,7 +1769,7 @@
   },
   {
     "input": "http://example.com/./.foo",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/.foo",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1784,7 +1784,7 @@
   },
   {
     "input": "http://example.com/foo/.",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1799,7 +1799,7 @@
   },
   {
     "input": "http://example.com/foo/./",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1814,7 +1814,7 @@
   },
   {
     "input": "http://example.com/foo/bar/..",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1829,7 +1829,7 @@
   },
   {
     "input": "http://example.com/foo/bar/../",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1844,7 +1844,7 @@
   },
   {
     "input": "http://example.com/foo/..bar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/..bar",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1859,7 +1859,7 @@
   },
   {
     "input": "http://example.com/foo/bar/../ton",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/ton",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1874,7 +1874,7 @@
   },
   {
     "input": "http://example.com/foo/bar/../ton/../../a",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/a",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1889,7 +1889,7 @@
   },
   {
     "input": "http://example.com/foo/../../..",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1904,7 +1904,7 @@
   },
   {
     "input": "http://example.com/foo/../../../ton",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/ton",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1919,7 +1919,7 @@
   },
   {
     "input": "http://example.com/foo/%2e",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1934,7 +1934,7 @@
   },
   {
     "input": "http://example.com/foo/%2e%2",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/%2e%2",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1949,7 +1949,7 @@
   },
   {
     "input": "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/%2e.bar",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1964,7 +1964,7 @@
   },
   {
     "input": "http://example.com////../..",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com//",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1979,7 +1979,7 @@
   },
   {
     "input": "http://example.com/foo/bar//../..",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -1994,7 +1994,7 @@
   },
   {
     "input": "http://example.com/foo/bar//..",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo/bar/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2009,7 +2009,7 @@
   },
   {
     "input": "http://example.com/foo",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2024,7 +2024,7 @@
   },
   {
     "input": "http://example.com/%20foo",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/%20foo",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2039,7 +2039,7 @@
   },
   {
     "input": "http://example.com/foo%",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo%",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2054,7 +2054,7 @@
   },
   {
     "input": "http://example.com/foo%2",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo%2",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2069,7 +2069,7 @@
   },
   {
     "input": "http://example.com/foo%2zbar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo%2zbar",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2084,7 +2084,7 @@
   },
   {
     "input": "http://example.com/foo%2©zbar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo%2%C3%82%C2%A9zbar",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2099,7 +2099,7 @@
   },
   {
     "input": "http://example.com/foo%41%7a",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo%41%7a",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2114,7 +2114,7 @@
   },
   {
     "input": "http://example.com/foo\t\u0091%91",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo%C2%91%91",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2129,7 +2129,7 @@
   },
   {
     "input": "http://example.com/foo%00%51",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foo%00%51",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2144,7 +2144,7 @@
   },
   {
     "input": "http://example.com/(%28:%3A%29)",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/(%28:%3A%29)",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2159,7 +2159,7 @@
   },
   {
     "input": "http://example.com/%3A%3a%3C%3c",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/%3A%3a%3C%3c",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2174,7 +2174,7 @@
   },
   {
     "input": "http://example.com/foo\tbar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/foobar",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2189,7 +2189,7 @@
   },
   {
     "input": "http://example.com\\\\foo\\\\bar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com//foo//bar",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2204,7 +2204,7 @@
   },
   {
     "input": "http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2219,7 +2219,7 @@
   },
   {
     "input": "http://example.com/@asdf%40",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/@asdf%40",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2234,7 +2234,7 @@
   },
   {
     "input": "http://example.com/你好你好",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2249,7 +2249,7 @@
   },
   {
     "input": "http://example.com/‥/foo",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/%E2%80%A5/foo",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2264,7 +2264,7 @@
   },
   {
     "input": "http://example.com//foo",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/%EF%BB%BF/foo",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2279,7 +2279,7 @@
   },
   {
     "input": "http://example.com/‮/foo/‭/bar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/%E2%80%AE/foo/%E2%80%AD/bar",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2295,7 +2295,7 @@
   "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/relative.js",
   {
     "input": "http://www.google.com/foo?bar=baz#",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www.google.com/foo?bar=baz#",
     "origin": "http://www.google.com",
     "protocol": "http:",
@@ -2310,7 +2310,7 @@
   },
   {
     "input": "http://www.google.com/foo?bar=baz# »",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www.google.com/foo?bar=baz#%20%C2%BB",
     "origin": "http://www.google.com",
     "protocol": "http:",
@@ -2325,7 +2325,7 @@
   },
   {
     "input": "data:test# »",
-    "base": "about:blank",
+    "base": null,
     "href": "data:test#%20%C2%BB",
     "origin": "null",
     "protocol": "data:",
@@ -2340,7 +2340,7 @@
   },
   {
     "input": "http://www.google.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www.google.com/",
     "origin": "http://www.google.com",
     "protocol": "http:",
@@ -2355,7 +2355,7 @@
   },
   {
     "input": "http://192.0x00A80001",
-    "base": "about:blank",
+    "base": null,
     "href": "http://192.168.0.1/",
     "origin": "http://192.168.0.1",
     "protocol": "http:",
@@ -2370,7 +2370,7 @@
   },
   {
     "input": "http://www/foo%2Ehtml",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www/foo%2Ehtml",
     "origin": "http://www",
     "protocol": "http:",
@@ -2385,7 +2385,7 @@
   },
   {
     "input": "http://www/foo/%2E/html",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www/foo/html",
     "origin": "http://www",
     "protocol": "http:",
@@ -2400,12 +2400,12 @@
   },
   {
     "input": "http://user:pass@/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://%25DOMAIN:foobar@foodomain.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "http://%25DOMAIN:foobar@foodomain.com/",
     "origin": "http://foodomain.com",
     "protocol": "http:",
@@ -2420,7 +2420,7 @@
   },
   {
     "input": "http:\\\\www.google.com\\foo",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www.google.com/foo",
     "origin": "http://www.google.com",
     "protocol": "http:",
@@ -2435,7 +2435,7 @@
   },
   {
     "input": "http://foo:80/",
-    "base": "about:blank",
+    "base": null,
     "href": "http://foo/",
     "origin": "http://foo",
     "protocol": "http:",
@@ -2450,7 +2450,7 @@
   },
   {
     "input": "http://foo:81/",
-    "base": "about:blank",
+    "base": null,
     "href": "http://foo:81/",
     "origin": "http://foo:81",
     "protocol": "http:",
@@ -2465,7 +2465,7 @@
   },
   {
     "input": "httpa://foo:80/",
-    "base": "about:blank",
+    "base": null,
     "href": "httpa://foo:80/",
     "origin": "null",
     "protocol": "httpa:",
@@ -2480,12 +2480,12 @@
   },
   {
     "input": "http://foo:-80/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://foo:443/",
-    "base": "about:blank",
+    "base": null,
     "href": "https://foo/",
     "origin": "https://foo",
     "protocol": "https:",
@@ -2500,7 +2500,7 @@
   },
   {
     "input": "https://foo:80/",
-    "base": "about:blank",
+    "base": null,
     "href": "https://foo:80/",
     "origin": "https://foo:80",
     "protocol": "https:",
@@ -2515,7 +2515,7 @@
   },
   {
     "input": "ftp://foo:21/",
-    "base": "about:blank",
+    "base": null,
     "href": "ftp://foo/",
     "origin": "ftp://foo",
     "protocol": "ftp:",
@@ -2530,7 +2530,7 @@
   },
   {
     "input": "ftp://foo:80/",
-    "base": "about:blank",
+    "base": null,
     "href": "ftp://foo:80/",
     "origin": "ftp://foo:80",
     "protocol": "ftp:",
@@ -2545,7 +2545,7 @@
   },
   {
     "input": "gopher://foo:70/",
-    "base": "about:blank",
+    "base": null,
     "href": "gopher://foo:70/",
     "origin": "null",
     "protocol": "gopher:",
@@ -2560,7 +2560,7 @@
   },
   {
     "input": "gopher://foo:443/",
-    "base": "about:blank",
+    "base": null,
     "href": "gopher://foo:443/",
     "origin": "null",
     "protocol": "gopher:",
@@ -2575,7 +2575,7 @@
   },
   {
     "input": "ws://foo:80/",
-    "base": "about:blank",
+    "base": null,
     "href": "ws://foo/",
     "origin": "ws://foo",
     "protocol": "ws:",
@@ -2590,7 +2590,7 @@
   },
   {
     "input": "ws://foo:81/",
-    "base": "about:blank",
+    "base": null,
     "href": "ws://foo:81/",
     "origin": "ws://foo:81",
     "protocol": "ws:",
@@ -2605,7 +2605,7 @@
   },
   {
     "input": "ws://foo:443/",
-    "base": "about:blank",
+    "base": null,
     "href": "ws://foo:443/",
     "origin": "ws://foo:443",
     "protocol": "ws:",
@@ -2620,7 +2620,7 @@
   },
   {
     "input": "ws://foo:815/",
-    "base": "about:blank",
+    "base": null,
     "href": "ws://foo:815/",
     "origin": "ws://foo:815",
     "protocol": "ws:",
@@ -2635,7 +2635,7 @@
   },
   {
     "input": "wss://foo:80/",
-    "base": "about:blank",
+    "base": null,
     "href": "wss://foo:80/",
     "origin": "wss://foo:80",
     "protocol": "wss:",
@@ -2650,7 +2650,7 @@
   },
   {
     "input": "wss://foo:81/",
-    "base": "about:blank",
+    "base": null,
     "href": "wss://foo:81/",
     "origin": "wss://foo:81",
     "protocol": "wss:",
@@ -2665,7 +2665,7 @@
   },
   {
     "input": "wss://foo:443/",
-    "base": "about:blank",
+    "base": null,
     "href": "wss://foo/",
     "origin": "wss://foo",
     "protocol": "wss:",
@@ -2680,7 +2680,7 @@
   },
   {
     "input": "wss://foo:815/",
-    "base": "about:blank",
+    "base": null,
     "href": "wss://foo:815/",
     "origin": "wss://foo:815",
     "protocol": "wss:",
@@ -2695,7 +2695,7 @@
   },
   {
     "input": "http:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2710,7 +2710,7 @@
   },
   {
     "input": "ftp:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "ftp://example.com/",
     "origin": "ftp://example.com",
     "protocol": "ftp:",
@@ -2725,7 +2725,7 @@
   },
   {
     "input": "https:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "https://example.com/",
     "origin": "https://example.com",
     "protocol": "https:",
@@ -2740,7 +2740,7 @@
   },
   {
     "input": "madeupscheme:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "madeupscheme:/example.com/",
     "origin": "null",
     "protocol": "madeupscheme:",
@@ -2755,7 +2755,7 @@
   },
   {
     "input": "file:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///example.com/",
     "protocol": "file:",
     "username": "",
@@ -2769,7 +2769,7 @@
   },
   {
     "input": "ftps:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "ftps:/example.com/",
     "origin": "null",
     "protocol": "ftps:",
@@ -2784,7 +2784,7 @@
   },
   {
     "input": "gopher:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "gopher:/example.com/",
     "origin": "null",
     "protocol": "gopher:",
@@ -2799,7 +2799,7 @@
   },
   {
     "input": "ws:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "ws://example.com/",
     "origin": "ws://example.com",
     "protocol": "ws:",
@@ -2814,7 +2814,7 @@
   },
   {
     "input": "wss:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "wss://example.com/",
     "origin": "wss://example.com",
     "protocol": "wss:",
@@ -2829,7 +2829,7 @@
   },
   {
     "input": "data:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "data:/example.com/",
     "origin": "null",
     "protocol": "data:",
@@ -2844,7 +2844,7 @@
   },
   {
     "input": "javascript:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "javascript:/example.com/",
     "origin": "null",
     "protocol": "javascript:",
@@ -2859,7 +2859,7 @@
   },
   {
     "input": "mailto:/example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "mailto:/example.com/",
     "origin": "null",
     "protocol": "mailto:",
@@ -2874,7 +2874,7 @@
   },
   {
     "input": "http:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -2889,7 +2889,7 @@
   },
   {
     "input": "ftp:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "ftp://example.com/",
     "origin": "ftp://example.com",
     "protocol": "ftp:",
@@ -2904,7 +2904,7 @@
   },
   {
     "input": "https:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "https://example.com/",
     "origin": "https://example.com",
     "protocol": "https:",
@@ -2919,7 +2919,7 @@
   },
   {
     "input": "madeupscheme:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "madeupscheme:example.com/",
     "origin": "null",
     "protocol": "madeupscheme:",
@@ -2934,7 +2934,7 @@
   },
   {
     "input": "ftps:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "ftps:example.com/",
     "origin": "null",
     "protocol": "ftps:",
@@ -2949,7 +2949,7 @@
   },
   {
     "input": "gopher:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "gopher:example.com/",
     "origin": "null",
     "protocol": "gopher:",
@@ -2964,7 +2964,7 @@
   },
   {
     "input": "ws:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "ws://example.com/",
     "origin": "ws://example.com",
     "protocol": "ws:",
@@ -2979,7 +2979,7 @@
   },
   {
     "input": "wss:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "wss://example.com/",
     "origin": "wss://example.com",
     "protocol": "wss:",
@@ -2994,7 +2994,7 @@
   },
   {
     "input": "data:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "data:example.com/",
     "origin": "null",
     "protocol": "data:",
@@ -3009,7 +3009,7 @@
   },
   {
     "input": "javascript:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "javascript:example.com/",
     "origin": "null",
     "protocol": "javascript:",
@@ -3024,7 +3024,7 @@
   },
   {
     "input": "mailto:example.com/",
-    "base": "about:blank",
+    "base": null,
     "href": "mailto:example.com/",
     "origin": "null",
     "protocol": "mailto:",
@@ -3040,7 +3040,7 @@
   "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/segments-userinfo-vs-host.html",
   {
     "input": "http:@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3055,7 +3055,7 @@
   },
   {
     "input": "http:/@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3070,7 +3070,7 @@
   },
   {
     "input": "http://@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3085,7 +3085,7 @@
   },
   {
     "input": "http:a:b@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://a:b@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3100,7 +3100,7 @@
   },
   {
     "input": "http:/a:b@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://a:b@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3115,7 +3115,7 @@
   },
   {
     "input": "http://a:b@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://a:b@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3130,7 +3130,7 @@
   },
   {
     "input": "http://@pple.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://pple.com/",
     "origin": "http://pple.com",
     "protocol": "http:",
@@ -3145,7 +3145,7 @@
   },
   {
     "input": "http::b@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://:b@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3160,7 +3160,7 @@
   },
   {
     "input": "http:/:b@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://:b@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3175,7 +3175,7 @@
   },
   {
     "input": "http://:b@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://:b@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3190,64 +3190,64 @@
   },
   {
     "input": "http:/:@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "http://user@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http:@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "http:/@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "http://@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https:@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "http:a:b@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "http:/a:b@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "http://a:b@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http::@/www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "http:a:@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://a@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3262,7 +3262,7 @@
   },
   {
     "input": "http:/a:@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://a@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3277,7 +3277,7 @@
   },
   {
     "input": "http://a:@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://a@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3292,7 +3292,7 @@
   },
   {
     "input": "http://www.@pple.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www.@pple.com/",
     "origin": "http://pple.com",
     "protocol": "http:",
@@ -3307,24 +3307,24 @@
   },
   {
     "input": "http:@:www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "http:/@:www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "http://@:www.example.com",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://:@www.example.com",
-    "base": "about:blank",
+    "base": null,
     "href": "http://www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
@@ -3622,7 +3622,7 @@
   "Leading and trailing C0 control or space",
   {
     "input": "\u0000\u001b\u0004\u0012 http://example.com/\u001f \u000d ",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -3666,17 +3666,17 @@
   "U+FFFD",
   {
     "input": "https://\ufffd",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://%EF%BF%BD",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://x/\ufffd?\ufffd#\ufffd",
-    "base": "about:blank",
+    "base": null,
     "href": "https://x/%EF%BF%BD?%EF%BF%BD#%EF%BF%BD",
     "origin": "https://x",
     "protocol": "https:",
@@ -3692,33 +3692,33 @@
   "Domain is ASCII, but a label is invalid IDNA",
   {
     "input": "http://a.b.c.xn--pokxncvks",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://10.0.0.xn--pokxncvks",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "IDNA labels should be matched case-insensitively",
   {
     "input": "http://a.b.c.XN--pokxncvks",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a.b.c.Xn--pokxncvks",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://10.0.0.XN--pokxncvks",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://10.0.0.xN--pokxncvks",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "Test name prepping, fullwidth input should be converted to ASCII and NOT IDN-ized. This is 'Go' in fullwidth UTF-8/UTF-16.",
@@ -3777,7 +3777,7 @@
   },
   {
     "input": "https://faß.ExAmPlE/",
-    "base": "about:blank",
+    "base": null,
     "href": "https://xn--fa-hia.example/",
     "origin": "https://xn--fa-hia.example",
     "protocol": "https:",
@@ -3792,7 +3792,7 @@
   },
   {
     "input": "sc://faß.ExAmPlE/",
-    "base": "about:blank",
+    "base": null,
     "href": "sc://fa%C3%9F.ExAmPlE/",
     "origin": "null",
     "protocol": "sc:",
@@ -3872,7 +3872,7 @@
   },
   {
     "input": "https://x x:12",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "Fullwidth and escaped UTF-8 fullwidth should still be treated as IP",
@@ -3894,7 +3894,7 @@
   "Domains with empty labels",
   {
     "input": "http://./",
-    "base": "about:blank",
+    "base": null,
     "href": "http://./",
     "origin": "http://.",
     "protocol": "http:",
@@ -3909,7 +3909,7 @@
   },
   {
     "input": "http://../",
-    "base": "about:blank",
+    "base": null,
     "href": "http://../",
     "origin": "http://..",
     "protocol": "http:",
@@ -3925,7 +3925,7 @@
   "Non-special domains with empty labels",
   {
     "input": "h://.",
-    "base": "about:blank",
+    "base": null,
     "href": "h://.",
     "origin": "null",
     "protocol": "h:",
@@ -3941,7 +3941,7 @@
   "Broken IPv6",
   {
     "input": "http://[www.google.com]/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
@@ -4131,7 +4131,7 @@
   "byte is ' and url is special",
   {
     "input": "http://host/?'",
-    "base": "about:blank",
+    "base": null,
     "href": "http://host/?%27",
     "origin": "http://host",
     "protocol": "http:",
@@ -4146,7 +4146,7 @@
   },
   {
     "input": "notspecial://host/?'",
-    "base": "about:blank",
+    "base": null,
     "href": "notspecial://host/?'",
     "origin": "null",
     "protocol": "notspecial:",
@@ -4504,7 +4504,7 @@
   "# make sure that relative URL logic works on known typically non-relative schemes too",
   {
     "input": "about:/../",
-    "base": "about:blank",
+    "base": null,
     "href": "about:/",
     "origin": "null",
     "protocol": "about:",
@@ -4519,7 +4519,7 @@
   },
   {
     "input": "data:/../",
-    "base": "about:blank",
+    "base": null,
     "href": "data:/",
     "origin": "null",
     "protocol": "data:",
@@ -4534,7 +4534,7 @@
   },
   {
     "input": "javascript:/../",
-    "base": "about:blank",
+    "base": null,
     "href": "javascript:/",
     "origin": "null",
     "protocol": "javascript:",
@@ -4549,7 +4549,7 @@
   },
   {
     "input": "mailto:/../",
-    "base": "about:blank",
+    "base": null,
     "href": "mailto:/",
     "origin": "null",
     "protocol": "mailto:",
@@ -4565,7 +4565,7 @@
   "# unknown schemes and their hosts",
   {
     "input": "sc://ñ.test/",
-    "base": "about:blank",
+    "base": null,
     "href": "sc://%C3%B1.test/",
     "origin": "null",
     "protocol": "sc:",
@@ -4580,7 +4580,7 @@
   },
   {
     "input": "sc://%/",
-    "base": "about:blank",
+    "base": null,
     "href": "sc://%/",
     "protocol": "sc:",
     "username": "",
@@ -4594,22 +4594,22 @@
   },
   {
     "input": "sc://@/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://te@s:t@/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://:/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://:12/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
@@ -4630,7 +4630,7 @@
   "# unknown schemes and backslashes",
   {
     "input": "sc:\\../",
-    "base": "about:blank",
+    "base": null,
     "href": "sc:\\../",
     "origin": "null",
     "protocol": "sc:",
@@ -4646,7 +4646,7 @@
   "# unknown scheme with path looking like a password",
   {
     "input": "sc::a@example.net",
-    "base": "about:blank",
+    "base": null,
     "href": "sc::a@example.net",
     "origin": "null",
     "protocol": "sc:",
@@ -4662,7 +4662,7 @@
   "# unknown scheme with bogus percent-encoding",
   {
     "input": "wow:%NBD",
-    "base": "about:blank",
+    "base": null,
     "href": "wow:%NBD",
     "origin": "null",
     "protocol": "wow:",
@@ -4677,7 +4677,7 @@
   },
   {
     "input": "wow:%1G",
-    "base": "about:blank",
+    "base": null,
     "href": "wow:%1G",
     "origin": "null",
     "protocol": "wow:",
@@ -4693,7 +4693,7 @@
   "# unknown scheme with non-URL characters",
   {
     "input": "wow:\uFFFF",
-    "base": "about:blank",
+    "base": null,
     "href": "wow:%EF%BF%BF",
     "origin": "null",
     "protocol": "wow:",
@@ -4708,7 +4708,7 @@
   },
   {
     "input": "http://example.com/\uD800\uD801\uDFFE\uDFFF\uFDD0\uFDCF\uFDEF\uFDF0\uFFFE\uFFFF?\uD800\uD801\uDFFE\uDFFF\uFDD0\uFDCF\uFDEF\uFDF0\uFFFE\uFFFF",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.com/%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF?%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF",
     "origin": "http://example.com",
     "protocol": "http:",
@@ -4724,53 +4724,53 @@
   "Forbidden host code points",
   {
     "input": "sc://a\u0000b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://a b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://a<b",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://a>b",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://a[b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://a\\b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://a]b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://a^b",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "sc://a|b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "Forbidden host codepoints: tabs and newlines are removed during preprocessing",
   {
     "input": "foo://ho\u0009st/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -4784,7 +4784,7 @@
   },
   {
     "input": "foo://ho\u000Ast/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -4798,7 +4798,7 @@
   },
   {
     "input": "foo://ho\u000Dst/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -4813,198 +4813,198 @@
   "Forbidden domain code-points",
   {
     "input": "http://a\u0000b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0001b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0002b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0003b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0004b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0005b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0006b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0007b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0008b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u000Bb/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u000Cb/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u000Eb/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u000Fb/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0010b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0011b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0012b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0013b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0014b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0015b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0016b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0017b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0018b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u0019b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u001Ab/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u001Bb/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u001Cb/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u001Db/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u001Eb/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u001Fb/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a%b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a<b",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a>b",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a[b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a]b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a^b",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a|b/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://a\u007Fb/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "Forbidden domain codepoints: tabs and newlines are removed during preprocessing",
   {
     "input": "http://ho\u0009st/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -5018,7 +5018,7 @@
   },
   {
     "input": "http://ho\u000Ast/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -5032,7 +5032,7 @@
   },
   {
     "input": "http://ho\u000Dst/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -5047,238 +5047,238 @@
   "Encoded forbidden domain codepoints in special URLs",
   {
     "input": "http://ho%00st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%01st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%02st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%03st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%04st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%05st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%06st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%07st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%08st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%09st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%0Ast/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%0Bst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%0Cst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%0Dst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%0Est/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%0Fst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%10st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%11st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%12st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%13st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%14st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%15st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%16st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%17st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%18st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%19st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%1Ast/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%1Bst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%1Cst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%1Dst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%1Est/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%1Fst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%20st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%23st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%25st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%2Fst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%3Ast/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%3Cst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%3Est/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%3Fst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%40st/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%5Bst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%5Cst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%5Dst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%7Cst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://ho%7Fst/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "Allowed host/domain code points",
   {
     "input": "http://!\"$&'()*+,-.;=_`{}~/",
-    "base": "about:blank",
+    "base": null,
     "href": "http://!\"$&'()*+,-.;=_`{}~/",
     "origin": "http://!\"$&'()*+,-.;=_`{}~",
     "protocol": "http:",
@@ -5293,7 +5293,7 @@
   },
   {
     "input": "sc://\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u000B\u000C\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F\u007F!\"$%&'()*+,-.;=_`{}~/",
-    "base": "about:blank",
+    "base": null,
     "href": "sc://%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~/",
     "origin": "null",
     "protocol": "sc:",
@@ -5309,27 +5309,27 @@
   "# Hosts and percent-encoding",
   {
     "input": "ftp://example.com%80/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "ftp://example.com%A0/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://example.com%80/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://example.com%A0/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "ftp://%e2%98%83",
-    "base": "about:blank",
+    "base": null,
     "href": "ftp://xn--n3h/",
     "origin": "ftp://xn--n3h",
     "protocol": "ftp:",
@@ -5344,7 +5344,7 @@
   },
   {
     "input": "https://%e2%98%83",
-    "base": "about:blank",
+    "base": null,
     "href": "https://xn--n3h/",
     "origin": "https://xn--n3h",
     "protocol": "https:",
@@ -5360,7 +5360,7 @@
   "# tests from jsdom/whatwg-url designed for code coverage",
   {
     "input": "http://127.0.0.1:10100/relative_import.html",
-    "base": "about:blank",
+    "base": null,
     "href": "http://127.0.0.1:10100/relative_import.html",
     "origin": "http://127.0.0.1:10100",
     "protocol": "http:",
@@ -5375,7 +5375,7 @@
   },
   {
     "input": "http://facebook.com/?foo=%7B%22abc%22",
-    "base": "about:blank",
+    "base": null,
     "href": "http://facebook.com/?foo=%7B%22abc%22",
     "origin": "http://facebook.com",
     "protocol": "http:",
@@ -5390,7 +5390,7 @@
   },
   {
     "input": "https://localhost:3000/jqueryui@1.2.3",
-    "base": "about:blank",
+    "base": null,
     "href": "https://localhost:3000/jqueryui@1.2.3",
     "origin": "https://localhost:3000",
     "protocol": "https:",
@@ -5406,7 +5406,7 @@
   "# tab/LF/CR",
   {
     "input": "h\tt\nt\rp://h\to\ns\rt:9\t0\n0\r0/p\ta\nt\rh?q\tu\ne\rry#f\tr\na\rg",
-    "base": "about:blank",
+    "base": null,
     "href": "http://host:9000/path?query#frag",
     "origin": "http://host:9000",
     "protocol": "http:",
@@ -5493,7 +5493,7 @@
   "# Percent encoding of fragments",
   {
     "input": "http://foo.bar/baz?qux#foo\bbar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://foo.bar/baz?qux#foo%08bar",
     "origin": "http://foo.bar",
     "protocol": "http:",
@@ -5509,7 +5509,7 @@
   },
   {
     "input": "http://foo.bar/baz?qux#foo\"bar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://foo.bar/baz?qux#foo%22bar",
     "origin": "http://foo.bar",
     "protocol": "http:",
@@ -5525,7 +5525,7 @@
   },
   {
     "input": "http://foo.bar/baz?qux#foo<bar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://foo.bar/baz?qux#foo%3Cbar",
     "origin": "http://foo.bar",
     "protocol": "http:",
@@ -5541,7 +5541,7 @@
   },
   {
     "input": "http://foo.bar/baz?qux#foo>bar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://foo.bar/baz?qux#foo%3Ebar",
     "origin": "http://foo.bar",
     "protocol": "http:",
@@ -5557,7 +5557,7 @@
   },
   {
     "input": "http://foo.bar/baz?qux#foo`bar",
-    "base": "about:blank",
+    "base": null,
     "href": "http://foo.bar/baz?qux#foo%60bar",
     "origin": "http://foo.bar",
     "protocol": "http:",
@@ -5789,7 +5789,7 @@
   },
   {
     "input": "https://0x.0x.0",
-    "base": "about:blank",
+    "base": null,
     "href": "https://0.0.0.0/",
     "origin": "https://0.0.0.0",
     "protocol": "https:",
@@ -5805,18 +5805,18 @@
   "More IPv4 parsing (via https://github.com/jsdom/whatwg-url/issues/92)",
   {
     "input": "https://0x100000000/test",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://256.0.0.1/test",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "# file URLs containing percent-encoded Windows drive letters (shouldn't work)",
   {
     "input": "file:///C%3A/",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///C%3A/",
     "protocol": "file:",
     "username": "",
@@ -5830,7 +5830,7 @@
   },
   {
     "input": "file:///C%7C/",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///C%7C/",
     "protocol": "file:",
     "username": "",
@@ -5844,42 +5844,42 @@
   },
   {
     "input": "file://%43%3A",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "file://%43%7C",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "file://%43|",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "file://C%7C",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "file://%43%7C/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://%43%7C/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "asdf://%43|/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "asdf://%43%7C/",
-    "base": "about:blank",
+    "base": null,
     "href": "asdf://%43%7C/",
     "origin": "null",
     "protocol": "asdf:",
@@ -6121,7 +6121,7 @@
   "# File URLs and many (back)slashes",
   {
     "input": "file:\\\\//",
-    "base": "about:blank",
+    "base": null,
     "href": "file:////",
     "protocol": "file:",
     "username": "",
@@ -6135,7 +6135,7 @@
   },
   {
     "input": "file:\\\\\\\\",
-    "base": "about:blank",
+    "base": null,
     "href": "file:////",
     "protocol": "file:",
     "username": "",
@@ -6149,7 +6149,7 @@
   },
   {
     "input": "file:\\\\\\\\?fox",
-    "base": "about:blank",
+    "base": null,
     "href": "file:////?fox",
     "protocol": "file:",
     "username": "",
@@ -6163,7 +6163,7 @@
   },
   {
     "input": "file:\\\\\\\\#guppy",
-    "base": "about:blank",
+    "base": null,
     "href": "file:////#guppy",
     "protocol": "file:",
     "username": "",
@@ -6177,7 +6177,7 @@
   },
   {
     "input": "file://spider///",
-    "base": "about:blank",
+    "base": null,
     "href": "file://spider///",
     "protocol": "file:",
     "username": "",
@@ -6191,7 +6191,7 @@
   },
   {
     "input": "file:\\\\localhost//",
-    "base": "about:blank",
+    "base": null,
     "href": "file:////",
     "protocol": "file:",
     "username": "",
@@ -6205,7 +6205,7 @@
   },
   {
     "input": "file:///localhost//cat",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///localhost//cat",
     "protocol": "file:",
     "username": "",
@@ -6219,7 +6219,7 @@
   },
   {
     "input": "file://\\/localhost//cat",
-    "base": "about:blank",
+    "base": null,
     "href": "file:////localhost//cat",
     "protocol": "file:",
     "username": "",
@@ -6233,7 +6233,7 @@
   },
   {
     "input": "file://localhost//a//../..//",
-    "base": "about:blank",
+    "base": null,
     "href": "file://///",
     "protocol": "file:",
     "username": "",
@@ -6545,7 +6545,7 @@
   "# Do not drop the host in the presence of a drive letter",
   {
     "input": "file://example.net/C:/",
-    "base": "about:blank",
+    "base": null,
     "href": "file://example.net/C:/",
     "protocol": "file:",
     "username": "",
@@ -6559,7 +6559,7 @@
   },
   {
     "input": "file://1.2.3.4/C:/",
-    "base": "about:blank",
+    "base": null,
     "href": "file://1.2.3.4/C:/",
     "protocol": "file:",
     "username": "",
@@ -6573,7 +6573,7 @@
   },
   {
     "input": "file://[1::8]/C:/",
-    "base": "about:blank",
+    "base": null,
     "href": "file://[1::8]/C:/",
     "protocol": "file:",
     "username": "",
@@ -6702,7 +6702,7 @@
   "# Windows drive letter quirk (no host)",
   {
     "input": "file:/C|/",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///C:/",
     "protocol": "file:",
     "username": "",
@@ -6716,7 +6716,7 @@
   },
   {
     "input": "file://C|/",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///C:/",
     "protocol": "file:",
     "username": "",
@@ -6731,7 +6731,7 @@
   "# file URLs without base URL by Rimas Misevičius",
   {
     "input": "file:",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///",
     "protocol": "file:",
     "username": "",
@@ -6745,7 +6745,7 @@
   },
   {
     "input": "file:?q=v",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///?q=v",
     "protocol": "file:",
     "username": "",
@@ -6759,7 +6759,7 @@
   },
   {
     "input": "file:#frag",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///#frag",
     "protocol": "file:",
     "username": "",
@@ -6774,7 +6774,7 @@
   "# file: drive letter cases from https://crbug.com/1078698",
   {
     "input": "file:///Y:",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///Y:",
     "protocol": "file:",
     "username": "",
@@ -6788,7 +6788,7 @@
   },
   {
     "input": "file:///Y:/",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///Y:/",
     "protocol": "file:",
     "username": "",
@@ -6802,7 +6802,7 @@
   },
   {
     "input": "file:///./Y",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///Y",
     "protocol": "file:",
     "username": "",
@@ -6816,7 +6816,7 @@
   },
   {
     "input": "file:///./Y:",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///Y:",
     "protocol": "file:",
     "username": "",
@@ -6830,14 +6830,14 @@
   },
   {
     "input": "\\\\\\.\\Y:",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   "# file: drive letter cases from https://crbug.com/1078698 but lowercased",
   {
     "input": "file:///y:",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///y:",
     "protocol": "file:",
     "username": "",
@@ -6851,7 +6851,7 @@
   },
   {
     "input": "file:///y:/",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///y:/",
     "protocol": "file:",
     "username": "",
@@ -6865,7 +6865,7 @@
   },
   {
     "input": "file:///./y",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///y",
     "protocol": "file:",
     "username": "",
@@ -6879,7 +6879,7 @@
   },
   {
     "input": "file:///./y:",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///y:",
     "protocol": "file:",
     "username": "",
@@ -6893,14 +6893,14 @@
   },
   {
     "input": "\\\\\\.\\y:",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   "# Additional file URL tests for (https://github.com/whatwg/url/issues/405)",
   {
     "input": "file://localhost//a//../..//foo",
-    "base": "about:blank",
+    "base": null,
     "href": "file://///foo",
     "protocol": "file:",
     "username": "",
@@ -6914,7 +6914,7 @@
   },
   {
     "input": "file://localhost////foo",
-    "base": "about:blank",
+    "base": null,
     "href": "file://////foo",
     "protocol": "file:",
     "username": "",
@@ -6928,7 +6928,7 @@
   },
   {
     "input": "file:////foo",
-    "base": "about:blank",
+    "base": null,
     "href": "file:////foo",
     "protocol": "file:",
     "username": "",
@@ -7027,7 +7027,7 @@
   "File URL tests for https://github.com/whatwg/url/issues/549",
   {
     "input": "file:.//p",
-    "base": "about:blank",
+    "base": null,
     "href": "file:////p",
     "protocol": "file:",
     "username": "",
@@ -7041,7 +7041,7 @@
   },
   {
     "input": "file:/.//p",
-    "base": "about:blank",
+    "base": null,
     "href": "file:////p",
     "protocol": "file:",
     "username": "",
@@ -7076,48 +7076,48 @@
   },
   {
     "input": "https://[0::0::0]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://[0:.0]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://[0:0:]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://[0:1:2:3:4:5:6:7.0.0.0.1]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://[0:1.00.0.0.0]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://[0:1.290.0.0.0]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://[0:1.23.23]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "# Empty host",
   {
     "input": "http://?",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://#",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "Port overflow (2^32 + 81)",
@@ -7141,7 +7141,7 @@
   "# Non-special-URL path tests",
   {
     "input": "sc://ñ",
-    "base": "about:blank",
+    "base": null,
     "href": "sc://%C3%B1",
     "origin": "null",
     "protocol": "sc:",
@@ -7156,7 +7156,7 @@
   },
   {
     "input": "sc://ñ?x",
-    "base": "about:blank",
+    "base": null,
     "href": "sc://%C3%B1?x",
     "origin": "null",
     "protocol": "sc:",
@@ -7171,7 +7171,7 @@
   },
   {
     "input": "sc://ñ#x",
-    "base": "about:blank",
+    "base": null,
     "href": "sc://%C3%B1#x",
     "origin": "null",
     "protocol": "sc:",
@@ -7216,7 +7216,7 @@
   },
   {
     "input": "sc://?",
-    "base": "about:blank",
+    "base": null,
     "href": "sc://?",
     "protocol": "sc:",
     "username": "",
@@ -7230,7 +7230,7 @@
   },
   {
     "input": "sc://#",
-    "base": "about:blank",
+    "base": null,
     "href": "sc://#",
     "protocol": "sc:",
     "username": "",
@@ -7286,7 +7286,7 @@
   },
   {
     "input": "tftp://foobar.com/someconfig;mode=netascii",
-    "base": "about:blank",
+    "base": null,
     "href": "tftp://foobar.com/someconfig;mode=netascii",
     "origin": "null",
     "protocol": "tftp:",
@@ -7301,7 +7301,7 @@
   },
   {
     "input": "telnet://user:pass@foobar.com:23/",
-    "base": "about:blank",
+    "base": null,
     "href": "telnet://user:pass@foobar.com:23/",
     "origin": "null",
     "protocol": "telnet:",
@@ -7316,7 +7316,7 @@
   },
   {
     "input": "ut2004://10.10.10.10:7777/Index.ut2",
-    "base": "about:blank",
+    "base": null,
     "href": "ut2004://10.10.10.10:7777/Index.ut2",
     "origin": "null",
     "protocol": "ut2004:",
@@ -7331,7 +7331,7 @@
   },
   {
     "input": "redis://foo:bar@somehost:6379/0?baz=bam&qux=baz",
-    "base": "about:blank",
+    "base": null,
     "href": "redis://foo:bar@somehost:6379/0?baz=bam&qux=baz",
     "origin": "null",
     "protocol": "redis:",
@@ -7346,7 +7346,7 @@
   },
   {
     "input": "rsync://foo@host:911/sup",
-    "base": "about:blank",
+    "base": null,
     "href": "rsync://foo@host:911/sup",
     "origin": "null",
     "protocol": "rsync:",
@@ -7361,7 +7361,7 @@
   },
   {
     "input": "git://github.com/foo/bar.git",
-    "base": "about:blank",
+    "base": null,
     "href": "git://github.com/foo/bar.git",
     "origin": "null",
     "protocol": "git:",
@@ -7376,7 +7376,7 @@
   },
   {
     "input": "irc://myserver.com:6999/channel?passwd",
-    "base": "about:blank",
+    "base": null,
     "href": "irc://myserver.com:6999/channel?passwd",
     "origin": "null",
     "protocol": "irc:",
@@ -7391,7 +7391,7 @@
   },
   {
     "input": "dns://fw.example.org:9999/foo.bar.org?type=TXT",
-    "base": "about:blank",
+    "base": null,
     "href": "dns://fw.example.org:9999/foo.bar.org?type=TXT",
     "origin": "null",
     "protocol": "dns:",
@@ -7406,7 +7406,7 @@
   },
   {
     "input": "ldap://localhost:389/ou=People,o=JNDITutorial",
-    "base": "about:blank",
+    "base": null,
     "href": "ldap://localhost:389/ou=People,o=JNDITutorial",
     "origin": "null",
     "protocol": "ldap:",
@@ -7421,7 +7421,7 @@
   },
   {
     "input": "git+https://github.com/foo/bar",
-    "base": "about:blank",
+    "base": null,
     "href": "git+https://github.com/foo/bar",
     "origin": "null",
     "protocol": "git+https:",
@@ -7436,7 +7436,7 @@
   },
   {
     "input": "urn:ietf:rfc:2648",
-    "base": "about:blank",
+    "base": null,
     "href": "urn:ietf:rfc:2648",
     "origin": "null",
     "protocol": "urn:",
@@ -7451,7 +7451,7 @@
   },
   {
     "input": "tag:joe@example.org,2001:foo/bar",
-    "base": "about:blank",
+    "base": null,
     "href": "tag:joe@example.org,2001:foo/bar",
     "origin": "null",
     "protocol": "tag:",
@@ -7467,7 +7467,7 @@
   "Serialize /. in path",
   {
     "input": "non-spec:/.//",
-    "base": "about:blank",
+    "base": null,
     "href": "non-spec:/.//",
     "protocol": "non-spec:",
     "username": "",
@@ -7481,7 +7481,7 @@
   },
   {
     "input": "non-spec:/..//",
-    "base": "about:blank",
+    "base": null,
     "href": "non-spec:/.//",
     "protocol": "non-spec:",
     "username": "",
@@ -7495,7 +7495,7 @@
   },
   {
     "input": "non-spec:/a/..//",
-    "base": "about:blank",
+    "base": null,
     "href": "non-spec:/.//",
     "protocol": "non-spec:",
     "username": "",
@@ -7509,7 +7509,7 @@
   },
   {
     "input": "non-spec:/.//path",
-    "base": "about:blank",
+    "base": null,
     "href": "non-spec:/.//path",
     "protocol": "non-spec:",
     "username": "",
@@ -7523,7 +7523,7 @@
   },
   {
     "input": "non-spec:/..//path",
-    "base": "about:blank",
+    "base": null,
     "href": "non-spec:/.//path",
     "protocol": "non-spec:",
     "username": "",
@@ -7537,7 +7537,7 @@
   },
   {
     "input": "non-spec:/a/..//path",
-    "base": "about:blank",
+    "base": null,
     "href": "non-spec:/.//path",
     "protocol": "non-spec:",
     "username": "",
@@ -7651,7 +7651,7 @@
   "# percent encoded hosts in non-special-URLs",
   {
     "input": "non-special://%E2%80%A0/",
-    "base": "about:blank",
+    "base": null,
     "href": "non-special://%E2%80%A0/",
     "protocol": "non-special:",
     "username": "",
@@ -7665,7 +7665,7 @@
   },
   {
     "input": "non-special://H%4fSt/path",
-    "base": "about:blank",
+    "base": null,
     "href": "non-special://H%4fSt/path",
     "protocol": "non-special:",
     "username": "",
@@ -7680,7 +7680,7 @@
   "# IPv6 in non-special-URLs",
   {
     "input": "non-special://[1:2:0:0:5:0:0:0]/",
-    "base": "about:blank",
+    "base": null,
     "href": "non-special://[1:2:0:0:5::]/",
     "protocol": "non-special:",
     "username": "",
@@ -7694,7 +7694,7 @@
   },
   {
     "input": "non-special://[1:2:0:0:0:0:0:3]/",
-    "base": "about:blank",
+    "base": null,
     "href": "non-special://[1:2::3]/",
     "protocol": "non-special:",
     "username": "",
@@ -7708,7 +7708,7 @@
   },
   {
     "input": "non-special://[1:2::3]:80/",
-    "base": "about:blank",
+    "base": null,
     "href": "non-special://[1:2::3]:80/",
     "protocol": "non-special:",
     "username": "",
@@ -7722,12 +7722,12 @@
   },
   {
     "input": "non-special://[:80/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "blob:https://example.com:443/",
-    "base": "about:blank",
+    "base": null,
     "href": "blob:https://example.com:443/",
     "origin": "https://example.com",
     "protocol": "blob:",
@@ -7742,7 +7742,7 @@
   },
   {
     "input": "blob:d3958f5c-0777-0845-9dcf-2cb28783acaf",
-    "base": "about:blank",
+    "base": null,
     "href": "blob:d3958f5c-0777-0845-9dcf-2cb28783acaf",
     "origin": "null",
     "protocol": "blob:",
@@ -7757,7 +7757,7 @@
   },
   {
     "input": "blob:",
-    "base": "about:blank",
+    "base": null,
     "href": "blob:",
     "origin": "null",
     "protocol": "blob:",
@@ -7773,7 +7773,7 @@
   "Invalid IPv4 radix digits",
   {
     "input": "http://0x7f.0.0.0x7g",
-    "base": "about:blank",
+    "base": null,
     "href": "http://0x7f.0.0.0x7g/",
     "protocol": "http:",
     "username": "",
@@ -7787,7 +7787,7 @@
   },
   {
     "input": "http://0X7F.0.0.0X7G",
-    "base": "about:blank",
+    "base": null,
     "href": "http://0x7f.0.0.0x7g/",
     "protocol": "http:",
     "username": "",
@@ -7802,13 +7802,13 @@
   "Invalid IPv4 portion of IPv6 address",
   {
     "input": "http://[::127.0.0.0.1]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "Uncompressed IPv6 addresses with 0",
   {
     "input": "http://[0:1:0:1:0:1:0:1]",
-    "base": "about:blank",
+    "base": null,
     "href": "http://[0:1:0:1:0:1:0:1]/",
     "protocol": "http:",
     "username": "",
@@ -7822,7 +7822,7 @@
   },
   {
     "input": "http://[1:0:1:0:1:0:1:0]",
-    "base": "about:blank",
+    "base": null,
     "href": "http://[1:0:1:0:1:0:1:0]/",
     "protocol": "http:",
     "username": "",
@@ -7837,7 +7837,7 @@
   "Percent-encoded query and fragment",
   {
     "input": "http://example.org/test?\u0022",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?%22",
     "protocol": "http:",
     "username": "",
@@ -7851,7 +7851,7 @@
   },
   {
     "input": "http://example.org/test?\u0023",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?#",
     "protocol": "http:",
     "username": "",
@@ -7865,7 +7865,7 @@
   },
   {
     "input": "http://example.org/test?\u003C",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?%3C",
     "protocol": "http:",
     "username": "",
@@ -7879,7 +7879,7 @@
   },
   {
     "input": "http://example.org/test?\u003E",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?%3E",
     "protocol": "http:",
     "username": "",
@@ -7893,7 +7893,7 @@
   },
   {
     "input": "http://example.org/test?\u2323",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?%E2%8C%A3",
     "protocol": "http:",
     "username": "",
@@ -7907,7 +7907,7 @@
   },
   {
     "input": "http://example.org/test?%23%23",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?%23%23",
     "protocol": "http:",
     "username": "",
@@ -7921,7 +7921,7 @@
   },
   {
     "input": "http://example.org/test?%GH",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?%GH",
     "protocol": "http:",
     "username": "",
@@ -7935,7 +7935,7 @@
   },
   {
     "input": "http://example.org/test?a#%EF",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?a#%EF",
     "protocol": "http:",
     "username": "",
@@ -7949,7 +7949,7 @@
   },
   {
     "input": "http://example.org/test?a#%GH",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?a#%GH",
     "protocol": "http:",
     "username": "",
@@ -7964,21 +7964,21 @@
   "URLs that require a non-about:blank base. (Also serve as invalid base tests.)",
   {
     "input": "a",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "a/",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "a//",
-    "base": "about:blank",
+    "base": null,
     "failure": true,
-    "inputCanBeRelative": true
+    "relativeTo": "non-opaque-path-base"
   },
   "Bases that don't fail to parse but fail to be bases",
   {
@@ -8051,7 +8051,7 @@
   "Null code point in fragment",
   {
     "input": "http://example.org/test?a#b\u0000c",
-    "base": "about:blank",
+    "base": null,
     "href": "http://example.org/test?a#b%00c",
     "protocol": "http:",
     "username": "",
@@ -8065,7 +8065,7 @@
   },
   {
     "input": "non-spec://example.org/test?a#b\u0000c",
-    "base": "about:blank",
+    "base": null,
     "href": "non-spec://example.org/test?a#b%00c",
     "protocol": "non-spec:",
     "username": "",
@@ -8079,7 +8079,7 @@
   },
   {
     "input": "non-spec:/test?a#b\u0000c",
-    "base": "about:blank",
+    "base": null,
     "href": "non-spec:/test?a#b%00c",
     "protocol": "non-spec:",
     "username": "",
@@ -8139,7 +8139,7 @@
   "IDNA ignored code points in file URLs hosts",
   {
     "input": "file://a\u00ADb/p",
-    "base": "about:blank",
+    "base": null,
     "href": "file://ab/p",
     "protocol": "file:",
     "username": "",
@@ -8153,7 +8153,7 @@
   },
   {
     "input": "file://a%C2%ADb/p",
-    "base": "about:blank",
+    "base": null,
     "href": "file://ab/p",
     "protocol": "file:",
     "username": "",
@@ -8168,7 +8168,7 @@
   "IDNA hostnames which get mapped to 'localhost'",
   {
     "input": "file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin",
-    "base": "about:blank",
+    "base": null,
     "href": "file:///usr/bin",
     "protocol": "file:",
     "username": "",
@@ -8183,17 +8183,17 @@
   "Empty host after the domain to ASCII",
   {
     "input": "file://\u00ad/p",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "file://%C2%AD/p",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "file://xn--/p",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "https://bugzilla.mozilla.org/show_bug.cgi?id=1647058",
@@ -8214,7 +8214,7 @@
   "UTF-8 percent-encode of C0 control percent-encode set and supersets",
   {
     "input": "non-special:cannot-be-a-base-url-\u0000\u0001\u001F\u001E\u007E\u007F\u0080",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "",
     "hostname": "",
@@ -8229,7 +8229,7 @@
   },
   {
     "input": "https://www.example.com/path{\u007Fpath.html?query'\u007F=query#fragment<\u007Ffragment",
-    "base": "about:blank",
+    "base": null,
     "hash": "#fragment%3C%7Ffragment",
     "host": "www.example.com",
     "hostname": "www.example.com",
@@ -8260,7 +8260,7 @@
   "Tests for the distinct percent-encode sets",
   {
     "input": "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -8275,7 +8275,7 @@
   },
   {
     "input": "wss:// !\"$%&'()*+,-.;<=>@[]^_`{|}~@host/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -8290,7 +8290,7 @@
   },
   {
     "input": "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -8305,7 +8305,7 @@
   },
   {
     "input": "wss://joe: !\"$%&'()*+,-.:;<=>@[]^_`{|}~@host/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -8320,7 +8320,7 @@
   },
   {
     "input": "foo://!\"$%&'()*+,-.;=_`{}~/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "!\"$%&'()*+,-.;=_`{}~",
     "hostname": "!\"$%&'()*+,-.;=_`{}~",
@@ -8335,7 +8335,7 @@
   },
   {
     "input": "wss://!\"$&'()*+,-.;=_`{}~/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "!\"$&'()*+,-.;=_`{}~",
     "hostname": "!\"$&'()*+,-.;=_`{}~",
@@ -8350,7 +8350,7 @@
   },
   {
     "input": "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -8365,7 +8365,7 @@
   },
   {
     "input": "wss://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -8380,7 +8380,7 @@
   },
   {
     "input": "foo://host/dir/? !\"$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -8395,7 +8395,7 @@
   },
   {
     "input": "wss://host/dir/? !\"$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "host",
     "hostname": "host",
@@ -8410,7 +8410,7 @@
   },
   {
     "input": "foo://host/dir/# !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-    "base": "about:blank",
+    "base": null,
     "hash": "#%20!%22#$%&'()*+,-./:;%3C=%3E?@[\\]^_%60{|}~",
     "host": "host",
     "hostname": "host",
@@ -8425,7 +8425,7 @@
   },
   {
     "input": "wss://host/dir/# !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-    "base": "about:blank",
+    "base": null,
     "hash": "#%20!%22#$%&'()*+,-./:;%3C=%3E?@[\\]^_%60{|}~",
     "host": "host",
     "hostname": "host",
@@ -8499,12 +8499,14 @@
   {
     "input": "#",
     "base": null,
-    "failure": true
+    "failure": true,
+    "relativeTo": "any-base"
   },
   {
     "input": "?",
     "base": null,
-    "failure": true
+    "failure": true,
+    "relativeTo": "non-opaque-path-base"
   },
   "Last component looks like a number, but not valid IPv4",
   {
@@ -8519,12 +8521,12 @@
   },
   {
     "input": "http://0..0x300/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://0..0x300./",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
@@ -8539,102 +8541,102 @@
   },
   {
     "input": "http://1.2.3.08",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://1.2.3.08.",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://1.2.3.09",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://09.2.3.4",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://09.2.3.4.",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://01.2.3.4.5",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://01.2.3.4.5.",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://0x100.2.3.4",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://0x100.2.3.4.",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://0x1.2.3.4.5",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://0x1.2.3.4.5.",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.1.2.3.4",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.1.2.3.4.",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.2.3.4",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.2.3.4.",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.09",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.09.",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.0x4",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.0x4.",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.09..",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "foo.09..",
     "hostname": "foo.09..",
@@ -8648,33 +8650,33 @@
   },
   {
     "input": "http://0999999999999999999/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.0x",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://foo.0XFfFfFfFfFfFfFfFfFfAcE123",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "http://💩.123/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "U+0000 and U+FFFF in various places",
   {
     "input": "https://\u0000y",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://x/\u0000y",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "x",
     "hostname": "x",
@@ -8688,7 +8690,7 @@
   },
   {
     "input": "https://x/?\u0000y",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "x",
     "hostname": "x",
@@ -8702,7 +8704,7 @@
   },
   {
     "input": "https://x/?#\u0000y",
-    "base": "about:blank",
+    "base": null,
     "hash": "#%00y",
     "host": "x",
     "hostname": "x",
@@ -8716,12 +8718,12 @@
   },
   {
     "input": "https://\uFFFFy",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://x/\uFFFFy",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "x",
     "hostname": "x",
@@ -8735,7 +8737,7 @@
   },
   {
     "input": "https://x/?\uFFFFy",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "x",
     "hostname": "x",
@@ -8749,7 +8751,7 @@
   },
   {
     "input": "https://x/?#\uFFFFy",
-    "base": "about:blank",
+    "base": null,
     "hash": "#%EF%BF%BFy",
     "host": "x",
     "hostname": "x",
@@ -8763,7 +8765,7 @@
   },
   {
     "input": "non-special:\u0000y",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "",
     "hostname": "",
@@ -8777,7 +8779,7 @@
   },
   {
     "input": "non-special:x/\u0000y",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "",
     "hostname": "",
@@ -8791,7 +8793,7 @@
   },
   {
     "input": "non-special:x/?\u0000y",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "",
     "hostname": "",
@@ -8805,7 +8807,7 @@
   },
   {
     "input": "non-special:x/?#\u0000y",
-    "base": "about:blank",
+    "base": null,
     "hash": "#%00y",
     "host": "",
     "hostname": "",
@@ -8819,7 +8821,7 @@
   },
   {
     "input": "non-special:\uFFFFy",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "",
     "hostname": "",
@@ -8833,7 +8835,7 @@
   },
   {
     "input": "non-special:x/\uFFFFy",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "",
     "hostname": "",
@@ -8847,7 +8849,7 @@
   },
   {
     "input": "non-special:x/?\uFFFFy",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "",
     "hostname": "",
@@ -8861,7 +8863,7 @@
   },
   {
     "input": "non-special:x/?#\uFFFFy",
-    "base": "about:blank",
+    "base": null,
     "hash": "#%EF%BF%BFy",
     "host": "",
     "hostname": "",
@@ -8875,12 +8877,13 @@
   },
   {
     "input": "",
-    "base": "about:blank",
-    "failure": true
+    "base": null,
+    "failure": true,
+    "relativeTo": "non-opaque-path-base"
   },
   {
     "input": "https://example.com/\"quoted\"",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "example.com",
     "hostname": "example.com",
@@ -8895,7 +8898,7 @@
   },
   {
     "input": "https://a%C2%ADb/",
-    "base": "about:blank",
+    "base": null,
     "hash": "",
     "host": "ab",
     "hostname": "ab",
@@ -8911,23 +8914,23 @@
   {
     "comment": "Empty host after domain to ASCII",
     "input": "https://\u00AD/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://%C2%AD/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "https://xn--/",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   "Non-special schemes that some implementations might incorrectly treat as special",
   {
     "input": "data://example.com:8080/pathname?search#hash",
-    "base": "about:blank",
+    "base": null,
     "href": "data://example.com:8080/pathname?search#hash",
     "origin": "null",
     "protocol": "data:",
@@ -8942,7 +8945,7 @@
   },
   {
     "input": "data:///test",
-    "base": "about:blank",
+    "base": null,
     "href": "data:///test",
     "origin": "null",
     "protocol": "data:",
@@ -8957,7 +8960,7 @@
   },
   {
     "input": "data://test/a/../b",
-    "base": "about:blank",
+    "base": null,
     "href": "data://test/b",
     "origin": "null",
     "protocol": "data:",
@@ -8972,22 +8975,22 @@
   },
   {
     "input": "data://:443",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "data://test:test",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "data://[:1]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "javascript://example.com:8080/pathname?search#hash",
-    "base": "about:blank",
+    "base": null,
     "href": "javascript://example.com:8080/pathname?search#hash",
     "origin": "null",
     "protocol": "javascript:",
@@ -9002,7 +9005,7 @@
   },
   {
     "input": "javascript:///test",
-    "base": "about:blank",
+    "base": null,
     "href": "javascript:///test",
     "origin": "null",
     "protocol": "javascript:",
@@ -9017,7 +9020,7 @@
   },
   {
     "input": "javascript://test/a/../b",
-    "base": "about:blank",
+    "base": null,
     "href": "javascript://test/b",
     "origin": "null",
     "protocol": "javascript:",
@@ -9032,22 +9035,22 @@
   },
   {
     "input": "javascript://:443",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "javascript://test:test",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "javascript://[:1]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "mailto://example.com:8080/pathname?search#hash",
-    "base": "about:blank",
+    "base": null,
     "href": "mailto://example.com:8080/pathname?search#hash",
     "origin": "null",
     "protocol": "mailto:",
@@ -9062,7 +9065,7 @@
   },
   {
     "input": "mailto:///test",
-    "base": "about:blank",
+    "base": null,
     "href": "mailto:///test",
     "origin": "null",
     "protocol": "mailto:",
@@ -9077,7 +9080,7 @@
   },
   {
     "input": "mailto://test/a/../b",
-    "base": "about:blank",
+    "base": null,
     "href": "mailto://test/b",
     "origin": "null",
     "protocol": "mailto:",
@@ -9092,22 +9095,22 @@
   },
   {
     "input": "mailto://:443",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "mailto://test:test",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "mailto://[:1]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "intent://example.com:8080/pathname?search#hash",
-    "base": "about:blank",
+    "base": null,
     "href": "intent://example.com:8080/pathname?search#hash",
     "origin": "null",
     "protocol": "intent:",
@@ -9122,7 +9125,7 @@
   },
   {
     "input": "intent:///test",
-    "base": "about:blank",
+    "base": null,
     "href": "intent:///test",
     "origin": "null",
     "protocol": "intent:",
@@ -9137,7 +9140,7 @@
   },
   {
     "input": "intent://test/a/../b",
-    "base": "about:blank",
+    "base": null,
     "href": "intent://test/b",
     "origin": "null",
     "protocol": "intent:",
@@ -9152,22 +9155,22 @@
   },
   {
     "input": "intent://:443",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "intent://test:test",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "intent://[:1]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "urn://example.com:8080/pathname?search#hash",
-    "base": "about:blank",
+    "base": null,
     "href": "urn://example.com:8080/pathname?search#hash",
     "origin": "null",
     "protocol": "urn:",
@@ -9182,7 +9185,7 @@
   },
   {
     "input": "urn:///test",
-    "base": "about:blank",
+    "base": null,
     "href": "urn:///test",
     "origin": "null",
     "protocol": "urn:",
@@ -9197,7 +9200,7 @@
   },
   {
     "input": "urn://test/a/../b",
-    "base": "about:blank",
+    "base": null,
     "href": "urn://test/b",
     "origin": "null",
     "protocol": "urn:",
@@ -9212,22 +9215,22 @@
   },
   {
     "input": "urn://:443",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "urn://test:test",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "urn://[:1]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "turn://example.com:8080/pathname?search#hash",
-    "base": "about:blank",
+    "base": null,
     "href": "turn://example.com:8080/pathname?search#hash",
     "origin": "null",
     "protocol": "turn:",
@@ -9242,7 +9245,7 @@
   },
   {
     "input": "turn:///test",
-    "base": "about:blank",
+    "base": null,
     "href": "turn:///test",
     "origin": "null",
     "protocol": "turn:",
@@ -9257,7 +9260,7 @@
   },
   {
     "input": "turn://test/a/../b",
-    "base": "about:blank",
+    "base": null,
     "href": "turn://test/b",
     "origin": "null",
     "protocol": "turn:",
@@ -9272,22 +9275,22 @@
   },
   {
     "input": "turn://:443",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "turn://test:test",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "turn://[:1]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "stun://example.com:8080/pathname?search#hash",
-    "base": "about:blank",
+    "base": null,
     "href": "stun://example.com:8080/pathname?search#hash",
     "origin": "null",
     "protocol": "stun:",
@@ -9302,7 +9305,7 @@
   },
   {
     "input": "stun:///test",
-    "base": "about:blank",
+    "base": null,
     "href": "stun:///test",
     "origin": "null",
     "protocol": "stun:",
@@ -9317,7 +9320,7 @@
   },
   {
     "input": "stun://test/a/../b",
-    "base": "about:blank",
+    "base": null,
     "href": "stun://test/b",
     "origin": "null",
     "protocol": "stun:",
@@ -9332,17 +9335,17 @@
   },
   {
     "input": "stun://:443",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "stun://test:test",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   },
   {
     "input": "stun://[:1]",
-    "base": "about:blank",
+    "base": null,
     "failure": true
   }
 ]
diff --git a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js
index 297b8ff..bea06d0 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js
+++ b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js
@@ -5,14 +5,13 @@
 // META: variant=?include=mailto
 // META: variant=?exclude=(file|javascript|mailto)
 
-function bURL(url, base) {
-  return base ? new URL(url, base) : new URL(url)
-}
+function runURLTests(urlTests) {
+  for (const expected of urlTests) {
+    // Skip comments
+    if (typeof expected === "string")
+      continue;
 
-function runURLTests(urltests) {
-  for(var i = 0, l = urltests.length; i < l; i++) {
-    var expected = urltests[i]
-    if (typeof expected === "string") continue // skip comments
+    const base = expected.base !== null ? expected.base : undefined;
 
     function getKey(expected) {
       if (expected.protocol) {
@@ -27,12 +26,12 @@
     subsetTestByKey(getKey(expected), test, function() {
       if (expected.failure) {
         assert_throws_js(TypeError, function() {
-          bURL(expected.input, expected.base)
-        })
-        return
+          new URL(expected.input, base);
+        });
+        return;
       }
 
-      var url = bURL(expected.input, expected.base)
+      const url = new URL(expected.input, base);
       assert_equals(url.href, expected.href, "href")
       assert_equals(url.protocol, expected.protocol, "protocol")
       assert_equals(url.username, expected.username, "username")
@@ -47,7 +46,7 @@
         assert_equals(url.searchParams.toString(), expected.searchParams, "searchParams")
       }
       assert_equals(url.hash, expected.hash, "hash")
-    }, "Parsing: <" + expected.input + "> against <" + expected.base + ">")
+    }, `Parsing: <${expected.input}> ${base ? "against <" + base + ">" : "without base"}`)
   }
 }
 
diff --git a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js.ini b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js.ini
index 93bf975e..70d3d3411 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js.ini
@@ -53,11 +53,11 @@
   [Parsing: <?x> against <sc://ñ>]
     expected: FAIL
 
-  [Parsing: <\\\\\\.\\Y:> against <about:blank>]
+  [Parsing: <\\\\\\.\\Y:> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <\\\\\\.\\y:> against <about:blank>]
+  [Parsing: <\\\\\\.\\y:> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
@@ -81,47 +81,47 @@
   [Parsing: <abc:rootless> against <abc:/path>]
     expected: FAIL
 
-  [Parsing: <about:/../> against <about:blank>]
+  [Parsing: <about:/../> without base]
     expected: FAIL
 
-  [Parsing: <asdf://%43%7C/> against <about:blank>]
+  [Parsing: <asdf://%43%7C/> without base]
     expected: FAIL
 
-  [Parsing: <asdf://%43|/> against <about:blank>]
+  [Parsing: <asdf://%43|/> without base]
     expected: FAIL
 
   [Parsing: <c:/foo> against <http://example.org/foo/bar>]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <data:/../> against <about:blank>]
+  [Parsing: <data:/../> without base]
     expected: FAIL
 
-  [Parsing: <data:///test> against <about:blank>]
+  [Parsing: <data:///test> without base]
     expected: FAIL
 
-  [Parsing: <data://:443> against <about:blank>]
+  [Parsing: <data://:443> without base]
     expected: FAIL
 
-  [Parsing: <data://[:1\]> against <about:blank>]
+  [Parsing: <data://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <data://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <data://test/a/../b> against <about:blank>]
+  [Parsing: <data://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <data://test:test> against <about:blank>]
+  [Parsing: <data://test:test> without base]
     expected: FAIL
 
-  [Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>]
+  [Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base]
     expected: FAIL
 
-  [Parsing: <foo:// !"$%&'()*+,-.;<=>@[\\\]^_`{|}~@host/> against <about:blank>]
+  [Parsing: <foo:// !"$%&'()*+,-.;<=>@[\\\]^_`{|}~@host/> without base]
     expected: FAIL
 
-  [Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
   [Parsing: <foo://///////> against <http://example.org/foo/bar>]
@@ -136,43 +136,43 @@
   [Parsing: <foo://> against <http://example.org/foo/bar>]
     expected: FAIL
 
-  [Parsing: <foo://ho\tst/> against <about:blank>]
+  [Parsing: <foo://ho\tst/> without base]
     expected: FAIL
 
-  [Parsing: <foo://ho\nst/> against <about:blank>]
+  [Parsing: <foo://ho\nst/> without base]
     expected: FAIL
 
-  [Parsing: <foo://ho\rst/> against <about:blank>]
+  [Parsing: <foo://ho\rst/> without base]
     expected: FAIL
 
-  [Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\\\]^_`{|}~> against <about:blank>]
+  [Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\\\]^_`{|}~> without base]
     expected: FAIL
 
-  [Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~> against <about:blank>]
+  [Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~> without base]
     expected: FAIL
 
-  [Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\\\]^_`{|}~> against <about:blank>]
+  [Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\\\]^_`{|}~> without base]
     expected: FAIL
 
-  [Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\\\]^_`{|}~@host/> against <about:blank>]
+  [Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\\\]^_`{|}~@host/> without base]
     expected: FAIL
 
-  [Parsing: <git+https://github.com/foo/bar> against <about:blank>]
+  [Parsing: <git+https://github.com/foo/bar> without base]
     expected: FAIL
 
-  [Parsing: <git://github.com/foo/bar.git> against <about:blank>]
+  [Parsing: <git://github.com/foo/bar.git> without base]
     expected: FAIL
 
-  [Parsing: <gopher://foo:443/> against <about:blank>]
+  [Parsing: <gopher://foo:443/> without base]
     expected: FAIL
 
-  [Parsing: <gopher://foo:70/> against <about:blank>]
+  [Parsing: <gopher://foo:70/> without base]
     expected: FAIL
 
-  [Parsing: <h://.> against <about:blank>]
+  [Parsing: <h://.> without base]
     expected: FAIL
 
-  [Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
   [Parsing: <http://%5B::1\]> against <http://other.com/>]
@@ -181,13 +181,13 @@
   [Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/>]
     expected: FAIL
 
-  [Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank>]
+  [Parsing: <http://10.0.0.XN--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank>]
+  [Parsing: <http://10.0.0.xN--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank>]
+  [Parsing: <http://10.0.0.xn--pokxncvks> without base]
     expected: FAIL
 
   [Parsing: <http://192.168.0.1 hello> against <http://other.com/>]
@@ -214,91 +214,91 @@
   [Parsing: <http://[::127.0.0.1.\]> against <http://example.org/foo/bar>]
     expected: FAIL
 
-  [Parsing: <http://a b/> against <about:blank>]
+  [Parsing: <http://a b/> without base]
     expected: FAIL
 
-  [Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank>]
+  [Parsing: <http://a.b.c.XN--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank>]
+  [Parsing: <http://a.b.c.Xn--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank>]
+  [Parsing: <http://a.b.c.xn--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://a<b> against <about:blank>]
+  [Parsing: <http://a<b> without base]
     expected: FAIL
 
-  [Parsing: <http://a>b> against <about:blank>]
+  [Parsing: <http://a>b> without base]
     expected: FAIL
 
-  [Parsing: <http://a|b/> against <about:blank>]
+  [Parsing: <http://a|b/> without base]
     expected: FAIL
 
   [Parsing: <http://example example.com> against <http://other.com/>]
     expected: FAIL
 
-  [Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank>]
+  [Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base]
     expected: FAIL
 
-  [Parsing: <http://example.com/foo%00%51> against <about:blank>]
+  [Parsing: <http://example.com/foo%00%51> without base]
     expected: FAIL
 
-  [Parsing: <http://example.com/foo%41%7a> against <about:blank>]
+  [Parsing: <http://example.com/foo%41%7a> without base]
     expected: FAIL
 
-  [Parsing: <http://example.com/foo/%2e%2> against <about:blank>]
+  [Parsing: <http://example.com/foo/%2e%2> without base]
     expected: FAIL
 
-  [Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>]
+  [Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%20st/> against <about:blank>]
+  [Parsing: <http://ho%20st/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%23st/> against <about:blank>]
+  [Parsing: <http://ho%23st/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%3Cst/> against <about:blank>]
+  [Parsing: <http://ho%3Cst/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%3Est/> against <about:blank>]
+  [Parsing: <http://ho%3Est/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%40st/> against <about:blank>]
+  [Parsing: <http://ho%40st/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%7Cst/> against <about:blank>]
+  [Parsing: <http://ho%7Cst/> without base]
     expected: FAIL
 
-  [Parsing: <http://www/foo%2Ehtml> against <about:blank>]
+  [Parsing: <http://www/foo%2Ehtml> without base]
     expected: FAIL
 
   [Parsing: <http://%41.com> against <http://other.com/>]
     expected: FAIL
 
-  [Parsing: <httpa://foo:80/> against <about:blank>]
+  [Parsing: <httpa://foo:80/> without base]
     expected: FAIL
 
-  [Parsing: <https://%43%7C/> against <about:blank>]
+  [Parsing: <https://%43%7C/> without base]
     expected: FAIL
 
-  [Parsing: <https://x x:12> against <about:blank>]
+  [Parsing: <https://x x:12> without base]
     expected: FAIL
 
-  [Parsing: <https://x/\x00y> against <about:blank>]
+  [Parsing: <https://x/\x00y> without base]
     expected: FAIL
 
-  [Parsing: <https://x/?#￿y> against <about:blank>]
+  [Parsing: <https://x/?#￿y> without base]
     expected: FAIL
 
-  [Parsing: <https://x/?￿y> against <about:blank>]
+  [Parsing: <https://x/?￿y> without base]
     expected: FAIL
 
-  [Parsing: <https://x/￿y> against <about:blank>]
+  [Parsing: <https://x/￿y> without base]
     expected: FAIL
 
-  [Parsing: <https://xn--/> against <about:blank>]
+  [Parsing: <https://xn--/> without base]
     expected: FAIL
 
   [Parsing: <i> against <sc:///pa/pa>]
@@ -307,190 +307,190 @@
   [Parsing: <i> against <sc://ho/pa>]
     expected: FAIL
 
-  [Parsing: <intent:///test> against <about:blank>]
+  [Parsing: <intent:///test> without base]
     expected: FAIL
 
-  [Parsing: <intent://:443> against <about:blank>]
+  [Parsing: <intent://:443> without base]
     expected: FAIL
 
-  [Parsing: <intent://[:1\]> against <about:blank>]
+  [Parsing: <intent://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <intent://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <intent://test/a/../b> against <about:blank>]
+  [Parsing: <intent://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <intent://test:test> against <about:blank>]
+  [Parsing: <intent://test:test> without base]
     expected: FAIL
 
-  [Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>]
+  [Parsing: <irc://myserver.com:6999/channel?passwd> without base]
     expected: FAIL
 
-  [Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>]
+  [Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/..//> against <about:blank>]
+  [Parsing: <non-spec:/..//> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/..//path> against <about:blank>]
+  [Parsing: <non-spec:/..//path> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/.//> against <about:blank>]
+  [Parsing: <non-spec:/.//> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/.//path> against <about:blank>]
+  [Parsing: <non-spec:/.//path> without base]
     expected: FAIL
 
-  [Parsing: <non-spec://example.org/test?a#b\x00c> against <about:blank>]
+  [Parsing: <non-spec://example.org/test?a#b\x00c> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/a/..//> against <about:blank>]
+  [Parsing: <non-spec:/a/..//> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/a/..//path> against <about:blank>]
+  [Parsing: <non-spec:/a/..//path> without base]
     expected: FAIL
 
-  [Parsing: <non-special://%E2%80%A0/> against <about:blank>]
+  [Parsing: <non-special://%E2%80%A0/> without base]
     expected: FAIL
 
-  [Parsing: <non-special://:@test/x> against <about:blank>]
+  [Parsing: <non-special://:@test/x> without base]
     expected: FAIL
 
-  [Parsing: <non-special://H%4fSt/path> against <about:blank>]
+  [Parsing: <non-special://H%4fSt/path> without base]
     expected: FAIL
 
-  [Parsing: <non-special://[1:2:0:0:0:0:0:3\]/> against <about:blank>]
+  [Parsing: <non-special://[1:2:0:0:0:0:0:3\]/> without base]
     expected: FAIL
 
-  [Parsing: <non-special://[1:2:0:0:5:0:0:0\]/> against <about:blank>]
+  [Parsing: <non-special://[1:2:0:0:5:0:0:0\]/> without base]
     expected: FAIL
 
-  [Parsing: <non-special://[1:2::3\]:80/> against <about:blank>]
+  [Parsing: <non-special://[1:2::3\]:80/> without base]
     expected: FAIL
 
-  [Parsing: <non-special://[:80/> against <about:blank>]
+  [Parsing: <non-special://[:80/> without base]
     expected: FAIL
 
   [Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar>]
     expected: FAIL
 
-  [Parsing: <non-special://test:@test/x> against <about:blank>]
+  [Parsing: <non-special://test:@test/x> without base]
     expected: FAIL
 
-  [Parsing: <non-special:x/?#￿y> against <about:blank>]
+  [Parsing: <non-special:x/?#￿y> without base]
     expected: FAIL
 
-  [Parsing: <non-special:x/?￿y> against <about:blank>]
+  [Parsing: <non-special:x/?￿y> without base]
     expected: FAIL
 
-  [Parsing: <non-special:x/￿y> against <about:blank>]
+  [Parsing: <non-special:x/￿y> without base]
     expected: FAIL
 
-  [Parsing: <non-special:￿y> against <about:blank>]
+  [Parsing: <non-special:￿y> without base]
     expected: FAIL
 
-  [Parsing: <notspecial://host/?'> against <about:blank>]
+  [Parsing: <notspecial://host/?'> without base]
     expected: FAIL
 
   [Parsing: <path> against <non-spec:/..//p>]
     expected: FAIL
 
-  [Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>]
+  [Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base]
     expected: FAIL
 
-  [Parsing: <rsync://foo@host:911/sup> against <about:blank>]
+  [Parsing: <rsync://foo@host:911/sup> without base]
     expected: FAIL
 
-  [Parsing: <sc://\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f!"$%&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Parsing: <sc://\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f!"$%&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
-  [Parsing: <sc://#> against <about:blank>]
+  [Parsing: <sc://#> without base]
     expected: FAIL
 
-  [Parsing: <sc://%/> against <about:blank>]
+  [Parsing: <sc://%/> without base]
     expected: FAIL
 
-  [Parsing: <sc://:/> against <about:blank>]
+  [Parsing: <sc://:/> without base]
     expected: FAIL
 
-  [Parsing: <sc://:12/> against <about:blank>]
+  [Parsing: <sc://:12/> without base]
     expected: FAIL
 
-  [Parsing: <sc://?> against <about:blank>]
+  [Parsing: <sc://?> without base]
     expected: FAIL
 
-  [Parsing: <sc://@/> against <about:blank>]
+  [Parsing: <sc://@/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a\x00b/> against <about:blank>]
+  [Parsing: <sc://a\x00b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a b/> against <about:blank>]
+  [Parsing: <sc://a b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a<b> against <about:blank>]
+  [Parsing: <sc://a<b> without base]
     expected: FAIL
 
-  [Parsing: <sc://a>b> against <about:blank>]
+  [Parsing: <sc://a>b> without base]
     expected: FAIL
 
-  [Parsing: <sc://a[b/> against <about:blank>]
+  [Parsing: <sc://a[b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a\\b/> against <about:blank>]
+  [Parsing: <sc://a\\b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a\]b/> against <about:blank>]
+  [Parsing: <sc://a\]b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a^b> against <about:blank>]
+  [Parsing: <sc://a^b> without base]
     expected: FAIL
 
-  [Parsing: <sc://a|b/> against <about:blank>]
+  [Parsing: <sc://a|b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://faß.ExAmPlE/> against <about:blank>]
+  [Parsing: <sc://faß.ExAmPlE/> without base]
     expected: FAIL
 
-  [Parsing: <sc://te@s:t@/> against <about:blank>]
+  [Parsing: <sc://te@s:t@/> without base]
     expected: FAIL
 
-  [Parsing: <sc://ñ#x> against <about:blank>]
+  [Parsing: <sc://ñ#x> without base]
     expected: FAIL
 
-  [Parsing: <sc://ñ.test/> against <about:blank>]
+  [Parsing: <sc://ñ.test/> without base]
     expected: FAIL
 
-  [Parsing: <sc://ñ> against <about:blank>]
+  [Parsing: <sc://ñ> without base]
     expected: FAIL
 
-  [Parsing: <sc://ñ?x> against <about:blank>]
+  [Parsing: <sc://ñ?x> without base]
     expected: FAIL
 
   [Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>]
     expected: FAIL
 
-  [Parsing: <stun:///test> against <about:blank>]
+  [Parsing: <stun:///test> without base]
     expected: FAIL
 
-  [Parsing: <stun://:443> against <about:blank>]
+  [Parsing: <stun://:443> without base]
     expected: FAIL
 
-  [Parsing: <stun://[:1\]> against <about:blank>]
+  [Parsing: <stun://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <stun://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <stun://test/a/../b> against <about:blank>]
+  [Parsing: <stun://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <stun://test:test> against <about:blank>]
+  [Parsing: <stun://test:test> without base]
     expected: FAIL
 
-  [Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>]
+  [Parsing: <telnet://user:pass@foobar.com:23/> without base]
     expected: FAIL
 
   [Parsing: <test-a-colon-b.html> against <a:b>]
@@ -515,61 +515,61 @@
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>]
+  [Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base]
     expected: FAIL
 
-  [Parsing: <turn:///test> against <about:blank>]
+  [Parsing: <turn:///test> without base]
     expected: FAIL
 
-  [Parsing: <turn://:443> against <about:blank>]
+  [Parsing: <turn://:443> without base]
     expected: FAIL
 
-  [Parsing: <turn://[:1\]> against <about:blank>]
+  [Parsing: <turn://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <turn://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <turn://test/a/../b> against <about:blank>]
+  [Parsing: <turn://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <turn://test:test> against <about:blank>]
+  [Parsing: <turn://test:test> without base]
     expected: FAIL
 
-  [Parsing: <urn:///test> against <about:blank>]
+  [Parsing: <urn:///test> without base]
     expected: FAIL
 
-  [Parsing: <urn://:443> against <about:blank>]
+  [Parsing: <urn://:443> without base]
     expected: FAIL
 
-  [Parsing: <urn://[:1\]> against <about:blank>]
+  [Parsing: <urn://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <urn://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <urn://test/a/../b> against <about:blank>]
+  [Parsing: <urn://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <urn://test:test> against <about:blank>]
+  [Parsing: <urn://test:test> without base]
     expected: FAIL
 
-  [Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>]
+  [Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base]
     expected: FAIL
 
-  [Parsing: <wow:￿> against <about:blank>]
+  [Parsing: <wow:￿> without base]
     expected: FAIL
 
-  [Parsing: <wss:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>]
+  [Parsing: <wss:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base]
     expected: FAIL
 
-  [Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
-  [Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\\\]^_`{|}~> against <about:blank>]
+  [Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\\\]^_`{|}~> without base]
     expected: FAIL
 
-  [Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>]
+  [Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base]
     expected: FAIL
 
   [Parsing: <x> against <sc://ñ>]
@@ -675,7 +675,7 @@
   [Parsing: <\\/localhost//pig> against <file://lion/>]
     expected: FAIL
 
-  [Parsing: <file:#frag> against <about:blank>]
+  [Parsing: <file:#frag> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
@@ -687,42 +687,42 @@
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:.//p> against <about:blank>]
+  [Parsing: <file:.//p> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:/.//p> against <about:blank>]
+  [Parsing: <file:/.//p> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file://%43%7C/> against <about:blank>]
+  [Parsing: <file://%43%7C/> without base]
     expected: FAIL
 
-  [Parsing: <file://%43%7C> against <about:blank>]
+  [Parsing: <file://%43%7C> without base]
     expected: FAIL
 
-  [Parsing: <file://%43|> against <about:blank>]
+  [Parsing: <file://%43|> without base]
     expected: FAIL
 
-  [Parsing: <file:///./y:> against <about:blank>]
+  [Parsing: <file:///./y:> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:////foo> against <about:blank>]
+  [Parsing: <file:////foo> without base]
     expected: FAIL
 
   [Parsing: <file:////one/two> against <file:///>]
     expected: FAIL
 
-  [Parsing: <file:///y:/> against <about:blank>]
+  [Parsing: <file:///y:/> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:///y:> against <about:blank>]
+  [Parsing: <file:///y:> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file://C%7C> against <about:blank>]
+  [Parsing: <file://C%7C> without base]
     expected: FAIL
 
   [Parsing: <file://C:/> against <file://host/>]
@@ -730,24 +730,24 @@
       if (product == "content_shell") and (os == "win"): PASS
       FAIL
 
-  [Parsing: <file://C|/> against <about:blank>]
+  [Parsing: <file://C|/> without base]
     expected:
       if (product == "content_shell") and (os == "win"): PASS
       FAIL
 
-  [Parsing: <file://\\/localhost//cat> against <about:blank>]
+  [Parsing: <file://\\/localhost//cat> without base]
     expected: FAIL
 
-  [Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank>]
+  [Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base]
     expected: FAIL
 
-  [Parsing: <file://localhost////foo> against <about:blank>]
+  [Parsing: <file://localhost////foo> without base]
     expected: FAIL
 
-  [Parsing: <file://localhost//a//../..//> against <about:blank>]
+  [Parsing: <file://localhost//a//../..//> without base]
     expected: FAIL
 
-  [Parsing: <file://localhost//a//../..//foo> against <about:blank>]
+  [Parsing: <file://localhost//a//../..//foo> without base]
     expected: FAIL
 
   [Parsing: <file://localhost/> against <file:///tmp/mock/path>]
@@ -759,27 +759,27 @@
   [Parsing: <file://localhost> against <file:///tmp/mock/path>]
     expected: FAIL
 
-  [Parsing: <file://xn--/p> against <about:blank>]
+  [Parsing: <file://xn--/p> without base]
     expected: FAIL
 
   [Parsing: <file:/C:/> against <file://host/>]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:/C|/> against <about:blank>]
+  [Parsing: <file:/C|/> without base]
     expected:
       if (product == "content_shell") and (os == "win"): PASS
       FAIL
 
-  [Parsing: <file:/example.com/> against <about:blank>]
-    expected:
-      if (product == "content_shell") and (os == "win"): FAIL
-
   [Parsing: <file:/example.com/> against <http://example.org/foo/bar>]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:?q=v> against <about:blank>]
+  [Parsing: <file:/example.com/> without base]
+    expected:
+      if (product == "content_shell") and (os == "win"): FAIL
+
+  [Parsing: <file:?q=v> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
@@ -787,19 +787,19 @@
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:\\\\//> against <about:blank>]
+  [Parsing: <file:\\\\//> without base]
     expected: FAIL
 
-  [Parsing: <file:\\\\\\\\#guppy> against <about:blank>]
+  [Parsing: <file:\\\\\\\\#guppy> without base]
     expected: FAIL
 
-  [Parsing: <file:\\\\\\\\> against <about:blank>]
+  [Parsing: <file:\\\\\\\\> without base]
     expected: FAIL
 
-  [Parsing: <file:\\\\\\\\?fox> against <about:blank>]
+  [Parsing: <file:\\\\\\\\?fox> without base]
     expected: FAIL
 
-  [Parsing: <file:\\\\localhost//> against <about:blank>]
+  [Parsing: <file:\\\\localhost//> without base]
     expected: FAIL
 
   [Parsing: <file:\\c:\\foo\\bar> against <file:///c:/baz/qux>]
@@ -815,48 +815,48 @@
 
 
 [url-constructor.any.html?include=javascript]
-  [Parsing: <javascript:/../> against <about:blank>]
+  [Parsing: <javascript:/../> without base]
     expected: FAIL
 
-  [Parsing: <javascript:///test> against <about:blank>]
+  [Parsing: <javascript:///test> without base]
     expected: FAIL
 
-  [Parsing: <javascript://:443> against <about:blank>]
+  [Parsing: <javascript://:443> without base]
     expected: FAIL
 
-  [Parsing: <javascript://[:1\]> against <about:blank>]
+  [Parsing: <javascript://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <javascript://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <javascript://test/a/../b> against <about:blank>]
+  [Parsing: <javascript://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <javascript://test:test> against <about:blank>]
+  [Parsing: <javascript://test:test> without base]
     expected: FAIL
 
 
 [url-constructor.any.html?include=mailto]
-  [Parsing: <mailto:/../> against <about:blank>]
+  [Parsing: <mailto:/../> without base]
     expected: FAIL
 
-  [Parsing: <mailto:///test> against <about:blank>]
+  [Parsing: <mailto:///test> without base]
     expected: FAIL
 
-  [Parsing: <mailto://:443> against <about:blank>]
+  [Parsing: <mailto://:443> without base]
     expected: FAIL
 
-  [Parsing: <mailto://[:1\]> against <about:blank>]
+  [Parsing: <mailto://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <mailto://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <mailto://test/a/../b> against <about:blank>]
+  [Parsing: <mailto://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <mailto://test:test> against <about:blank>]
+  [Parsing: <mailto://test:test> without base]
     expected: FAIL
 
 
@@ -915,11 +915,11 @@
   [Parsing: <?x> against <sc://ñ>]
     expected: FAIL
 
-  [Parsing: <\\\\\\.\\Y:> against <about:blank>]
+  [Parsing: <\\\\\\.\\Y:> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <\\\\\\.\\y:> against <about:blank>]
+  [Parsing: <\\\\\\.\\y:> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
@@ -943,47 +943,47 @@
   [Parsing: <abc:rootless> against <abc:/path>]
     expected: FAIL
 
-  [Parsing: <about:/../> against <about:blank>]
+  [Parsing: <about:/../> without base]
     expected: FAIL
 
-  [Parsing: <asdf://%43%7C/> against <about:blank>]
+  [Parsing: <asdf://%43%7C/> without base]
     expected: FAIL
 
-  [Parsing: <asdf://%43|/> against <about:blank>]
+  [Parsing: <asdf://%43|/> without base]
     expected: FAIL
 
   [Parsing: <c:/foo> against <http://example.org/foo/bar>]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <data:/../> against <about:blank>]
+  [Parsing: <data:/../> without base]
     expected: FAIL
 
-  [Parsing: <data:///test> against <about:blank>]
+  [Parsing: <data:///test> without base]
     expected: FAIL
 
-  [Parsing: <data://:443> against <about:blank>]
+  [Parsing: <data://:443> without base]
     expected: FAIL
 
-  [Parsing: <data://[:1\]> against <about:blank>]
+  [Parsing: <data://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <data://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <data://test/a/../b> against <about:blank>]
+  [Parsing: <data://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <data://test:test> against <about:blank>]
+  [Parsing: <data://test:test> without base]
     expected: FAIL
 
-  [Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>]
+  [Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base]
     expected: FAIL
 
-  [Parsing: <foo:// !"$%&'()*+,-.;<=>@[\\\]^_`{|}~@host/> against <about:blank>]
+  [Parsing: <foo:// !"$%&'()*+,-.;<=>@[\\\]^_`{|}~@host/> without base]
     expected: FAIL
 
-  [Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
   [Parsing: <foo://///////> against <http://example.org/foo/bar>]
@@ -998,43 +998,43 @@
   [Parsing: <foo://> against <http://example.org/foo/bar>]
     expected: FAIL
 
-  [Parsing: <foo://ho\tst/> against <about:blank>]
+  [Parsing: <foo://ho\tst/> without base]
     expected: FAIL
 
-  [Parsing: <foo://ho\nst/> against <about:blank>]
+  [Parsing: <foo://ho\nst/> without base]
     expected: FAIL
 
-  [Parsing: <foo://ho\rst/> against <about:blank>]
+  [Parsing: <foo://ho\rst/> without base]
     expected: FAIL
 
-  [Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\\\]^_`{|}~> against <about:blank>]
+  [Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\\\]^_`{|}~> without base]
     expected: FAIL
 
-  [Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~> against <about:blank>]
+  [Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~> without base]
     expected: FAIL
 
-  [Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\\\]^_`{|}~> against <about:blank>]
+  [Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\\\]^_`{|}~> without base]
     expected: FAIL
 
-  [Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\\\]^_`{|}~@host/> against <about:blank>]
+  [Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\\\]^_`{|}~@host/> without base]
     expected: FAIL
 
-  [Parsing: <git+https://github.com/foo/bar> against <about:blank>]
+  [Parsing: <git+https://github.com/foo/bar> without base]
     expected: FAIL
 
-  [Parsing: <git://github.com/foo/bar.git> against <about:blank>]
+  [Parsing: <git://github.com/foo/bar.git> without base]
     expected: FAIL
 
-  [Parsing: <gopher://foo:443/> against <about:blank>]
+  [Parsing: <gopher://foo:443/> without base]
     expected: FAIL
 
-  [Parsing: <gopher://foo:70/> against <about:blank>]
+  [Parsing: <gopher://foo:70/> without base]
     expected: FAIL
 
-  [Parsing: <h://.> against <about:blank>]
+  [Parsing: <h://.> without base]
     expected: FAIL
 
-  [Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
   [Parsing: <http://%5B::1\]> against <http://other.com/>]
@@ -1043,13 +1043,13 @@
   [Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/>]
     expected: FAIL
 
-  [Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank>]
+  [Parsing: <http://10.0.0.XN--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank>]
+  [Parsing: <http://10.0.0.xN--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank>]
+  [Parsing: <http://10.0.0.xn--pokxncvks> without base]
     expected: FAIL
 
   [Parsing: <http://192.168.0.1 hello> against <http://other.com/>]
@@ -1076,91 +1076,91 @@
   [Parsing: <http://[::127.0.0.1.\]> against <http://example.org/foo/bar>]
     expected: FAIL
 
-  [Parsing: <http://a b/> against <about:blank>]
+  [Parsing: <http://a b/> without base]
     expected: FAIL
 
-  [Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank>]
+  [Parsing: <http://a.b.c.XN--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank>]
+  [Parsing: <http://a.b.c.Xn--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank>]
+  [Parsing: <http://a.b.c.xn--pokxncvks> without base]
     expected: FAIL
 
-  [Parsing: <http://a<b> against <about:blank>]
+  [Parsing: <http://a<b> without base]
     expected: FAIL
 
-  [Parsing: <http://a>b> against <about:blank>]
+  [Parsing: <http://a>b> without base]
     expected: FAIL
 
-  [Parsing: <http://a|b/> against <about:blank>]
+  [Parsing: <http://a|b/> without base]
     expected: FAIL
 
   [Parsing: <http://example example.com> against <http://other.com/>]
     expected: FAIL
 
-  [Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank>]
+  [Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base]
     expected: FAIL
 
-  [Parsing: <http://example.com/foo%00%51> against <about:blank>]
+  [Parsing: <http://example.com/foo%00%51> without base]
     expected: FAIL
 
-  [Parsing: <http://example.com/foo%41%7a> against <about:blank>]
+  [Parsing: <http://example.com/foo%41%7a> without base]
     expected: FAIL
 
-  [Parsing: <http://example.com/foo/%2e%2> against <about:blank>]
+  [Parsing: <http://example.com/foo/%2e%2> without base]
     expected: FAIL
 
-  [Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>]
+  [Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%20st/> against <about:blank>]
+  [Parsing: <http://ho%20st/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%23st/> against <about:blank>]
+  [Parsing: <http://ho%23st/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%3Cst/> against <about:blank>]
+  [Parsing: <http://ho%3Cst/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%3Est/> against <about:blank>]
+  [Parsing: <http://ho%3Est/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%40st/> against <about:blank>]
+  [Parsing: <http://ho%40st/> without base]
     expected: FAIL
 
-  [Parsing: <http://ho%7Cst/> against <about:blank>]
+  [Parsing: <http://ho%7Cst/> without base]
     expected: FAIL
 
-  [Parsing: <http://www/foo%2Ehtml> against <about:blank>]
+  [Parsing: <http://www/foo%2Ehtml> without base]
     expected: FAIL
 
   [Parsing: <http://%41.com> against <http://other.com/>]
     expected: FAIL
 
-  [Parsing: <httpa://foo:80/> against <about:blank>]
+  [Parsing: <httpa://foo:80/> without base]
     expected: FAIL
 
-  [Parsing: <https://%43%7C/> against <about:blank>]
+  [Parsing: <https://%43%7C/> without base]
     expected: FAIL
 
-  [Parsing: <https://x x:12> against <about:blank>]
+  [Parsing: <https://x x:12> without base]
     expected: FAIL
 
-  [Parsing: <https://x/\x00y> against <about:blank>]
+  [Parsing: <https://x/\x00y> without base]
     expected: FAIL
 
-  [Parsing: <https://x/?#￿y> against <about:blank>]
+  [Parsing: <https://x/?#￿y> without base]
     expected: FAIL
 
-  [Parsing: <https://x/?￿y> against <about:blank>]
+  [Parsing: <https://x/?￿y> without base]
     expected: FAIL
 
-  [Parsing: <https://x/￿y> against <about:blank>]
+  [Parsing: <https://x/￿y> without base]
     expected: FAIL
 
-  [Parsing: <https://xn--/> against <about:blank>]
+  [Parsing: <https://xn--/> without base]
     expected: FAIL
 
   [Parsing: <i> against <sc:///pa/pa>]
@@ -1169,190 +1169,190 @@
   [Parsing: <i> against <sc://ho/pa>]
     expected: FAIL
 
-  [Parsing: <intent:///test> against <about:blank>]
+  [Parsing: <intent:///test> without base]
     expected: FAIL
 
-  [Parsing: <intent://:443> against <about:blank>]
+  [Parsing: <intent://:443> without base]
     expected: FAIL
 
-  [Parsing: <intent://[:1\]> against <about:blank>]
+  [Parsing: <intent://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <intent://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <intent://test/a/../b> against <about:blank>]
+  [Parsing: <intent://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <intent://test:test> against <about:blank>]
+  [Parsing: <intent://test:test> without base]
     expected: FAIL
 
-  [Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>]
+  [Parsing: <irc://myserver.com:6999/channel?passwd> without base]
     expected: FAIL
 
-  [Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>]
+  [Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/..//> against <about:blank>]
+  [Parsing: <non-spec:/..//> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/..//path> against <about:blank>]
+  [Parsing: <non-spec:/..//path> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/.//> against <about:blank>]
+  [Parsing: <non-spec:/.//> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/.//path> against <about:blank>]
+  [Parsing: <non-spec:/.//path> without base]
     expected: FAIL
 
-  [Parsing: <non-spec://example.org/test?a#b\x00c> against <about:blank>]
+  [Parsing: <non-spec://example.org/test?a#b\x00c> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/a/..//> against <about:blank>]
+  [Parsing: <non-spec:/a/..//> without base]
     expected: FAIL
 
-  [Parsing: <non-spec:/a/..//path> against <about:blank>]
+  [Parsing: <non-spec:/a/..//path> without base]
     expected: FAIL
 
-  [Parsing: <non-special://%E2%80%A0/> against <about:blank>]
+  [Parsing: <non-special://%E2%80%A0/> without base]
     expected: FAIL
 
-  [Parsing: <non-special://:@test/x> against <about:blank>]
+  [Parsing: <non-special://:@test/x> without base]
     expected: FAIL
 
-  [Parsing: <non-special://H%4fSt/path> against <about:blank>]
+  [Parsing: <non-special://H%4fSt/path> without base]
     expected: FAIL
 
-  [Parsing: <non-special://[1:2:0:0:0:0:0:3\]/> against <about:blank>]
+  [Parsing: <non-special://[1:2:0:0:0:0:0:3\]/> without base]
     expected: FAIL
 
-  [Parsing: <non-special://[1:2:0:0:5:0:0:0\]/> against <about:blank>]
+  [Parsing: <non-special://[1:2:0:0:5:0:0:0\]/> without base]
     expected: FAIL
 
-  [Parsing: <non-special://[1:2::3\]:80/> against <about:blank>]
+  [Parsing: <non-special://[1:2::3\]:80/> without base]
     expected: FAIL
 
-  [Parsing: <non-special://[:80/> against <about:blank>]
+  [Parsing: <non-special://[:80/> without base]
     expected: FAIL
 
   [Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar>]
     expected: FAIL
 
-  [Parsing: <non-special://test:@test/x> against <about:blank>]
+  [Parsing: <non-special://test:@test/x> without base]
     expected: FAIL
 
-  [Parsing: <non-special:x/?#￿y> against <about:blank>]
+  [Parsing: <non-special:x/?#￿y> without base]
     expected: FAIL
 
-  [Parsing: <non-special:x/?￿y> against <about:blank>]
+  [Parsing: <non-special:x/?￿y> without base]
     expected: FAIL
 
-  [Parsing: <non-special:x/￿y> against <about:blank>]
+  [Parsing: <non-special:x/￿y> without base]
     expected: FAIL
 
-  [Parsing: <non-special:￿y> against <about:blank>]
+  [Parsing: <non-special:￿y> without base]
     expected: FAIL
 
-  [Parsing: <notspecial://host/?'> against <about:blank>]
+  [Parsing: <notspecial://host/?'> without base]
     expected: FAIL
 
   [Parsing: <path> against <non-spec:/..//p>]
     expected: FAIL
 
-  [Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>]
+  [Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base]
     expected: FAIL
 
-  [Parsing: <rsync://foo@host:911/sup> against <about:blank>]
+  [Parsing: <rsync://foo@host:911/sup> without base]
     expected: FAIL
 
-  [Parsing: <sc://\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f!"$%&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Parsing: <sc://\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f!"$%&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
-  [Parsing: <sc://#> against <about:blank>]
+  [Parsing: <sc://#> without base]
     expected: FAIL
 
-  [Parsing: <sc://%/> against <about:blank>]
+  [Parsing: <sc://%/> without base]
     expected: FAIL
 
-  [Parsing: <sc://:/> against <about:blank>]
+  [Parsing: <sc://:/> without base]
     expected: FAIL
 
-  [Parsing: <sc://:12/> against <about:blank>]
+  [Parsing: <sc://:12/> without base]
     expected: FAIL
 
-  [Parsing: <sc://?> against <about:blank>]
+  [Parsing: <sc://?> without base]
     expected: FAIL
 
-  [Parsing: <sc://@/> against <about:blank>]
+  [Parsing: <sc://@/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a\x00b/> against <about:blank>]
+  [Parsing: <sc://a\x00b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a b/> against <about:blank>]
+  [Parsing: <sc://a b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a<b> against <about:blank>]
+  [Parsing: <sc://a<b> without base]
     expected: FAIL
 
-  [Parsing: <sc://a>b> against <about:blank>]
+  [Parsing: <sc://a>b> without base]
     expected: FAIL
 
-  [Parsing: <sc://a[b/> against <about:blank>]
+  [Parsing: <sc://a[b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a\\b/> against <about:blank>]
+  [Parsing: <sc://a\\b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a\]b/> against <about:blank>]
+  [Parsing: <sc://a\]b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://a^b> against <about:blank>]
+  [Parsing: <sc://a^b> without base]
     expected: FAIL
 
-  [Parsing: <sc://a|b/> against <about:blank>]
+  [Parsing: <sc://a|b/> without base]
     expected: FAIL
 
-  [Parsing: <sc://faß.ExAmPlE/> against <about:blank>]
+  [Parsing: <sc://faß.ExAmPlE/> without base]
     expected: FAIL
 
-  [Parsing: <sc://te@s:t@/> against <about:blank>]
+  [Parsing: <sc://te@s:t@/> without base]
     expected: FAIL
 
-  [Parsing: <sc://ñ#x> against <about:blank>]
+  [Parsing: <sc://ñ#x> without base]
     expected: FAIL
 
-  [Parsing: <sc://ñ.test/> against <about:blank>]
+  [Parsing: <sc://ñ.test/> without base]
     expected: FAIL
 
-  [Parsing: <sc://ñ> against <about:blank>]
+  [Parsing: <sc://ñ> without base]
     expected: FAIL
 
-  [Parsing: <sc://ñ?x> against <about:blank>]
+  [Parsing: <sc://ñ?x> without base]
     expected: FAIL
 
   [Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>]
     expected: FAIL
 
-  [Parsing: <stun:///test> against <about:blank>]
+  [Parsing: <stun:///test> without base]
     expected: FAIL
 
-  [Parsing: <stun://:443> against <about:blank>]
+  [Parsing: <stun://:443> without base]
     expected: FAIL
 
-  [Parsing: <stun://[:1\]> against <about:blank>]
+  [Parsing: <stun://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <stun://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <stun://test/a/../b> against <about:blank>]
+  [Parsing: <stun://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <stun://test:test> against <about:blank>]
+  [Parsing: <stun://test:test> without base]
     expected: FAIL
 
-  [Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>]
+  [Parsing: <telnet://user:pass@foobar.com:23/> without base]
     expected: FAIL
 
   [Parsing: <test-a-colon-b.html> against <a:b>]
@@ -1377,61 +1377,61 @@
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>]
+  [Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base]
     expected: FAIL
 
-  [Parsing: <turn:///test> against <about:blank>]
+  [Parsing: <turn:///test> without base]
     expected: FAIL
 
-  [Parsing: <turn://:443> against <about:blank>]
+  [Parsing: <turn://:443> without base]
     expected: FAIL
 
-  [Parsing: <turn://[:1\]> against <about:blank>]
+  [Parsing: <turn://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <turn://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <turn://test/a/../b> against <about:blank>]
+  [Parsing: <turn://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <turn://test:test> against <about:blank>]
+  [Parsing: <turn://test:test> without base]
     expected: FAIL
 
-  [Parsing: <urn:///test> against <about:blank>]
+  [Parsing: <urn:///test> without base]
     expected: FAIL
 
-  [Parsing: <urn://:443> against <about:blank>]
+  [Parsing: <urn://:443> without base]
     expected: FAIL
 
-  [Parsing: <urn://[:1\]> against <about:blank>]
+  [Parsing: <urn://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <urn://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <urn://test/a/../b> against <about:blank>]
+  [Parsing: <urn://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <urn://test:test> against <about:blank>]
+  [Parsing: <urn://test:test> without base]
     expected: FAIL
 
-  [Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>]
+  [Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base]
     expected: FAIL
 
-  [Parsing: <wow:￿> against <about:blank>]
+  [Parsing: <wow:￿> without base]
     expected: FAIL
 
-  [Parsing: <wss:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>]
+  [Parsing: <wss:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base]
     expected: FAIL
 
-  [Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
-  [Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\\\]^_`{|}~> against <about:blank>]
+  [Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\\\]^_`{|}~> without base]
     expected: FAIL
 
-  [Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>]
+  [Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base]
     expected: FAIL
 
   [Parsing: <x> against <sc://ñ>]
@@ -1537,7 +1537,7 @@
   [Parsing: <\\/localhost//pig> against <file://lion/>]
     expected: FAIL
 
-  [Parsing: <file:#frag> against <about:blank>]
+  [Parsing: <file:#frag> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
@@ -1549,42 +1549,42 @@
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:.//p> against <about:blank>]
+  [Parsing: <file:.//p> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:/.//p> against <about:blank>]
+  [Parsing: <file:/.//p> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file://%43%7C/> against <about:blank>]
+  [Parsing: <file://%43%7C/> without base]
     expected: FAIL
 
-  [Parsing: <file://%43%7C> against <about:blank>]
+  [Parsing: <file://%43%7C> without base]
     expected: FAIL
 
-  [Parsing: <file://%43|> against <about:blank>]
+  [Parsing: <file://%43|> without base]
     expected: FAIL
 
-  [Parsing: <file:///./y:> against <about:blank>]
+  [Parsing: <file:///./y:> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:////foo> against <about:blank>]
+  [Parsing: <file:////foo> without base]
     expected: FAIL
 
   [Parsing: <file:////one/two> against <file:///>]
     expected: FAIL
 
-  [Parsing: <file:///y:/> against <about:blank>]
+  [Parsing: <file:///y:/> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:///y:> against <about:blank>]
+  [Parsing: <file:///y:> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file://C%7C> against <about:blank>]
+  [Parsing: <file://C%7C> without base]
     expected: FAIL
 
   [Parsing: <file://C:/> against <file://host/>]
@@ -1592,24 +1592,24 @@
       if (product == "content_shell") and (os == "win"): PASS
       FAIL
 
-  [Parsing: <file://C|/> against <about:blank>]
+  [Parsing: <file://C|/> without base]
     expected:
       if (product == "content_shell") and (os == "win"): PASS
       FAIL
 
-  [Parsing: <file://\\/localhost//cat> against <about:blank>]
+  [Parsing: <file://\\/localhost//cat> without base]
     expected: FAIL
 
-  [Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank>]
+  [Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base]
     expected: FAIL
 
-  [Parsing: <file://localhost////foo> against <about:blank>]
+  [Parsing: <file://localhost////foo> without base]
     expected: FAIL
 
-  [Parsing: <file://localhost//a//../..//> against <about:blank>]
+  [Parsing: <file://localhost//a//../..//> without base]
     expected: FAIL
 
-  [Parsing: <file://localhost//a//../..//foo> against <about:blank>]
+  [Parsing: <file://localhost//a//../..//foo> without base]
     expected: FAIL
 
   [Parsing: <file://localhost/> against <file:///tmp/mock/path>]
@@ -1621,27 +1621,27 @@
   [Parsing: <file://localhost> against <file:///tmp/mock/path>]
     expected: FAIL
 
-  [Parsing: <file://xn--/p> against <about:blank>]
+  [Parsing: <file://xn--/p> without base]
     expected: FAIL
 
   [Parsing: <file:/C:/> against <file://host/>]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:/C|/> against <about:blank>]
+  [Parsing: <file:/C|/> without base]
     expected:
       if (product == "content_shell") and (os == "win"): PASS
       FAIL
 
-  [Parsing: <file:/example.com/> against <about:blank>]
-    expected:
-      if (product == "content_shell") and (os == "win"): FAIL
-
   [Parsing: <file:/example.com/> against <http://example.org/foo/bar>]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:?q=v> against <about:blank>]
+  [Parsing: <file:/example.com/> without base]
+    expected:
+      if (product == "content_shell") and (os == "win"): FAIL
+
+  [Parsing: <file:?q=v> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
@@ -1649,19 +1649,19 @@
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Parsing: <file:\\\\//> against <about:blank>]
+  [Parsing: <file:\\\\//> without base]
     expected: FAIL
 
-  [Parsing: <file:\\\\\\\\#guppy> against <about:blank>]
+  [Parsing: <file:\\\\\\\\#guppy> without base]
     expected: FAIL
 
-  [Parsing: <file:\\\\\\\\> against <about:blank>]
+  [Parsing: <file:\\\\\\\\> without base]
     expected: FAIL
 
-  [Parsing: <file:\\\\\\\\?fox> against <about:blank>]
+  [Parsing: <file:\\\\\\\\?fox> without base]
     expected: FAIL
 
-  [Parsing: <file:\\\\localhost//> against <about:blank>]
+  [Parsing: <file:\\\\localhost//> without base]
     expected: FAIL
 
   [Parsing: <file:\\c:\\foo\\bar> against <file:///c:/baz/qux>]
@@ -1677,46 +1677,46 @@
 
 
 [url-constructor.any.worker.html?include=javascript]
-  [Parsing: <javascript:/../> against <about:blank>]
+  [Parsing: <javascript:/../> without base]
     expected: FAIL
 
-  [Parsing: <javascript:///test> against <about:blank>]
+  [Parsing: <javascript:///test> without base]
     expected: FAIL
 
-  [Parsing: <javascript://:443> against <about:blank>]
+  [Parsing: <javascript://:443> without base]
     expected: FAIL
 
-  [Parsing: <javascript://[:1\]> against <about:blank>]
+  [Parsing: <javascript://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <javascript://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <javascript://test/a/../b> against <about:blank>]
+  [Parsing: <javascript://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <javascript://test:test> against <about:blank>]
+  [Parsing: <javascript://test:test> without base]
     expected: FAIL
 
 
 [url-constructor.any.worker.html?include=mailto]
-  [Parsing: <mailto:/../> against <about:blank>]
+  [Parsing: <mailto:/../> without base]
     expected: FAIL
 
-  [Parsing: <mailto:///test> against <about:blank>]
+  [Parsing: <mailto:///test> without base]
     expected: FAIL
 
-  [Parsing: <mailto://:443> against <about:blank>]
+  [Parsing: <mailto://:443> without base]
     expected: FAIL
 
-  [Parsing: <mailto://[:1\]> against <about:blank>]
+  [Parsing: <mailto://[:1\]> without base]
     expected: FAIL
 
-  [Parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>]
+  [Parsing: <mailto://example.com:8080/pathname?search#hash> without base]
     expected: FAIL
 
-  [Parsing: <mailto://test/a/../b> against <about:blank>]
+  [Parsing: <mailto://test/a/../b> without base]
     expected: FAIL
 
-  [Parsing: <mailto://test:test> against <about:blank>]
+  [Parsing: <mailto://test:test> without base]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt
index c84000a..f9c6986 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt
@@ -2,21 +2,21 @@
 PASS Loading data…
 PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <javascript:/example.com/> against <about:blank>
-PASS Parsing: <javascript:example.com/> against <about:blank>
-FAIL Parsing: <javascript:/../> against <about:blank> assert_equals: href expected "javascript:/" but got "javascript:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <javascript:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <javascript://test/a/../b> against <about:blank> assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
-FAIL Parsing: <javascript://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <javascript:/example.com/> without base
+PASS Parsing: <javascript:example.com/> without base
+FAIL Parsing: <javascript:/../> without base assert_equals: href expected "javascript:/" but got "javascript:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <javascript:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <javascript://test/a/../b> without base assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
+FAIL Parsing: <javascript://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt
index 76ca25f4..f33c013 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt
@@ -2,22 +2,22 @@
 PASS Loading data…
 PASS Parsing: <mailto:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <mailto:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <mailto:/example.com/> against <about:blank>
-PASS Parsing: <mailto:example.com/> against <about:blank>
+PASS Parsing: <mailto:/example.com/> without base
+PASS Parsing: <mailto:example.com/> without base
 PASS Parsing: <#x> against <mailto:x@x.com>
-FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: href expected "mailto:/" but got "mailto:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
-FAIL Parsing: <mailto:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <mailto://test/a/../b> against <about:blank> assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
-FAIL Parsing: <mailto://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto:/../> without base assert_equals: href expected "mailto:/" but got "mailto:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> without base assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
+FAIL Parsing: <mailto:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <mailto://test/a/../b> without base assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
+FAIL Parsing: <mailto://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/url/url-constructor.any_include=javascript-expected.txt b/third_party/blink/web_tests/external/wpt/url/url-constructor.any_include=javascript-expected.txt
index c84000a..f9c6986 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-constructor.any_include=javascript-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/url-constructor.any_include=javascript-expected.txt
@@ -2,21 +2,21 @@
 PASS Loading data…
 PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <javascript:/example.com/> against <about:blank>
-PASS Parsing: <javascript:example.com/> against <about:blank>
-FAIL Parsing: <javascript:/../> against <about:blank> assert_equals: href expected "javascript:/" but got "javascript:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <javascript:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <javascript://test/a/../b> against <about:blank> assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
-FAIL Parsing: <javascript://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <javascript:/example.com/> without base
+PASS Parsing: <javascript:example.com/> without base
+FAIL Parsing: <javascript:/../> without base assert_equals: href expected "javascript:/" but got "javascript:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <javascript:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <javascript://test/a/../b> without base assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
+FAIL Parsing: <javascript://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/url/url-constructor.any_include=mailto-expected.txt b/third_party/blink/web_tests/external/wpt/url/url-constructor.any_include=mailto-expected.txt
index 76ca25f4..f33c013 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-constructor.any_include=mailto-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/url-constructor.any_include=mailto-expected.txt
@@ -2,22 +2,22 @@
 PASS Loading data…
 PASS Parsing: <mailto:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <mailto:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <mailto:/example.com/> against <about:blank>
-PASS Parsing: <mailto:example.com/> against <about:blank>
+PASS Parsing: <mailto:/example.com/> without base
+PASS Parsing: <mailto:example.com/> without base
 PASS Parsing: <#x> against <mailto:x@x.com>
-FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: href expected "mailto:/" but got "mailto:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
-FAIL Parsing: <mailto:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <mailto://test/a/../b> against <about:blank> assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
-FAIL Parsing: <mailto://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto:/../> without base assert_equals: href expected "mailto:/" but got "mailto:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> without base assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
+FAIL Parsing: <mailto:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <mailto://test/a/../b> without base assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
+FAIL Parsing: <mailto://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/url/url-origin.any.js b/third_party/blink/web_tests/external/wpt/url/url-origin.any.js
index 9c1f97e..599984c6 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-origin.any.js
+++ b/third_party/blink/web_tests/external/wpt/url/url-origin.any.js
@@ -1,17 +1,16 @@
 promise_test(() => fetch("resources/urltestdata.json").then(res => res.json()).then(runURLTests), "Loading data…");
 
-function bURL(url, base) {
-  return base ? new URL(url, base) : new URL(url)
-}
+function runURLTests(urlTests) {
+  for (const expected of urlTests) {
+    // Skip comments and tests without "origin" expectation
+    if (typeof expected === "string" || !("origin" in expected))
+      continue;
 
-function runURLTests(urltests) {
-  for(var i = 0, l = urltests.length; i < l; i++) {
-    var expected = urltests[i]
-    if (typeof expected === "string" || !("origin" in expected)) continue
+    const base = expected.base !== null ? expected.base : undefined;
 
-    test(function() {
-      var url = bURL(expected.input, expected.base)
-      assert_equals(url.origin, expected.origin, "origin")
-    }, "Origin parsing: <" + expected.input + "> against <" + expected.base + ">")
+    test(() => {
+      const url = new URL(expected.input, base);
+      assert_equals(url.origin, expected.origin, "origin");
+    }, `Origin parsing: <${expected.input}> ${base ? "against <" + base + ">" : "without base"}`);
   }
 }
diff --git a/third_party/blink/web_tests/external/wpt/url/url-origin.any.js.ini b/third_party/blink/web_tests/external/wpt/url/url-origin.any.js.ini
index 83629f0d..837c7c2 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-origin.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/url/url-origin.any.js.ini
@@ -17,20 +17,20 @@
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Origin parsing: <h://.> against <about:blank>]
+  [Origin parsing: <h://.> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
-  [Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank>]
+  [Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base]
     expected: FAIL
 
-  [Origin parsing: <http://example.com/foo%00%51> against <about:blank>]
+  [Origin parsing: <http://example.com/foo%00%51> without base]
     expected: FAIL
 
-  [Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
   [Origin parsing: <x> against <sc://ñ>]
@@ -56,20 +56,20 @@
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Origin parsing: <h://.> against <about:blank>]
+  [Origin parsing: <h://.> without base]
     expected:
       if (product == "content_shell") and (os == "win"): FAIL
 
-  [Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
-  [Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank>]
+  [Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base]
     expected: FAIL
 
-  [Origin parsing: <http://example.com/foo%00%51> against <about:blank>]
+  [Origin parsing: <http://example.com/foo%00%51> without base]
     expected: FAIL
 
-  [Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank>]
+  [Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base]
     expected: FAIL
 
   [Origin parsing: <x> against <sc://ñ>]
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-worker.https.html b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-worker.https.html
index e022bff4..cb31057 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-worker.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-worker.https.html
@@ -117,6 +117,80 @@
   return onmessagePromise;
 }, 'RTCRtpSender readable stream transferred to a Worker and the Worker sends an RTCEncodedVideoFrame back');
 
+promise_test(async t => {
+  const caller = new RTCPeerConnection({encodedInsertableStreams:true});
+  t.add_cleanup(() => caller.close());
+  const callee = new RTCPeerConnection();
+  t.add_cleanup(() => callee.close());
+
+  const stream = await navigator.mediaDevices.getUserMedia({video:true});
+  const videoTrack = stream.getVideoTracks()[0];
+  t.add_cleanup(() => videoTrack.stop());
+
+  const videoSender = caller.addTrack(videoTrack)
+  const senderStreams = videoSender.createEncodedStreams();
+
+  const senderWorker = new Worker('RTCPeerConnection-worker-transform.js')
+  t.add_cleanup(() => senderWorker.terminate());
+  senderWorker.postMessage(
+    {
+      readableStream: senderStreams.readable,
+      writableStream: senderStreams.writable,
+      insertError: true
+    },
+    [senderStreams.readable, senderStreams.writable]);
+
+  const onmessagePromise = new Promise(resolve => {
+    senderWorker.onmessage = t.step_func(message => {
+      assert_false(message.data.success);
+      assert_true(message.data.error instanceof TypeError);
+      resolve();
+    });
+  });
+
+  exchangeIceCandidates(caller, callee);
+  await exchangeOfferAnswer(caller, callee);
+
+  return onmessagePromise;
+}, 'Video RTCRtpSender insertable streams transferred to a worker, which tries to write an invalid frame');
+
+promise_test(async t => {
+  const caller = new RTCPeerConnection({encodedInsertableStreams:true});
+  t.add_cleanup(() => caller.close());
+  const callee = new RTCPeerConnection();
+  t.add_cleanup(() => callee.close());
+
+  const stream = await navigator.mediaDevices.getUserMedia({audio:true});
+  const audioTrack = stream.getAudioTracks()[0];
+  t.add_cleanup(() => audioTrack.stop());
+
+  const audioSender = caller.addTrack(audioTrack)
+  const senderStreams = audioSender.createEncodedStreams();
+
+  const senderWorker = new Worker('RTCPeerConnection-worker-transform.js')
+  t.add_cleanup(() => senderWorker.terminate());
+  senderWorker.postMessage(
+    {
+      readableStream: senderStreams.readable,
+      writableStream: senderStreams.writable,
+      insertError: true
+    },
+    [senderStreams.readable, senderStreams.writable]);
+
+  const onmessagePromise = new Promise(resolve => {
+    senderWorker.onmessage = t.step_func(message => {
+      assert_false(message.data.success);
+      assert_true(message.data.error instanceof TypeError);
+      resolve();
+    });
+  });
+
+  exchangeIceCandidates(caller, callee);
+  await exchangeOfferAnswer(caller, callee);
+
+  return onmessagePromise;
+}, 'Audio RTCRtpSender insertable streams transferred to a worker, which tries to write an invalid frame');
+
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/RTCPeerConnection-worker-transform.js b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/RTCPeerConnection-worker-transform.js
new file mode 100644
index 0000000..36e3949e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/RTCPeerConnection-worker-transform.js
@@ -0,0 +1,22 @@
+onmessage = async (event) => {
+  const readableStream = event.data.readableStream;
+  const writableStream = event.data.writableStream;
+  const insertError = event.data.insertError;
+
+  try {
+    await readableStream.pipeThrough(new TransformStream({
+      transform: (chunk, controller) => {
+        if (insertError) {
+          controller.enqueue("This is not a valid frame");
+        } else {
+          controller.enqueue(chunk);
+        }
+      }
+    })).pipeTo(writableStream);
+
+    postMessage({success:true});
+  } catch(e) {
+    postMessage({success:false, error: e});
+  }
+
+}
diff --git a/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/constructor.any.js.ini b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/constructor.any.js.ini
index 149394c..06db16b 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/constructor.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/constructor.any.js.ini
@@ -8,3 +8,7 @@
 [constructor.any.sharedworker.html?wpt_flags=h2]
   expected:
     if (product == "content_shell") and (os == "mac"): [TIMEOUT, OK]
+
+[constructor.any.worker.html?wpt_flags=h2]
+  expected:
+    if (product == "content_shell") and (os == "mac"): [TIMEOUT, OK]
diff --git a/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/external/wpt/dom/events/Event-dispatch-on-disabled-elements-expected.txt b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/external/wpt/dom/events/Event-dispatch-on-disabled-elements-expected.txt
new file mode 100644
index 0000000..c0287e59
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/external/wpt/dom/events/Event-dispatch-on-disabled-elements-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+PASS Can dispatch untrusted 'click' Events at disabled HTML elements.
+PASS Can dispatch untrusted Events at disabled HTML elements.
+PASS Can dispatch CustomEvents at disabled HTML elements.
+PASS Calling click() on disabled elements must not dispatch events.
+PASS CSS Transitions transitionrun, transitionstart, transitionend events fire on disabled form elements
+PASS CSS Transitions transitioncancel event fires on disabled form elements
+PASS CSS Animation animationstart, animationiteration, animationend fire on disabled form elements
+PASS CSS Animation's animationcancel event fires on disabled form elements
+FAIL Real clicks on disabled elements must not dispatch events. assert_true: HTMLSelectElement is enabled, so onclick must fire. expected true got false
+Harness: the test ran to completion.
+
diff --git "a/third_party/blink/web_tests/flag-specific/highdpi/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/flag-specific/highdpi/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index 79cf282..8cbb574 100644
--- "a/third_party/blink/web_tests/flag-specific/highdpi/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/flag-specific/highdpi/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 347 PASS, 313 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 347 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
index 79cf282..8cbb574 100644
--- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 347 PASS, 313 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 347 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index 79cf282..8cbb574 100644
--- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 347 PASS, 313 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 347 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/failure-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/failure-expected.txt
index b2c687c..e53a616 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/failure-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/failure-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1205 tests; 882 PASS, 323 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1205 tests; 886 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS URL's constructor's base argument: file://example:1/ should throw
 PASS URL's href: file://example:1/ should throw
@@ -893,6 +893,10 @@
 PASS sendBeacon(): file://xn--/p should throw
 FAIL Location's href: file://xn--/p should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
 FAIL window.open(): file://xn--/p should throw assert_throws_dom: function "() => self.open(test.input).close()" threw object "TypeError: Cannot read properties of null (reading 'close')" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12
+PASS URL's constructor's base argument: # should throw
+PASS URL's href: # should throw
+PASS URL's constructor's base argument: ? should throw
+PASS URL's href: ? should throw
 PASS URL's constructor's base argument: http://0..0x300/ should throw
 PASS URL's href: http://0..0x300/ should throw
 PASS XHR: http://0..0x300/ should throw
@@ -1057,10 +1061,6 @@
 PASS window.open(): https://￿y should throw
 PASS URL's constructor's base argument:  should throw
 PASS URL's href:  should throw
-FAIL XHR:  should throw assert_throws_dom: function "() => client.open("GET", test.input)" did not throw
-FAIL sendBeacon():  should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw
-FAIL Location's href:  should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
-FAIL window.open():  should throw assert_throws_dom: function "() => self.open(test.input).close()" did not throw
 PASS URL's constructor's base argument: https://­/ should throw
 PASS URL's href: https://­/ should throw
 PASS XHR: https://­/ should throw
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index 4eda65ae2..23ffa0d 100644
--- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 PASS Parsing: <a:	 foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -78,7 +78,7 @@
 PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar>
 FAIL Parsing: <http://[::127.0.0.1.]> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>
@@ -108,116 +108,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -232,54 +232,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-PASS Parsing: <https://faß.ExAmPlE/> against <about:blank>
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+PASS Parsing: <https://faß.ExAmPlE/> without base
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -288,34 +288,34 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: host expected "." but got ""
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: host expected "." but got ""
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1.2]> against <http://other.com/>
 FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -325,8 +325,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -355,196 +355,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -562,60 +562,60 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-PASS Parsing: <\\\.\Y:> against <about:blank>
-PASS Parsing: <\\\.\y:> against <about:blank>
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+PASS Parsing: <\\\.\Y:> without base
+PASS Parsing: <\\\.\y:> without base
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -623,179 +623,179 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 PASS Parsing: <test-a-colon.html> against <a:>
 PASS Parsing: <test-a-colon-b.html> against <a:b>
 PASS Parsing: <test-a-colon-slash.html> against <a:/>
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> Failed to construct 'URL': Invalid URL
 PASS Parsing: <test-a-colon-slash-b.html> against <a:/b>
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_include=file-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
index 5b6c4784..bf0df7e 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 78 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html"
 FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar"
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-PASS Parsing: <file:/example.com/> against <about:blank>
+PASS Parsing: <file:/example.com/> without base
 PASS Parsing: <file:...> against <http://www.example.com/test>
 PASS Parsing: <file:..> against <http://www.example.com/test>
 PASS Parsing: <file:a> against <http://www.example.com/test>
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///"
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox"
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base assert_equals: href expected "file:////?fox" but got "file:///?fox"
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar"
 PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux>
 PASS Parsing: </c:/foo/bar> against <file://host/path>
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/"
 PASS Parsing: </C:/> against <file://host/>
 PASS Parsing: <file:C:/> against <file://host/>
@@ -102,40 +102,40 @@
 FAIL Parsing: <file://C:/> against <file://host/> Failed to construct 'URL': Invalid URL
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
-FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/"
-PASS Parsing: <file:> against <about:blank>
-PASS Parsing: <file:?q=v> against <about:blank>
-PASS Parsing: <file:#frag> against <about:blank>
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-PASS Parsing: <file:///y:> against <about:blank>
-PASS Parsing: <file:///y:/> against <about:blank>
-PASS Parsing: <file:///./y> against <about:blank>
-PASS Parsing: <file:///./y:> against <about:blank>
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo"
+FAIL Parsing: <file:/C|/> without base assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
+FAIL Parsing: <file://C|/> without base assert_equals: href expected "file:///C:/" but got "file://c%7C/"
+PASS Parsing: <file:> without base
+PASS Parsing: <file:?q=v> without base
+PASS Parsing: <file:#frag> without base
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+PASS Parsing: <file:///y:> without base
+PASS Parsing: <file:///y:/> without base
+PASS Parsing: <file:///./y> without base
+PASS Parsing: <file:///./y:> without base
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file:///foo"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <file:///.//> against <file:////>
-PASS Parsing: <file:.//p> against <about:blank>
-PASS Parsing: <file:/.//p> against <about:blank>
+PASS Parsing: <file:.//p> without base
+PASS Parsing: <file:/.//p> without base
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index 4eda65ae2..23ffa0d 100644
--- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 PASS Parsing: <a:	 foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -78,7 +78,7 @@
 PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar>
 FAIL Parsing: <http://[::127.0.0.1.]> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>
@@ -108,116 +108,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -232,54 +232,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-PASS Parsing: <https://faß.ExAmPlE/> against <about:blank>
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+PASS Parsing: <https://faß.ExAmPlE/> without base
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -288,34 +288,34 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: host expected "." but got ""
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: host expected "." but got ""
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1.2]> against <http://other.com/>
 FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -325,8 +325,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -355,196 +355,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -562,60 +562,60 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-PASS Parsing: <\\\.\Y:> against <about:blank>
-PASS Parsing: <\\\.\y:> against <about:blank>
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+PASS Parsing: <\\\.\Y:> without base
+PASS Parsing: <\\\.\y:> without base
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -623,179 +623,179 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 PASS Parsing: <test-a-colon.html> against <a:>
 PASS Parsing: <test-a-colon-b.html> against <a:b>
 PASS Parsing: <test-a-colon-slash.html> against <a:/>
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> Failed to construct 'URL': Invalid URL
 PASS Parsing: <test-a-colon-slash-b.html> against <a:/b>
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_include=file-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_include=file-expected.txt
index 5b6c4784..bf0df7e 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 78 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html"
 FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar"
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-PASS Parsing: <file:/example.com/> against <about:blank>
+PASS Parsing: <file:/example.com/> without base
 PASS Parsing: <file:...> against <http://www.example.com/test>
 PASS Parsing: <file:..> against <http://www.example.com/test>
 PASS Parsing: <file:a> against <http://www.example.com/test>
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///"
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox"
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base assert_equals: href expected "file:////?fox" but got "file:///?fox"
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar"
 PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux>
 PASS Parsing: </c:/foo/bar> against <file://host/path>
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/"
 PASS Parsing: </C:/> against <file://host/>
 PASS Parsing: <file:C:/> against <file://host/>
@@ -102,40 +102,40 @@
 FAIL Parsing: <file://C:/> against <file://host/> Failed to construct 'URL': Invalid URL
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
-FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/"
-PASS Parsing: <file:> against <about:blank>
-PASS Parsing: <file:?q=v> against <about:blank>
-PASS Parsing: <file:#frag> against <about:blank>
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-PASS Parsing: <file:///y:> against <about:blank>
-PASS Parsing: <file:///y:/> against <about:blank>
-PASS Parsing: <file:///./y> against <about:blank>
-PASS Parsing: <file:///./y:> against <about:blank>
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo"
+FAIL Parsing: <file:/C|/> without base assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
+FAIL Parsing: <file://C|/> without base assert_equals: href expected "file:///C:/" but got "file://c%7C/"
+PASS Parsing: <file:> without base
+PASS Parsing: <file:?q=v> without base
+PASS Parsing: <file:#frag> without base
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+PASS Parsing: <file:///y:> without base
+PASS Parsing: <file:///y:/> without base
+PASS Parsing: <file:///./y> without base
+PASS Parsing: <file:///./y:> without base
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file:///foo"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <file:///.//> against <file:////>
-PASS Parsing: <file:.//p> against <about:blank>
-PASS Parsing: <file:/.//p> against <about:blank>
+PASS Parsing: <file:.//p> without base
+PASS Parsing: <file:/.//p> without base
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any-expected.txt
index b882097..eff480d 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-PASS Origin parsing: <https://faß.ExAmPlE/> against <about:blank>
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+PASS Origin parsing: <https://faß.ExAmPlE/> without base
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-PASS Origin parsing: <h://.> against <about:blank>
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+PASS Origin parsing: <h://.> without base
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any.worker-expected.txt
index b882097..eff480d 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any.worker-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-PASS Origin parsing: <https://faß.ExAmPlE/> against <about:blank>
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+PASS Origin parsing: <https://faß.ExAmPlE/> without base
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-PASS Origin parsing: <h://.> against <about:blank>
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+PASS Origin parsing: <h://.> without base
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
index 4ac3e49..fb19aff 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 346 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 346 PASS, 315 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index 4ac3e49..fb19aff 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 346 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 346 PASS, 315 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/failure-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/failure-expected.txt
index b2c687c..e53a616 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/failure-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/failure-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1205 tests; 882 PASS, 323 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1205 tests; 886 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS URL's constructor's base argument: file://example:1/ should throw
 PASS URL's href: file://example:1/ should throw
@@ -893,6 +893,10 @@
 PASS sendBeacon(): file://xn--/p should throw
 FAIL Location's href: file://xn--/p should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
 FAIL window.open(): file://xn--/p should throw assert_throws_dom: function "() => self.open(test.input).close()" threw object "TypeError: Cannot read properties of null (reading 'close')" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12
+PASS URL's constructor's base argument: # should throw
+PASS URL's href: # should throw
+PASS URL's constructor's base argument: ? should throw
+PASS URL's href: ? should throw
 PASS URL's constructor's base argument: http://0..0x300/ should throw
 PASS URL's href: http://0..0x300/ should throw
 PASS XHR: http://0..0x300/ should throw
@@ -1057,10 +1061,6 @@
 PASS window.open(): https://￿y should throw
 PASS URL's constructor's base argument:  should throw
 PASS URL's href:  should throw
-FAIL XHR:  should throw assert_throws_dom: function "() => client.open("GET", test.input)" did not throw
-FAIL sendBeacon():  should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw
-FAIL Location's href:  should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
-FAIL window.open():  should throw assert_throws_dom: function "() => self.open(test.input).close()" did not throw
 PASS URL's constructor's base argument: https://­/ should throw
 PASS URL's href: https://­/ should throw
 PASS XHR: https://­/ should throw
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index 09351a8f..bd3f061 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 PASS Parsing: <a:	 foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -78,7 +78,7 @@
 PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar>
 FAIL Parsing: <http://[::127.0.0.1.]> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>
@@ -108,116 +108,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -232,54 +232,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-FAIL Parsing: <https://faß.ExAmPlE/> against <about:blank> assert_equals: href expected "https://xn--fa-hia.example/" but got "https://fass.example/"
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+FAIL Parsing: <https://faß.ExAmPlE/> without base assert_equals: href expected "https://xn--fa-hia.example/" but got "https://fass.example/"
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -288,34 +288,34 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: host expected "." but got ""
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: host expected "." but got ""
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1.2]> against <http://other.com/>
 FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -325,8 +325,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -355,196 +355,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -562,60 +562,60 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-PASS Parsing: <\\\.\Y:> against <about:blank>
-PASS Parsing: <\\\.\y:> against <about:blank>
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+PASS Parsing: <\\\.\Y:> without base
+PASS Parsing: <\\\.\y:> without base
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -623,179 +623,179 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 PASS Parsing: <test-a-colon.html> against <a:>
 PASS Parsing: <test-a-colon-b.html> against <a:b>
 PASS Parsing: <test-a-colon-slash.html> against <a:/>
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> Failed to construct 'URL': Invalid URL
 PASS Parsing: <test-a-colon-slash-b.html> against <a:/b>
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=file-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
index 5b6c4784..bf0df7e 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 78 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html"
 FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar"
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-PASS Parsing: <file:/example.com/> against <about:blank>
+PASS Parsing: <file:/example.com/> without base
 PASS Parsing: <file:...> against <http://www.example.com/test>
 PASS Parsing: <file:..> against <http://www.example.com/test>
 PASS Parsing: <file:a> against <http://www.example.com/test>
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///"
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox"
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base assert_equals: href expected "file:////?fox" but got "file:///?fox"
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar"
 PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux>
 PASS Parsing: </c:/foo/bar> against <file://host/path>
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/"
 PASS Parsing: </C:/> against <file://host/>
 PASS Parsing: <file:C:/> against <file://host/>
@@ -102,40 +102,40 @@
 FAIL Parsing: <file://C:/> against <file://host/> Failed to construct 'URL': Invalid URL
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
-FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/"
-PASS Parsing: <file:> against <about:blank>
-PASS Parsing: <file:?q=v> against <about:blank>
-PASS Parsing: <file:#frag> against <about:blank>
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-PASS Parsing: <file:///y:> against <about:blank>
-PASS Parsing: <file:///y:/> against <about:blank>
-PASS Parsing: <file:///./y> against <about:blank>
-PASS Parsing: <file:///./y:> against <about:blank>
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo"
+FAIL Parsing: <file:/C|/> without base assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
+FAIL Parsing: <file://C|/> without base assert_equals: href expected "file:///C:/" but got "file://c%7C/"
+PASS Parsing: <file:> without base
+PASS Parsing: <file:?q=v> without base
+PASS Parsing: <file:#frag> without base
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+PASS Parsing: <file:///y:> without base
+PASS Parsing: <file:///y:/> without base
+PASS Parsing: <file:///./y> without base
+PASS Parsing: <file:///./y:> without base
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file:///foo"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <file:///.//> against <file:////>
-PASS Parsing: <file:.//p> against <about:blank>
-PASS Parsing: <file:/.//p> against <about:blank>
+PASS Parsing: <file:.//p> without base
+PASS Parsing: <file:/.//p> without base
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt
index c84000a..f9c6986 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt
@@ -2,21 +2,21 @@
 PASS Loading data…
 PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <javascript:/example.com/> against <about:blank>
-PASS Parsing: <javascript:example.com/> against <about:blank>
-FAIL Parsing: <javascript:/../> against <about:blank> assert_equals: href expected "javascript:/" but got "javascript:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <javascript:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <javascript://test/a/../b> against <about:blank> assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
-FAIL Parsing: <javascript://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <javascript:/example.com/> without base
+PASS Parsing: <javascript:example.com/> without base
+FAIL Parsing: <javascript:/../> without base assert_equals: href expected "javascript:/" but got "javascript:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <javascript:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <javascript://test/a/../b> without base assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
+FAIL Parsing: <javascript://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt
index 76ca25f4..f33c013 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt
@@ -2,22 +2,22 @@
 PASS Loading data…
 PASS Parsing: <mailto:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <mailto:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <mailto:/example.com/> against <about:blank>
-PASS Parsing: <mailto:example.com/> against <about:blank>
+PASS Parsing: <mailto:/example.com/> without base
+PASS Parsing: <mailto:example.com/> without base
 PASS Parsing: <#x> against <mailto:x@x.com>
-FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: href expected "mailto:/" but got "mailto:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
-FAIL Parsing: <mailto:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <mailto://test/a/../b> against <about:blank> assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
-FAIL Parsing: <mailto://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto:/../> without base assert_equals: href expected "mailto:/" but got "mailto:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> without base assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
+FAIL Parsing: <mailto:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <mailto://test/a/../b> without base assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
+FAIL Parsing: <mailto://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index 09351a8f..bd3f061 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 PASS Parsing: <a:	 foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -78,7 +78,7 @@
 PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar>
 FAIL Parsing: <http://[::127.0.0.1.]> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>
@@ -108,116 +108,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -232,54 +232,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-FAIL Parsing: <https://faß.ExAmPlE/> against <about:blank> assert_equals: href expected "https://xn--fa-hia.example/" but got "https://fass.example/"
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+FAIL Parsing: <https://faß.ExAmPlE/> without base assert_equals: href expected "https://xn--fa-hia.example/" but got "https://fass.example/"
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -288,34 +288,34 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: host expected "." but got ""
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: host expected "." but got ""
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1.2]> against <http://other.com/>
 FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -325,8 +325,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -355,196 +355,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -562,60 +562,60 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-PASS Parsing: <\\\.\Y:> against <about:blank>
-PASS Parsing: <\\\.\y:> against <about:blank>
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+PASS Parsing: <\\\.\Y:> without base
+PASS Parsing: <\\\.\y:> without base
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -623,179 +623,179 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 PASS Parsing: <test-a-colon.html> against <a:>
 PASS Parsing: <test-a-colon-b.html> against <a:b>
 PASS Parsing: <test-a-colon-slash.html> against <a:/>
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> Failed to construct 'URL': Invalid URL
 PASS Parsing: <test-a-colon-slash-b.html> against <a:/b>
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=file-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=file-expected.txt
index 5b6c4784..bf0df7e 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 78 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html"
 FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar"
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-PASS Parsing: <file:/example.com/> against <about:blank>
+PASS Parsing: <file:/example.com/> without base
 PASS Parsing: <file:...> against <http://www.example.com/test>
 PASS Parsing: <file:..> against <http://www.example.com/test>
 PASS Parsing: <file:a> against <http://www.example.com/test>
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///"
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox"
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base assert_equals: href expected "file:////?fox" but got "file:///?fox"
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar"
 PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux>
 PASS Parsing: </c:/foo/bar> against <file://host/path>
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/"
 PASS Parsing: </C:/> against <file://host/>
 PASS Parsing: <file:C:/> against <file://host/>
@@ -102,40 +102,40 @@
 FAIL Parsing: <file://C:/> against <file://host/> Failed to construct 'URL': Invalid URL
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
-FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/"
-PASS Parsing: <file:> against <about:blank>
-PASS Parsing: <file:?q=v> against <about:blank>
-PASS Parsing: <file:#frag> against <about:blank>
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-PASS Parsing: <file:///y:> against <about:blank>
-PASS Parsing: <file:///y:/> against <about:blank>
-PASS Parsing: <file:///./y> against <about:blank>
-PASS Parsing: <file:///./y:> against <about:blank>
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo"
+FAIL Parsing: <file:/C|/> without base assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
+FAIL Parsing: <file://C|/> without base assert_equals: href expected "file:///C:/" but got "file://c%7C/"
+PASS Parsing: <file:> without base
+PASS Parsing: <file:?q=v> without base
+PASS Parsing: <file:#frag> without base
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+PASS Parsing: <file:///y:> without base
+PASS Parsing: <file:///y:/> without base
+PASS Parsing: <file:///./y> without base
+PASS Parsing: <file:///./y:> without base
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file:///foo"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <file:///.//> against <file:////>
-PASS Parsing: <file:.//p> against <about:blank>
-PASS Parsing: <file:/.//p> against <about:blank>
+PASS Parsing: <file:.//p> without base
+PASS Parsing: <file:/.//p> without base
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=javascript-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=javascript-expected.txt
index c84000a..f9c6986 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=javascript-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=javascript-expected.txt
@@ -2,21 +2,21 @@
 PASS Loading data…
 PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <javascript:/example.com/> against <about:blank>
-PASS Parsing: <javascript:example.com/> against <about:blank>
-FAIL Parsing: <javascript:/../> against <about:blank> assert_equals: href expected "javascript:/" but got "javascript:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <javascript:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <javascript://test/a/../b> against <about:blank> assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
-FAIL Parsing: <javascript://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <javascript:/example.com/> without base
+PASS Parsing: <javascript:example.com/> without base
+FAIL Parsing: <javascript:/../> without base assert_equals: href expected "javascript:/" but got "javascript:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <javascript:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <javascript://test/a/../b> without base assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
+FAIL Parsing: <javascript://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=mailto-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=mailto-expected.txt
index 76ca25f4..f33c013 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=mailto-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_include=mailto-expected.txt
@@ -2,22 +2,22 @@
 PASS Loading data…
 PASS Parsing: <mailto:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <mailto:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <mailto:/example.com/> against <about:blank>
-PASS Parsing: <mailto:example.com/> against <about:blank>
+PASS Parsing: <mailto:/example.com/> without base
+PASS Parsing: <mailto:example.com/> without base
 PASS Parsing: <#x> against <mailto:x@x.com>
-FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: href expected "mailto:/" but got "mailto:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
-FAIL Parsing: <mailto:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <mailto://test/a/../b> against <about:blank> assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
-FAIL Parsing: <mailto://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto:/../> without base assert_equals: href expected "mailto:/" but got "mailto:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> without base assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
+FAIL Parsing: <mailto:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <mailto://test/a/../b> without base assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
+FAIL Parsing: <mailto://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any-expected.txt
index 01c499f4..0707cc8 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-FAIL Origin parsing: <https://faß.ExAmPlE/> against <about:blank> assert_equals: origin expected "https://xn--fa-hia.example" but got "https://fass.example"
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+FAIL Origin parsing: <https://faß.ExAmPlE/> without base assert_equals: origin expected "https://xn--fa-hia.example" but got "https://fass.example"
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-PASS Origin parsing: <h://.> against <about:blank>
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+PASS Origin parsing: <h://.> without base
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any.worker-expected.txt
index 01c499f4..0707cc8 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any.worker-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-FAIL Origin parsing: <https://faß.ExAmPlE/> against <about:blank> assert_equals: origin expected "https://xn--fa-hia.example" but got "https://fass.example"
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+FAIL Origin parsing: <https://faß.ExAmPlE/> without base assert_equals: origin expected "https://xn--fa-hia.example" but got "https://fass.example"
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-PASS Origin parsing: <h://.> against <about:blank>
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+PASS Origin parsing: <h://.> without base
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
index 8654cb5..68ea9c1 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 347 PASS, 313 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 347 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index 8654cb5..68ea9c1 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 347 PASS, 313 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 347 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/failure-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/failure-expected.txt
index b2c687c..e53a616 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/failure-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/failure-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1205 tests; 882 PASS, 323 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1205 tests; 886 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS URL's constructor's base argument: file://example:1/ should throw
 PASS URL's href: file://example:1/ should throw
@@ -893,6 +893,10 @@
 PASS sendBeacon(): file://xn--/p should throw
 FAIL Location's href: file://xn--/p should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
 FAIL window.open(): file://xn--/p should throw assert_throws_dom: function "() => self.open(test.input).close()" threw object "TypeError: Cannot read properties of null (reading 'close')" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12
+PASS URL's constructor's base argument: # should throw
+PASS URL's href: # should throw
+PASS URL's constructor's base argument: ? should throw
+PASS URL's href: ? should throw
 PASS URL's constructor's base argument: http://0..0x300/ should throw
 PASS URL's href: http://0..0x300/ should throw
 PASS XHR: http://0..0x300/ should throw
@@ -1057,10 +1061,6 @@
 PASS window.open(): https://￿y should throw
 PASS URL's constructor's base argument:  should throw
 PASS URL's href:  should throw
-FAIL XHR:  should throw assert_throws_dom: function "() => client.open("GET", test.input)" did not throw
-FAIL sendBeacon():  should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw
-FAIL Location's href:  should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
-FAIL window.open():  should throw assert_throws_dom: function "() => self.open(test.input).close()" did not throw
 PASS URL's constructor's base argument: https://­/ should throw
 PASS URL's href: https://­/ should throw
 PASS XHR: https://­/ should throw
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index 96427b1..4dc34a6 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 PASS Parsing: <a:	 foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -106,116 +106,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -230,54 +230,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-PASS Parsing: <https://faß.ExAmPlE/> against <about:blank>
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+PASS Parsing: <https://faß.ExAmPlE/> without base
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -286,16 +286,16 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: host expected "." but got ""
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: host expected "." but got ""
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.]> against <http://other.com/>
@@ -304,10 +304,10 @@
 PASS Parsing: <http://[::1.]> against <http://other.com/>
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -317,8 +317,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -347,196 +347,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -554,60 +554,60 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-PASS Parsing: <\\\.\Y:> against <about:blank>
-PASS Parsing: <\\\.\y:> against <about:blank>
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+PASS Parsing: <\\\.\Y:> without base
+PASS Parsing: <\\\.\y:> without base
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -615,179 +615,179 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 PASS Parsing: <test-a-colon.html> against <a:>
 PASS Parsing: <test-a-colon-b.html> against <a:b>
 PASS Parsing: <test-a-colon-slash.html> against <a:/>
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> Failed to construct 'URL': Invalid URL
 PASS Parsing: <test-a-colon-slash-b.html> against <a:/b>
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=file-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
index 5b6c4784..bf0df7e 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 78 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html"
 FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar"
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-PASS Parsing: <file:/example.com/> against <about:blank>
+PASS Parsing: <file:/example.com/> without base
 PASS Parsing: <file:...> against <http://www.example.com/test>
 PASS Parsing: <file:..> against <http://www.example.com/test>
 PASS Parsing: <file:a> against <http://www.example.com/test>
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///"
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox"
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base assert_equals: href expected "file:////?fox" but got "file:///?fox"
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar"
 PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux>
 PASS Parsing: </c:/foo/bar> against <file://host/path>
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/"
 PASS Parsing: </C:/> against <file://host/>
 PASS Parsing: <file:C:/> against <file://host/>
@@ -102,40 +102,40 @@
 FAIL Parsing: <file://C:/> against <file://host/> Failed to construct 'URL': Invalid URL
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
-FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/"
-PASS Parsing: <file:> against <about:blank>
-PASS Parsing: <file:?q=v> against <about:blank>
-PASS Parsing: <file:#frag> against <about:blank>
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-PASS Parsing: <file:///y:> against <about:blank>
-PASS Parsing: <file:///y:/> against <about:blank>
-PASS Parsing: <file:///./y> against <about:blank>
-PASS Parsing: <file:///./y:> against <about:blank>
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo"
+FAIL Parsing: <file:/C|/> without base assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
+FAIL Parsing: <file://C|/> without base assert_equals: href expected "file:///C:/" but got "file://c%7C/"
+PASS Parsing: <file:> without base
+PASS Parsing: <file:?q=v> without base
+PASS Parsing: <file:#frag> without base
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+PASS Parsing: <file:///y:> without base
+PASS Parsing: <file:///y:/> without base
+PASS Parsing: <file:///./y> without base
+PASS Parsing: <file:///./y:> without base
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file:///foo"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <file:///.//> against <file:////>
-PASS Parsing: <file:.//p> against <about:blank>
-PASS Parsing: <file:/.//p> against <about:blank>
+PASS Parsing: <file:.//p> without base
+PASS Parsing: <file:/.//p> without base
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt
index c84000a..f9c6986 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=javascript-expected.txt
@@ -2,21 +2,21 @@
 PASS Loading data…
 PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <javascript:/example.com/> against <about:blank>
-PASS Parsing: <javascript:example.com/> against <about:blank>
-FAIL Parsing: <javascript:/../> against <about:blank> assert_equals: href expected "javascript:/" but got "javascript:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <javascript:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <javascript://test/a/../b> against <about:blank> assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
-FAIL Parsing: <javascript://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <javascript:/example.com/> without base
+PASS Parsing: <javascript:example.com/> without base
+FAIL Parsing: <javascript:/../> without base assert_equals: href expected "javascript:/" but got "javascript:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <javascript:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <javascript://test/a/../b> without base assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
+FAIL Parsing: <javascript://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt
index 76ca25f4..f33c013 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_include=mailto-expected.txt
@@ -2,22 +2,22 @@
 PASS Loading data…
 PASS Parsing: <mailto:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <mailto:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <mailto:/example.com/> against <about:blank>
-PASS Parsing: <mailto:example.com/> against <about:blank>
+PASS Parsing: <mailto:/example.com/> without base
+PASS Parsing: <mailto:example.com/> without base
 PASS Parsing: <#x> against <mailto:x@x.com>
-FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: href expected "mailto:/" but got "mailto:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
-FAIL Parsing: <mailto:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <mailto://test/a/../b> against <about:blank> assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
-FAIL Parsing: <mailto://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto:/../> without base assert_equals: href expected "mailto:/" but got "mailto:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> without base assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
+FAIL Parsing: <mailto:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <mailto://test/a/../b> without base assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
+FAIL Parsing: <mailto://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index 96427b1..4dc34a6 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 PASS Parsing: <a:	 foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -106,116 +106,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -230,54 +230,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-PASS Parsing: <https://faß.ExAmPlE/> against <about:blank>
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+PASS Parsing: <https://faß.ExAmPlE/> without base
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -286,16 +286,16 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: host expected "." but got ""
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: host expected "." but got ""
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.]> against <http://other.com/>
@@ -304,10 +304,10 @@
 PASS Parsing: <http://[::1.]> against <http://other.com/>
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -317,8 +317,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -347,196 +347,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -554,60 +554,60 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-PASS Parsing: <\\\.\Y:> against <about:blank>
-PASS Parsing: <\\\.\y:> against <about:blank>
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+PASS Parsing: <\\\.\Y:> without base
+PASS Parsing: <\\\.\y:> without base
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -615,179 +615,179 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 PASS Parsing: <test-a-colon.html> against <a:>
 PASS Parsing: <test-a-colon-b.html> against <a:b>
 PASS Parsing: <test-a-colon-slash.html> against <a:/>
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> Failed to construct 'URL': Invalid URL
 PASS Parsing: <test-a-colon-slash-b.html> against <a:/b>
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=file-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=file-expected.txt
index 5b6c4784..bf0df7e 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 78 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html"
 FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar"
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-PASS Parsing: <file:/example.com/> against <about:blank>
+PASS Parsing: <file:/example.com/> without base
 PASS Parsing: <file:...> against <http://www.example.com/test>
 PASS Parsing: <file:..> against <http://www.example.com/test>
 PASS Parsing: <file:a> against <http://www.example.com/test>
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///"
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox"
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base assert_equals: href expected "file:////?fox" but got "file:///?fox"
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar"
 PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux>
 PASS Parsing: </c:/foo/bar> against <file://host/path>
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/"
 PASS Parsing: </C:/> against <file://host/>
 PASS Parsing: <file:C:/> against <file://host/>
@@ -102,40 +102,40 @@
 FAIL Parsing: <file://C:/> against <file://host/> Failed to construct 'URL': Invalid URL
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
-FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/"
-PASS Parsing: <file:> against <about:blank>
-PASS Parsing: <file:?q=v> against <about:blank>
-PASS Parsing: <file:#frag> against <about:blank>
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-PASS Parsing: <file:///y:> against <about:blank>
-PASS Parsing: <file:///y:/> against <about:blank>
-PASS Parsing: <file:///./y> against <about:blank>
-PASS Parsing: <file:///./y:> against <about:blank>
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo"
+FAIL Parsing: <file:/C|/> without base assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
+FAIL Parsing: <file://C|/> without base assert_equals: href expected "file:///C:/" but got "file://c%7C/"
+PASS Parsing: <file:> without base
+PASS Parsing: <file:?q=v> without base
+PASS Parsing: <file:#frag> without base
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+PASS Parsing: <file:///y:> without base
+PASS Parsing: <file:///y:/> without base
+PASS Parsing: <file:///./y> without base
+PASS Parsing: <file:///./y:> without base
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file:///foo"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <file:///.//> against <file:////>
-PASS Parsing: <file:.//p> against <about:blank>
-PASS Parsing: <file:/.//p> against <about:blank>
+PASS Parsing: <file:.//p> without base
+PASS Parsing: <file:/.//p> without base
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=javascript-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=javascript-expected.txt
index c84000a..f9c6986 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=javascript-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=javascript-expected.txt
@@ -2,21 +2,21 @@
 PASS Loading data…
 PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <javascript:/example.com/> against <about:blank>
-PASS Parsing: <javascript:example.com/> against <about:blank>
-FAIL Parsing: <javascript:/../> against <about:blank> assert_equals: href expected "javascript:/" but got "javascript:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <javascript:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <javascript://test/a/../b> against <about:blank> assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
-FAIL Parsing: <javascript://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <javascript:/example.com/> without base
+PASS Parsing: <javascript:example.com/> without base
+FAIL Parsing: <javascript:/../> without base assert_equals: href expected "javascript:/" but got "javascript:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <javascript://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <javascript:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <javascript://test/a/../b> without base assert_equals: href expected "javascript://test/b" but got "javascript://test/a/../b"
+FAIL Parsing: <javascript://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <javascript://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <javascript://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=mailto-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=mailto-expected.txt
index 76ca25f4..f33c013 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=mailto-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_include=mailto-expected.txt
@@ -2,22 +2,22 @@
 PASS Loading data…
 PASS Parsing: <mailto:/example.com/> against <http://example.org/foo/bar>
 PASS Parsing: <mailto:example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <mailto:/example.com/> against <about:blank>
-PASS Parsing: <mailto:example.com/> against <about:blank>
+PASS Parsing: <mailto:/example.com/> without base
+PASS Parsing: <mailto:example.com/> without base
 PASS Parsing: <#x> against <mailto:x@x.com>
-FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: href expected "mailto:/" but got "mailto:/../"
-PASS Parsing: <> against <about:blank>
-FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
-FAIL Parsing: <mailto:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <mailto://test/a/../b> against <about:blank> assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
-FAIL Parsing: <mailto://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto:/../> without base assert_equals: href expected "mailto:/" but got "mailto:/../"
+PASS Parsing: <> without base
+FAIL Parsing: <mailto://example.com:8080/pathname?search#hash> without base assert_equals: href expected "mailto://example.com:8080/pathname?search#hash" but got "mailto://example.com:8080/pathname?search%23hash"
+FAIL Parsing: <mailto:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <mailto://test/a/../b> without base assert_equals: href expected "mailto://test/b" but got "mailto://test/a/../b"
+FAIL Parsing: <mailto://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <mailto://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <mailto://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any-expected.txt
index b882097..eff480d 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-PASS Origin parsing: <https://faß.ExAmPlE/> against <about:blank>
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+PASS Origin parsing: <https://faß.ExAmPlE/> without base
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-PASS Origin parsing: <h://.> against <about:blank>
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+PASS Origin parsing: <h://.> without base
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any.worker-expected.txt
index b882097..eff480d 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any.worker-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-PASS Origin parsing: <https://faß.ExAmPlE/> against <about:blank>
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+PASS Origin parsing: <https://faß.ExAmPlE/> without base
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-PASS Origin parsing: <h://.> against <about:blank>
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+PASS Origin parsing: <h://.> without base
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git "a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index 79cf282..8cbb574 100644
--- "a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 347 PASS, 313 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 347 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git "a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index 79cf282..8cbb574 100644
--- "a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 347 PASS, 313 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 347 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac13-arm64/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker-expected.txt
new file mode 100644
index 0000000..6c9a04cb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac13-arm64/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS Test we can transfer a Video MediaStreamTrackProcessor stream
+PASS Test we can transfer an Audio MediaStreamTrackProcessor stream
+Harness: the test ran to completion.
+
diff --git "a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index 79cf282..8cbb574 100644
--- "a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 347 PASS, 313 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 347 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/failure-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/failure-expected.txt
index b2c687c..e53a616 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/failure-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/failure-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1205 tests; 882 PASS, 323 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1205 tests; 886 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS URL's constructor's base argument: file://example:1/ should throw
 PASS URL's href: file://example:1/ should throw
@@ -893,6 +893,10 @@
 PASS sendBeacon(): file://xn--/p should throw
 FAIL Location's href: file://xn--/p should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
 FAIL window.open(): file://xn--/p should throw assert_throws_dom: function "() => self.open(test.input).close()" threw object "TypeError: Cannot read properties of null (reading 'close')" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12
+PASS URL's constructor's base argument: # should throw
+PASS URL's href: # should throw
+PASS URL's constructor's base argument: ? should throw
+PASS URL's href: ? should throw
 PASS URL's constructor's base argument: http://0..0x300/ should throw
 PASS URL's href: http://0..0x300/ should throw
 PASS XHR: http://0..0x300/ should throw
@@ -1057,10 +1061,6 @@
 PASS window.open(): https://￿y should throw
 PASS URL's constructor's base argument:  should throw
 PASS URL's href:  should throw
-FAIL XHR:  should throw assert_throws_dom: function "() => client.open("GET", test.input)" did not throw
-FAIL sendBeacon():  should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw
-FAIL Location's href:  should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
-FAIL window.open():  should throw assert_throws_dom: function "() => self.open(test.input).close()" did not throw
 PASS URL's constructor's base argument: https://­/ should throw
 PASS URL's href: https://­/ should throw
 PASS XHR: https://­/ should throw
diff --git "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index 4eda65ae2..23ffa0d 100644
--- "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 PASS Parsing: <a:	 foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -78,7 +78,7 @@
 PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar>
 FAIL Parsing: <http://[::127.0.0.1.]> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>
@@ -108,116 +108,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -232,54 +232,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-PASS Parsing: <https://faß.ExAmPlE/> against <about:blank>
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+PASS Parsing: <https://faß.ExAmPlE/> without base
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -288,34 +288,34 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: host expected "." but got ""
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: host expected "." but got ""
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1.2]> against <http://other.com/>
 FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -325,8 +325,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -355,196 +355,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -562,60 +562,60 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-PASS Parsing: <\\\.\Y:> against <about:blank>
-PASS Parsing: <\\\.\y:> against <about:blank>
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+PASS Parsing: <\\\.\Y:> without base
+PASS Parsing: <\\\.\y:> without base
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -623,179 +623,179 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 PASS Parsing: <test-a-colon.html> against <a:>
 PASS Parsing: <test-a-colon-b.html> against <a:b>
 PASS Parsing: <test-a-colon-slash.html> against <a:/>
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> Failed to construct 'URL': Invalid URL
 PASS Parsing: <test-a-colon-slash-b.html> against <a:/b>
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_include=file-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
index 5b6c4784..bf0df7e 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 78 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html"
 FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar"
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-PASS Parsing: <file:/example.com/> against <about:blank>
+PASS Parsing: <file:/example.com/> without base
 PASS Parsing: <file:...> against <http://www.example.com/test>
 PASS Parsing: <file:..> against <http://www.example.com/test>
 PASS Parsing: <file:a> against <http://www.example.com/test>
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///"
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox"
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base assert_equals: href expected "file:////?fox" but got "file:///?fox"
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar"
 PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux>
 PASS Parsing: </c:/foo/bar> against <file://host/path>
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/"
 PASS Parsing: </C:/> against <file://host/>
 PASS Parsing: <file:C:/> against <file://host/>
@@ -102,40 +102,40 @@
 FAIL Parsing: <file://C:/> against <file://host/> Failed to construct 'URL': Invalid URL
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
-FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/"
-PASS Parsing: <file:> against <about:blank>
-PASS Parsing: <file:?q=v> against <about:blank>
-PASS Parsing: <file:#frag> against <about:blank>
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-PASS Parsing: <file:///y:> against <about:blank>
-PASS Parsing: <file:///y:/> against <about:blank>
-PASS Parsing: <file:///./y> against <about:blank>
-PASS Parsing: <file:///./y:> against <about:blank>
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo"
+FAIL Parsing: <file:/C|/> without base assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
+FAIL Parsing: <file://C|/> without base assert_equals: href expected "file:///C:/" but got "file://c%7C/"
+PASS Parsing: <file:> without base
+PASS Parsing: <file:?q=v> without base
+PASS Parsing: <file:#frag> without base
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+PASS Parsing: <file:///y:> without base
+PASS Parsing: <file:///y:/> without base
+PASS Parsing: <file:///./y> without base
+PASS Parsing: <file:///./y:> without base
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file:///foo"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <file:///.//> against <file:////>
-PASS Parsing: <file:.//p> against <about:blank>
-PASS Parsing: <file:/.//p> against <about:blank>
+PASS Parsing: <file:.//p> without base
+PASS Parsing: <file:/.//p> without base
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index 4eda65ae2..23ffa0d 100644
--- "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 PASS Parsing: <a:	 foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -78,7 +78,7 @@
 PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar>
 FAIL Parsing: <http://[::127.0.0.1.]> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>
@@ -108,116 +108,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -232,54 +232,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-PASS Parsing: <https://faß.ExAmPlE/> against <about:blank>
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+PASS Parsing: <https://faß.ExAmPlE/> without base
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -288,34 +288,34 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: host expected "." but got ""
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: host expected "." but got ""
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1.2]> against <http://other.com/>
 FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -325,8 +325,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -355,196 +355,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -562,60 +562,60 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-PASS Parsing: <\\\.\Y:> against <about:blank>
-PASS Parsing: <\\\.\y:> against <about:blank>
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+PASS Parsing: <\\\.\Y:> without base
+PASS Parsing: <\\\.\y:> without base
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -623,179 +623,179 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 PASS Parsing: <test-a-colon.html> against <a:>
 PASS Parsing: <test-a-colon-b.html> against <a:b>
 PASS Parsing: <test-a-colon-slash.html> against <a:/>
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> Failed to construct 'URL': Invalid URL
 PASS Parsing: <test-a-colon-slash-b.html> against <a:/b>
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_include=file-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_include=file-expected.txt
index 5b6c4784..bf0df7e 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 78 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar>
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html"
 FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar"
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-PASS Parsing: <file:/example.com/> against <about:blank>
+PASS Parsing: <file:/example.com/> without base
 PASS Parsing: <file:...> against <http://www.example.com/test>
 PASS Parsing: <file:..> against <http://www.example.com/test>
 PASS Parsing: <file:a> against <http://www.example.com/test>
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///"
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox"
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base assert_equals: href expected "file:////?fox" but got "file:///?fox"
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file:///#guppy"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar"
 PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux>
 PASS Parsing: </c:/foo/bar> against <file://host/path>
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/"
 PASS Parsing: </C:/> against <file://host/>
 PASS Parsing: <file:C:/> against <file://host/>
@@ -102,40 +102,40 @@
 FAIL Parsing: <file://C:/> against <file://host/> Failed to construct 'URL': Invalid URL
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
-FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/"
-PASS Parsing: <file:> against <about:blank>
-PASS Parsing: <file:?q=v> against <about:blank>
-PASS Parsing: <file:#frag> against <about:blank>
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-PASS Parsing: <file:///y:> against <about:blank>
-PASS Parsing: <file:///y:/> against <about:blank>
-PASS Parsing: <file:///./y> against <about:blank>
-PASS Parsing: <file:///./y:> against <about:blank>
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo"
+FAIL Parsing: <file:/C|/> without base assert_equals: href expected "file:///C:/" but got "file:///C%7C/"
+FAIL Parsing: <file://C|/> without base assert_equals: href expected "file:///C:/" but got "file://c%7C/"
+PASS Parsing: <file:> without base
+PASS Parsing: <file:?q=v> without base
+PASS Parsing: <file:#frag> without base
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+PASS Parsing: <file:///y:> without base
+PASS Parsing: <file:///y:/> without base
+PASS Parsing: <file:///./y> without base
+PASS Parsing: <file:///./y:> without base
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file:///foo"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two"
 PASS Parsing: <file:///.//> against <file:////>
-PASS Parsing: <file:.//p> against <about:blank>
-PASS Parsing: <file:/.//p> against <about:blank>
+PASS Parsing: <file:.//p> without base
+PASS Parsing: <file:/.//p> without base
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any-expected.txt
index b882097..eff480d 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-PASS Origin parsing: <https://faß.ExAmPlE/> against <about:blank>
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+PASS Origin parsing: <https://faß.ExAmPlE/> without base
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-PASS Origin parsing: <h://.> against <about:blank>
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+PASS Origin parsing: <h://.> without base
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any.worker-expected.txt
index b882097..eff480d 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any.worker-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-PASS Origin parsing: <https://faß.ExAmPlE/> against <about:blank>
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+PASS Origin parsing: <https://faß.ExAmPlE/> without base
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-PASS Origin parsing: <h://.> against <about:blank>
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+PASS Origin parsing: <h://.> without base
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any-expected.txt
index 1ba815f..1037440 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 403 tests; 250 PASS, 153 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 403 tests; 252 PASS, 151 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
 PASS idl_test validation
 PASS Partial interface MLContext: original interface defined
@@ -222,7 +222,7 @@
 FAIL MLGraphBuilder interface: operation lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstm" missing
 FAIL MLGraphBuilder interface: operation lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstmCell" missing
 FAIL MLGraphBuilder interface: operation matmul(MLOperand, MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "matmul" missing
-FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_own_property: interface prototype object missing non-static operation expected property "pad" missing
+FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_equals: property has wrong .length expected 2 but got 3
 PASS MLGraphBuilder interface: operation averagePool2d(MLOperand, optional MLPool2dOptions)
 FAIL MLGraphBuilder interface: operation l2Pool2d(MLOperand, optional MLPool2dOptions) assert_own_property: interface prototype object missing non-static operation expected property "l2Pool2d" missing
 PASS MLGraphBuilder interface: operation maxPool2d(MLOperand, optional MLPool2dOptions)
@@ -342,8 +342,8 @@
 FAIL MLGraphBuilder interface: calling lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) on builder with too few arguments must throw TypeError assert_inherits: property "lstmCell" not found in prototype chain
 FAIL MLGraphBuilder interface: builder must inherit property "matmul(MLOperand, MLOperand)" with the proper type assert_inherits: property "matmul" not found in prototype chain
 FAIL MLGraphBuilder interface: calling matmul(MLOperand, MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "matmul" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type assert_inherits: property "pad" not found in prototype chain
-FAIL MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError assert_inherits: property "pad" not found in prototype chain
+PASS MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type
+PASS MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "averagePool2d(MLOperand, optional MLPool2dOptions)" with the proper type
 PASS MLGraphBuilder interface: calling averagePool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError
 FAIL MLGraphBuilder interface: builder must inherit property "l2Pool2d(MLOperand, optional MLPool2dOptions)" with the proper type assert_inherits: property "l2Pool2d" not found in prototype chain
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any.worker-expected.txt
index eeaa9227..7128d20f 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 409 tests; 255 PASS, 154 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 409 tests; 257 PASS, 152 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented"
 PASS idl_test validation
 PASS Partial interface MLContext: original interface defined
@@ -227,7 +227,7 @@
 FAIL MLGraphBuilder interface: operation lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstm" missing
 FAIL MLGraphBuilder interface: operation lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstmCell" missing
 FAIL MLGraphBuilder interface: operation matmul(MLOperand, MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "matmul" missing
-FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_own_property: interface prototype object missing non-static operation expected property "pad" missing
+FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_equals: property has wrong .length expected 2 but got 3
 PASS MLGraphBuilder interface: operation averagePool2d(MLOperand, optional MLPool2dOptions)
 FAIL MLGraphBuilder interface: operation l2Pool2d(MLOperand, optional MLPool2dOptions) assert_own_property: interface prototype object missing non-static operation expected property "l2Pool2d" missing
 PASS MLGraphBuilder interface: operation maxPool2d(MLOperand, optional MLPool2dOptions)
@@ -348,8 +348,8 @@
 FAIL MLGraphBuilder interface: calling lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) on builder with too few arguments must throw TypeError assert_inherits: property "lstmCell" not found in prototype chain
 FAIL MLGraphBuilder interface: builder must inherit property "matmul(MLOperand, MLOperand)" with the proper type assert_inherits: property "matmul" not found in prototype chain
 FAIL MLGraphBuilder interface: calling matmul(MLOperand, MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "matmul" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type assert_inherits: property "pad" not found in prototype chain
-FAIL MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError assert_inherits: property "pad" not found in prototype chain
+PASS MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type
+PASS MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "averagePool2d(MLOperand, optional MLPool2dOptions)" with the proper type
 PASS MLGraphBuilder interface: calling averagePool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError
 FAIL MLGraphBuilder interface: builder must inherit property "l2Pool2d(MLOperand, optional MLPool2dOptions)" with the proper type assert_inherits: property "l2Pool2d" not found in prototype chain
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
index 354d8d7..b686296 100644
--- "a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 342 PASS, 318 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 342 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index 354d8d7..b686296 100644
--- "a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 660 tests; 342 PASS, 318 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 661 tests; 342 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -589,6 +589,7 @@
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
+FAIL Parsing: <?> against <about:blank> assert_equals: failure should set href to input expected "?" but got ""
 FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/"
 FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./"
 PASS Parsing: <http://0..0x300/> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/failure-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/failure-expected.txt
index 95c7ca26..95cc6971 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/failure-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/failure-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1205 tests; 878 PASS, 327 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1205 tests; 882 PASS, 323 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS URL's constructor's base argument: file://example:1/ should throw
 PASS URL's href: file://example:1/ should throw
@@ -893,6 +893,10 @@
 PASS sendBeacon(): file://xn--/p should throw
 FAIL Location's href: file://xn--/p should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
 FAIL window.open(): file://xn--/p should throw assert_throws_dom: function "() => self.open(test.input).close()" threw object "TypeError: Cannot read properties of null (reading 'close')" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12
+PASS URL's constructor's base argument: # should throw
+PASS URL's href: # should throw
+PASS URL's constructor's base argument: ? should throw
+PASS URL's href: ? should throw
 PASS URL's constructor's base argument: http://0..0x300/ should throw
 PASS URL's href: http://0..0x300/ should throw
 PASS XHR: http://0..0x300/ should throw
@@ -1057,10 +1061,6 @@
 PASS window.open(): https://￿y should throw
 PASS URL's constructor's base argument:  should throw
 PASS URL's href:  should throw
-FAIL XHR:  should throw assert_throws_dom: function "() => client.open("GET", test.input)" did not throw
-FAIL sendBeacon():  should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw
-FAIL Location's href:  should throw assert_throws_dom: function "() => frame.contentWindow.location = test.input" did not throw
-FAIL window.open():  should throw assert_throws_dom: function "() => self.open(test.input).close()" did not throw
 PASS URL's constructor's base argument: https://­/ should throw
 PASS URL's href: https://­/ should throw
 PASS XHR: https://­/ should throw
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index f59aee5..372ec55 100644
--- "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 FAIL Parsing: <a:	 foo.com> against <http://example.org/foo/bar> assert_equals: href expected "a: foo.com" but got "file:///A:/%20foo.com"
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -78,7 +78,7 @@
 PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar>
 FAIL Parsing: <http://[::127.0.0.1.]> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>
@@ -108,116 +108,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -232,54 +232,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-PASS Parsing: <https://faß.ExAmPlE/> against <about:blank>
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+PASS Parsing: <https://faß.ExAmPlE/> without base
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -288,34 +288,34 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: href expected "h://." but got "file:///H://"
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: href expected "h://." but got "file:///H://"
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1.2]> against <http://other.com/>
 FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -325,8 +325,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -355,196 +355,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -562,64 +562,64 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-FAIL Parsing: <\\\.\Y:> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+FAIL Parsing: <\\\.\Y:> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <\\\.\y:> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <\\\.\y:> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -627,183 +627,183 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 FAIL Parsing: <test-a-colon.html> against <a:> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <test-a-colon-b.html> against <a:b> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <test-a-colon-slash.html> against <a:/> assert_equals: href expected "a:/test-a-colon-slash.html" but got "file:///A:/test-a-colon-slash.html"
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> assert_equals: href expected "a:///test-a-colon-slash-slash.html" but got "file:///A://test-a-colon-slash-slash.html"
 FAIL Parsing: <test-a-colon-slash-b.html> against <a:/b> assert_equals: href expected "a:/test-a-colon-slash-b.html" but got "file:///A:/test-a-colon-slash-b.html"
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> assert_equals: href expected "a://b/test-a-colon-slash-slash-b.html" but got "file:///A://test-a-colon-slash-slash-b.html"
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_include=file-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
index 592f8c7..4722982c 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 70 PASS, 56 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 FAIL Parsing: <file:/example.com/> against <http://example.org/foo/bar> assert_equals: href expected "file:///example.com/" but got "file://example.com/"
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///C:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///C:////foo/bar.html"
 PASS Parsing: <C|/foo/bar> against <file:///tmp/mock/path>
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-FAIL Parsing: <file:/example.com/> against <about:blank> assert_equals: href expected "file:///example.com/" but got "file://example.com/"
+FAIL Parsing: <file:/example.com/> without base assert_equals: href expected "file:///example.com/" but got "file://example.com/"
 FAIL Parsing: <file:...> against <http://www.example.com/test> assert_equals: href expected "file:///..." but got "file://.../"
 FAIL Parsing: <file:..> against <http://www.example.com/test> assert_equals: href expected "file:///" but got "file://../"
 FAIL Parsing: <file:a> against <http://www.example.com/test> assert_equals: href expected "file:///a" but got "file://a/"
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 PASS Parsing: <..> against <file:///C:/>
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file://%23guppy/"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file://localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file://%23guppy/"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file://localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file://mouse/"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///C:/foo/bar"
 FAIL Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///C:/foo/bar"
 FAIL Parsing: </c:/foo/bar> against <file://host/path> assert_equals: href expected "file://host/c:/foo/bar" but got "file:///C:/foo/bar"
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file:///C:/"
 FAIL Parsing: </C:/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file:///C:/"
 FAIL Parsing: <file:C:/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file:///C:/"
@@ -102,40 +102,40 @@
 PASS Parsing: <file://C:/> against <file://host/>
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-PASS Parsing: <file:/C|/> against <about:blank>
-PASS Parsing: <file://C|/> against <about:blank>
-PASS Parsing: <file:> against <about:blank>
-FAIL Parsing: <file:?q=v> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <file:#frag> against <about:blank> assert_equals: href expected "file:///#frag" but got "file://%23frag/"
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-FAIL Parsing: <file:///y:> against <about:blank> assert_equals: href expected "file:///y:" but got "file:///Y:"
-FAIL Parsing: <file:///y:/> against <about:blank> assert_equals: href expected "file:///y:/" but got "file:///Y:/"
-PASS Parsing: <file:///./y> against <about:blank>
-FAIL Parsing: <file:///./y:> against <about:blank> assert_equals: href expected "file:///y:" but got "file:///Y:"
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file://foo/"
+PASS Parsing: <file:/C|/> without base
+PASS Parsing: <file://C|/> without base
+PASS Parsing: <file:> without base
+FAIL Parsing: <file:?q=v> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <file:#frag> without base assert_equals: href expected "file:///#frag" but got "file://%23frag/"
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+FAIL Parsing: <file:///y:> without base assert_equals: href expected "file:///y:" but got "file:///Y:"
+FAIL Parsing: <file:///y:/> without base assert_equals: href expected "file:///y:/" but got "file:///Y:/"
+PASS Parsing: <file:///./y> without base
+FAIL Parsing: <file:///./y:> without base assert_equals: href expected "file:///y:" but got "file:///Y:"
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file://foo/"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file://one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file://one/two"
 PASS Parsing: <file:///.//> against <file:////>
-FAIL Parsing: <file:.//p> against <about:blank> assert_equals: href expected "file:////p" but got "file://.//p"
-FAIL Parsing: <file:/.//p> against <about:blank> assert_equals: href expected "file:////p" but got "file://.//p"
+FAIL Parsing: <file:.//p> without base assert_equals: href expected "file:////p" but got "file://.//p"
+FAIL Parsing: <file:/.//p> without base assert_equals: href expected "file:////p" but got "file://.//p"
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index f59aee5..372ec55 100644
--- "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -4,17 +4,17 @@
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Parsing: <https://test:@test> against <about:blank>
-PASS Parsing: <https://:@test> against <about:blank>
-FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
-FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
+PASS Parsing: <https://test:@test> without base
+PASS Parsing: <https://:@test> without base
+FAIL Parsing: <non-special://test:@test/x> without base assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x"
+FAIL Parsing: <non-special://:@test/x> without base assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x"
 PASS Parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
 PASS Parsing: < foo.com  > against <http://example.org/foo/bar>
 FAIL Parsing: <a:	 foo.com> against <http://example.org/foo/bar> assert_equals: href expected "a: foo.com" but got "file:///A:/%20foo.com"
 PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>
-PASS Parsing: <lolscheme:x x#x x> against <about:blank>
+PASS Parsing: <lolscheme:x x#x x> without base
 PASS Parsing: <http://f:/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar>
@@ -26,7 +26,7 @@
 PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar>
 PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar>
 FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>
 PASS Parsing: <> against <http://example.org/foo/bar>
@@ -78,7 +78,7 @@
 PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar>
 FAIL Parsing: <http://[::127.0.0.1.]> against <http://example.org/foo/bar> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar>
 PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>
@@ -108,116 +108,116 @@
 PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar>
 FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got ""
-PASS Parsing: <http://example.com/././foo> against <about:blank>
-PASS Parsing: <http://example.com/./.foo> against <about:blank>
-PASS Parsing: <http://example.com/foo/.> against <about:blank>
-PASS Parsing: <http://example.com/foo/./> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Parsing: <http://example.com/foo/%2e> against <about:blank>
-FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
-FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
-PASS Parsing: <http://example.com////../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Parsing: <http://example.com/foo> against <about:blank>
-PASS Parsing: <http://example.com/%20foo> against <about:blank>
-PASS Parsing: <http://example.com/foo%> against <about:blank>
-PASS Parsing: <http://example.com/foo%2> against <about:blank>
-PASS Parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank>
-FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
-PASS Parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Parsing: <http://example.com/你好你好> against <about:blank>
-PASS Parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Parsing: <http://example.com//foo> against <about:blank>
-PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Parsing: <data:test# »> against <about:blank>
-PASS Parsing: <http://www.google.com> against <about:blank>
-PASS Parsing: <http://192.0x00A80001> against <about:blank>
-FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
-PASS Parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Parsing: <http://user:pass@/> against <about:blank>
-PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Parsing: <http://foo:80/> against <about:blank>
-PASS Parsing: <http://foo:81/> against <about:blank>
-FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got ""
-PASS Parsing: <http://foo:-80/> against <about:blank>
-PASS Parsing: <https://foo:443/> against <about:blank>
-PASS Parsing: <https://foo:80/> against <about:blank>
-PASS Parsing: <ftp://foo:21/> against <about:blank>
-PASS Parsing: <ftp://foo:80/> against <about:blank>
-FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got ""
-FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got ""
-PASS Parsing: <ws://foo:80/> against <about:blank>
-PASS Parsing: <ws://foo:81/> against <about:blank>
-PASS Parsing: <ws://foo:443/> against <about:blank>
-PASS Parsing: <ws://foo:815/> against <about:blank>
-PASS Parsing: <wss://foo:80/> against <about:blank>
-PASS Parsing: <wss://foo:81/> against <about:blank>
-PASS Parsing: <wss://foo:443/> against <about:blank>
-PASS Parsing: <wss://foo:815/> against <about:blank>
-PASS Parsing: <http:/example.com/> against <about:blank>
-PASS Parsing: <ftp:/example.com/> against <about:blank>
-PASS Parsing: <https:/example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Parsing: <ftps:/example.com/> against <about:blank>
-PASS Parsing: <gopher:/example.com/> against <about:blank>
-PASS Parsing: <ws:/example.com/> against <about:blank>
-PASS Parsing: <wss:/example.com/> against <about:blank>
-PASS Parsing: <data:/example.com/> against <about:blank>
-PASS Parsing: <http:example.com/> against <about:blank>
-PASS Parsing: <ftp:example.com/> against <about:blank>
-PASS Parsing: <https:example.com/> against <about:blank>
-PASS Parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Parsing: <ftps:example.com/> against <about:blank>
-PASS Parsing: <gopher:example.com/> against <about:blank>
-PASS Parsing: <ws:example.com/> against <about:blank>
-PASS Parsing: <wss:example.com/> against <about:blank>
-PASS Parsing: <data:example.com/> against <about:blank>
-PASS Parsing: <http:@www.example.com> against <about:blank>
-PASS Parsing: <http:/@www.example.com> against <about:blank>
-PASS Parsing: <http://@www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Parsing: <http://@pple.com> against <about:blank>
-PASS Parsing: <http::b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Parsing: <http://:b@www.example.com> against <about:blank>
-PASS Parsing: <http:/:@/www.example.com> against <about:blank>
-PASS Parsing: <http://user@/www.example.com> against <about:blank>
-PASS Parsing: <http:@/www.example.com> against <about:blank>
-PASS Parsing: <http:/@/www.example.com> against <about:blank>
-PASS Parsing: <http://@/www.example.com> against <about:blank>
-PASS Parsing: <https:@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http:/a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http://a:b@/www.example.com> against <about:blank>
-PASS Parsing: <http::@/www.example.com> against <about:blank>
-PASS Parsing: <http:a:@www.example.com> against <about:blank>
-PASS Parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Parsing: <http://a:@www.example.com> against <about:blank>
-PASS Parsing: <http://www.@pple.com> against <about:blank>
-PASS Parsing: <http:@:www.example.com> against <about:blank>
-PASS Parsing: <http:/@:www.example.com> against <about:blank>
-PASS Parsing: <http://@:www.example.com> against <about:blank>
-PASS Parsing: <http://:@www.example.com> against <about:blank>
+PASS Parsing: <http://example.com/././foo> without base
+PASS Parsing: <http://example.com/./.foo> without base
+PASS Parsing: <http://example.com/foo/.> without base
+PASS Parsing: <http://example.com/foo/./> without base
+PASS Parsing: <http://example.com/foo/bar/..> without base
+PASS Parsing: <http://example.com/foo/bar/../> without base
+PASS Parsing: <http://example.com/foo/..bar> without base
+PASS Parsing: <http://example.com/foo/bar/../ton> without base
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Parsing: <http://example.com/foo/../../..> without base
+PASS Parsing: <http://example.com/foo/../../../ton> without base
+PASS Parsing: <http://example.com/foo/%2e> without base
+FAIL Parsing: <http://example.com/foo/%2e%2> without base assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar"
+PASS Parsing: <http://example.com////../..> without base
+PASS Parsing: <http://example.com/foo/bar//../..> without base
+PASS Parsing: <http://example.com/foo/bar//..> without base
+PASS Parsing: <http://example.com/foo> without base
+PASS Parsing: <http://example.com/%20foo> without base
+PASS Parsing: <http://example.com/foo%> without base
+PASS Parsing: <http://example.com/foo%2> without base
+PASS Parsing: <http://example.com/foo%2zbar> without base
+PASS Parsing: <http://example.com/foo%2©zbar> without base
+FAIL Parsing: <http://example.com/foo%41%7a> without base assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz"
+PASS Parsing: <http://example.com/foo	‘%91> without base
+FAIL Parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Parsing: <http://example.com/foo	bar> without base
+PASS Parsing: <http://example.com\\foo\\bar> without base
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Parsing: <http://example.com/@asdf%40> without base
+PASS Parsing: <http://example.com/你好你好> without base
+PASS Parsing: <http://example.com/‥/foo> without base
+PASS Parsing: <http://example.com//foo> without base
+PASS Parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Parsing: <data:test# »> without base
+PASS Parsing: <http://www.google.com> without base
+PASS Parsing: <http://192.0x00A80001> without base
+FAIL Parsing: <http://www/foo%2Ehtml> without base assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html"
+PASS Parsing: <http://www/foo/%2E/html> without base
+PASS Parsing: <http://user:pass@/> without base
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Parsing: <http:\\www.google.com\foo> without base
+PASS Parsing: <http://foo:80/> without base
+PASS Parsing: <http://foo:81/> without base
+FAIL Parsing: <httpa://foo:80/> without base assert_equals: host expected "foo:80" but got ""
+PASS Parsing: <http://foo:-80/> without base
+PASS Parsing: <https://foo:443/> without base
+PASS Parsing: <https://foo:80/> without base
+PASS Parsing: <ftp://foo:21/> without base
+PASS Parsing: <ftp://foo:80/> without base
+FAIL Parsing: <gopher://foo:70/> without base assert_equals: host expected "foo:70" but got ""
+FAIL Parsing: <gopher://foo:443/> without base assert_equals: host expected "foo:443" but got ""
+PASS Parsing: <ws://foo:80/> without base
+PASS Parsing: <ws://foo:81/> without base
+PASS Parsing: <ws://foo:443/> without base
+PASS Parsing: <ws://foo:815/> without base
+PASS Parsing: <wss://foo:80/> without base
+PASS Parsing: <wss://foo:81/> without base
+PASS Parsing: <wss://foo:443/> without base
+PASS Parsing: <wss://foo:815/> without base
+PASS Parsing: <http:/example.com/> without base
+PASS Parsing: <ftp:/example.com/> without base
+PASS Parsing: <https:/example.com/> without base
+PASS Parsing: <madeupscheme:/example.com/> without base
+PASS Parsing: <ftps:/example.com/> without base
+PASS Parsing: <gopher:/example.com/> without base
+PASS Parsing: <ws:/example.com/> without base
+PASS Parsing: <wss:/example.com/> without base
+PASS Parsing: <data:/example.com/> without base
+PASS Parsing: <http:example.com/> without base
+PASS Parsing: <ftp:example.com/> without base
+PASS Parsing: <https:example.com/> without base
+PASS Parsing: <madeupscheme:example.com/> without base
+PASS Parsing: <ftps:example.com/> without base
+PASS Parsing: <gopher:example.com/> without base
+PASS Parsing: <ws:example.com/> without base
+PASS Parsing: <wss:example.com/> without base
+PASS Parsing: <data:example.com/> without base
+PASS Parsing: <http:@www.example.com> without base
+PASS Parsing: <http:/@www.example.com> without base
+PASS Parsing: <http://@www.example.com> without base
+PASS Parsing: <http:a:b@www.example.com> without base
+PASS Parsing: <http:/a:b@www.example.com> without base
+PASS Parsing: <http://a:b@www.example.com> without base
+PASS Parsing: <http://@pple.com> without base
+PASS Parsing: <http::b@www.example.com> without base
+PASS Parsing: <http:/:b@www.example.com> without base
+PASS Parsing: <http://:b@www.example.com> without base
+PASS Parsing: <http:/:@/www.example.com> without base
+PASS Parsing: <http://user@/www.example.com> without base
+PASS Parsing: <http:@/www.example.com> without base
+PASS Parsing: <http:/@/www.example.com> without base
+PASS Parsing: <http://@/www.example.com> without base
+PASS Parsing: <https:@/www.example.com> without base
+PASS Parsing: <http:a:b@/www.example.com> without base
+PASS Parsing: <http:/a:b@/www.example.com> without base
+PASS Parsing: <http://a:b@/www.example.com> without base
+PASS Parsing: <http::@/www.example.com> without base
+PASS Parsing: <http:a:@www.example.com> without base
+PASS Parsing: <http:/a:@www.example.com> without base
+PASS Parsing: <http://a:@www.example.com> without base
+PASS Parsing: <http://www.@pple.com> without base
+PASS Parsing: <http:@:www.example.com> without base
+PASS Parsing: <http:/@:www.example.com> without base
+PASS Parsing: <http://@:www.example.com> without base
+PASS Parsing: <http://:@www.example.com> without base
 PASS Parsing: </> against <http://www.example.com/test>
 PASS Parsing: </test.txt> against <http://www.example.com/test>
 PASS Parsing: <.> against <http://www.example.com/test>
@@ -232,54 +232,54 @@
 PASS Parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 FAIL Parsing: <http://example example.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[]> against <http://other.com/>
 PASS Parsing: <http://[:]> against <http://other.com/>
 FAIL Parsing: <http://GOO  goo.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Parsing: <\0 http://example.com/ \r > without base
 PASS Parsing: <http://www.foo。bar.com> against <http://other.com/>
 PASS Parsing: <http://﷐zyx.com> against <http://other.com/>
 PASS Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>
-PASS Parsing: <https://�> against <about:blank>
-PASS Parsing: <https://%EF%BF%BD> against <about:blank>
-PASS Parsing: <https://x/�?�#�> against <about:blank>
-FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://�> without base
+PASS Parsing: <https://%EF%BF%BD> without base
+PASS Parsing: <https://x/�?�#�> without base
+FAIL Parsing: <http://a.b.c.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a.b.c.Xn--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.XN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://10.0.0.xN--pokxncvks> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://Go.com> against <http://other.com/>
 FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://%00.com> against <http://other.com/>
 PASS Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/>
 PASS Parsing: <http://你好你好> against <http://other.com/>
-PASS Parsing: <https://faß.ExAmPlE/> against <about:blank>
-FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
+PASS Parsing: <https://faß.ExAmPlE/> without base
+FAIL Parsing: <sc://faß.ExAmPlE/> without base assert_equals: host expected "fa%C3%9F.ExAmPlE" but got ""
 PASS Parsing: <http://%zz%66%a.com> against <http://other.com/>
 PASS Parsing: <http://%25> against <http://other.com/>
 PASS Parsing: <http://hello%00> against <http://other.com/>
@@ -288,34 +288,34 @@
 PASS Parsing: <http://192.168.0.257> against <http://other.com/>
 PASS Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/>
 FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <https://x x:12> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <https://x x:12> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Parsing: <http://./> against <about:blank>
-PASS Parsing: <http://../> against <about:blank>
-FAIL Parsing: <h://.> against <about:blank> assert_equals: href expected "h://." but got "file:///H://"
-PASS Parsing: <http://[www.google.com]/> against <about:blank>
+PASS Parsing: <http://./> without base
+PASS Parsing: <http://../> without base
+FAIL Parsing: <h://.> without base assert_equals: href expected "h://." but got "file:///H://"
+PASS Parsing: <http://[www.google.com]/> without base
 PASS Parsing: <http://[google.com]> against <http://other.com/>
 PASS Parsing: <http://[::1.2.3.4x]> against <http://other.com/>
 FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1.2]> against <http://other.com/>
 FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[::.1]> against <http://other.com/>
 FAIL Parsing: <http://[::%31]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <http://%5B::1]> against <http://other.com/> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Parsing: <#> against <test:test>
@@ -325,8 +325,8 @@
 PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Parsing: <http://host/?'> against <about:blank>
-FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
+PASS Parsing: <http://host/?'> without base
+FAIL Parsing: <notspecial://host/?'> without base assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27"
 PASS Parsing: </some/path> against <http://user@example.org/smth>
 PASS Parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -355,196 +355,196 @@
 PASS Parsing: <#i> against <sc:/pa/pa>
 FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got ""
 FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa"
-FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../"
-FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../"
-FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got ""
-FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got ""
-FAIL Parsing: <sc://@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <about:/../> without base assert_equals: href expected "about:/" but got "about:/../"
+FAIL Parsing: <data:/../> without base assert_equals: href expected "data:/" but got "data:/../"
+FAIL Parsing: <sc://ñ.test/> without base assert_equals: host expected "%C3%B1.test" but got ""
+FAIL Parsing: <sc://%/> without base assert_equals: host expected "%" but got ""
+FAIL Parsing: <sc://@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://te@s:t@/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://:12/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://:12/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Parsing: <sc:\../> against <about:blank>
-PASS Parsing: <sc::a@example.net> against <about:blank>
-PASS Parsing: <wow:%NBD> against <about:blank>
-PASS Parsing: <wow:%1G> against <about:blank>
-FAIL Parsing: <wow:￿> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
-FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://a\0b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <sc:\../> without base
+PASS Parsing: <sc::a@example.net> without base
+PASS Parsing: <wow:%NBD> without base
+PASS Parsing: <wow:%1G> without base
+FAIL Parsing: <wow:￿> without base assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD"
+FAIL Parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://a\0b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a[b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a[b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a\b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a\b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a]b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a]b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a^b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a^b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <sc://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <sc://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <foo://ho	st/> against <about:blank> assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho	st/> without base assert_equals: host expected "host" but got ""
 FAIL Parsing: <foo://ho
-st/> against <about:blank> assert_equals: host expected "host" but got ""
-FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <http://a\0b/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ab/> against <about:blank>
-FAIL Parsing: <http://a b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base assert_equals: host expected "host" but got ""
+FAIL Parsing: <foo://ho\rst/> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <http://a\0b/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ab/> without base
+FAIL Parsing: <http://a b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a%b/> against <about:blank>
-FAIL Parsing: <http://a<b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a%b/> without base
+FAIL Parsing: <http://a<b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://a>b> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://a>b> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://a[b/> against <about:blank>
-PASS Parsing: <http://a]b/> against <about:blank>
-PASS Parsing: <http://a^b> against <about:blank>
-FAIL Parsing: <http://a|b/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://a[b/> without base
+PASS Parsing: <http://a]b/> without base
+PASS Parsing: <http://a^b> without base
+FAIL Parsing: <http://a|b/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ab/> against <about:blank>
-PASS Parsing: <http://ho	st/> against <about:blank>
+PASS Parsing: <http://ab/> without base
+PASS Parsing: <http://ho	st/> without base
 PASS Parsing: <http://ho
-st/> against <about:blank>
-PASS Parsing: <http://ho\rst/> against <about:blank>
-PASS Parsing: <http://ho%00st/> against <about:blank>
-PASS Parsing: <http://ho%01st/> against <about:blank>
-PASS Parsing: <http://ho%02st/> against <about:blank>
-PASS Parsing: <http://ho%03st/> against <about:blank>
-PASS Parsing: <http://ho%04st/> against <about:blank>
-PASS Parsing: <http://ho%05st/> against <about:blank>
-PASS Parsing: <http://ho%06st/> against <about:blank>
-PASS Parsing: <http://ho%07st/> against <about:blank>
-PASS Parsing: <http://ho%08st/> against <about:blank>
-PASS Parsing: <http://ho%09st/> against <about:blank>
-PASS Parsing: <http://ho%0Ast/> against <about:blank>
-PASS Parsing: <http://ho%0Bst/> against <about:blank>
-PASS Parsing: <http://ho%0Cst/> against <about:blank>
-PASS Parsing: <http://ho%0Dst/> against <about:blank>
-PASS Parsing: <http://ho%0Est/> against <about:blank>
-PASS Parsing: <http://ho%0Fst/> against <about:blank>
-PASS Parsing: <http://ho%10st/> against <about:blank>
-PASS Parsing: <http://ho%11st/> against <about:blank>
-PASS Parsing: <http://ho%12st/> against <about:blank>
-PASS Parsing: <http://ho%13st/> against <about:blank>
-PASS Parsing: <http://ho%14st/> against <about:blank>
-PASS Parsing: <http://ho%15st/> against <about:blank>
-PASS Parsing: <http://ho%16st/> against <about:blank>
-PASS Parsing: <http://ho%17st/> against <about:blank>
-PASS Parsing: <http://ho%18st/> against <about:blank>
-PASS Parsing: <http://ho%19st/> against <about:blank>
-PASS Parsing: <http://ho%1Ast/> against <about:blank>
-PASS Parsing: <http://ho%1Bst/> against <about:blank>
-PASS Parsing: <http://ho%1Cst/> against <about:blank>
-PASS Parsing: <http://ho%1Dst/> against <about:blank>
-PASS Parsing: <http://ho%1Est/> against <about:blank>
-PASS Parsing: <http://ho%1Fst/> against <about:blank>
-FAIL Parsing: <http://ho%20st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+st/> without base
+PASS Parsing: <http://ho\rst/> without base
+PASS Parsing: <http://ho%00st/> without base
+PASS Parsing: <http://ho%01st/> without base
+PASS Parsing: <http://ho%02st/> without base
+PASS Parsing: <http://ho%03st/> without base
+PASS Parsing: <http://ho%04st/> without base
+PASS Parsing: <http://ho%05st/> without base
+PASS Parsing: <http://ho%06st/> without base
+PASS Parsing: <http://ho%07st/> without base
+PASS Parsing: <http://ho%08st/> without base
+PASS Parsing: <http://ho%09st/> without base
+PASS Parsing: <http://ho%0Ast/> without base
+PASS Parsing: <http://ho%0Bst/> without base
+PASS Parsing: <http://ho%0Cst/> without base
+PASS Parsing: <http://ho%0Dst/> without base
+PASS Parsing: <http://ho%0Est/> without base
+PASS Parsing: <http://ho%0Fst/> without base
+PASS Parsing: <http://ho%10st/> without base
+PASS Parsing: <http://ho%11st/> without base
+PASS Parsing: <http://ho%12st/> without base
+PASS Parsing: <http://ho%13st/> without base
+PASS Parsing: <http://ho%14st/> without base
+PASS Parsing: <http://ho%15st/> without base
+PASS Parsing: <http://ho%16st/> without base
+PASS Parsing: <http://ho%17st/> without base
+PASS Parsing: <http://ho%18st/> without base
+PASS Parsing: <http://ho%19st/> without base
+PASS Parsing: <http://ho%1Ast/> without base
+PASS Parsing: <http://ho%1Bst/> without base
+PASS Parsing: <http://ho%1Cst/> without base
+PASS Parsing: <http://ho%1Dst/> without base
+PASS Parsing: <http://ho%1Est/> without base
+PASS Parsing: <http://ho%1Fst/> without base
+FAIL Parsing: <http://ho%20st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%23st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%23st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%25st/> against <about:blank>
-PASS Parsing: <http://ho%2Fst/> against <about:blank>
-PASS Parsing: <http://ho%3Ast/> against <about:blank>
-FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%25st/> without base
+PASS Parsing: <http://ho%2Fst/> without base
+PASS Parsing: <http://ho%3Ast/> without base
+FAIL Parsing: <http://ho%3Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <http://ho%3Est/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%3Fst/> against <about:blank>
-FAIL Parsing: <http://ho%40st/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%3Fst/> without base
+FAIL Parsing: <http://ho%40st/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%5Bst/> against <about:blank>
-PASS Parsing: <http://ho%5Cst/> against <about:blank>
-PASS Parsing: <http://ho%5Dst/> against <about:blank>
-FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://ho%5Bst/> without base
+PASS Parsing: <http://ho%5Cst/> without base
+PASS Parsing: <http://ho%5Dst/> without base
+FAIL Parsing: <http://ho%7Cst/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <http://ho%7Fst/> against <about:blank>
-FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
-PASS Parsing: <ftp://example.com%80/> against <about:blank>
-PASS Parsing: <ftp://example.com%A0/> against <about:blank>
-PASS Parsing: <https://example.com%80/> against <about:blank>
-PASS Parsing: <https://example.com%A0/> against <about:blank>
-PASS Parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Parsing: <https://%e2%98%83> against <about:blank>
-PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Parsing: <http://ho%7Fst/> without base
+FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got ""
+PASS Parsing: <ftp://example.com%80/> without base
+PASS Parsing: <ftp://example.com%A0/> without base
+PASS Parsing: <https://example.com%80/> without base
+PASS Parsing: <https://example.com%A0/> without base
+PASS Parsing: <ftp://%e2%98%83> without base
+PASS Parsing: <https://%e2%98%83> without base
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <http://example.org/foo/bar>
 PASS Parsing: <http:> against <https://example.org/foo/bar>
 PASS Parsing: <sc:> against <https://example.org/foo/bar>
-PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Parsing: <http://192.168.257> against <http://other.com/>
@@ -562,64 +562,64 @@
 PASS Parsing: <http://0xffffffff> against <http://other.com/>
 PASS Parsing: <http://0xffffffff1> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256> against <http://other.com/>
-PASS Parsing: <https://0x.0x.0> against <about:blank>
-PASS Parsing: <https://0x100000000/test> against <about:blank>
-PASS Parsing: <https://256.0.0.1/test> against <about:blank>
-FAIL Parsing: <https://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <https://0x.0x.0> without base
+PASS Parsing: <https://0x100000000/test> without base
+PASS Parsing: <https://256.0.0.1/test> without base
+FAIL Parsing: <https://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43|/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43|/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got ""
-FAIL Parsing: <\\\.\Y:> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <asdf://%43%7C/> without base assert_equals: host expected "%43%7C" but got ""
+FAIL Parsing: <\\\.\Y:> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <\\\.\y:> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <\\\.\y:> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <http://[1:0::]> against <http://example.net/>
 PASS Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/>
-PASS Parsing: <https://[0::0::0]> against <about:blank>
-PASS Parsing: <https://[0:.0]> against <about:blank>
-PASS Parsing: <https://[0:0:]> against <about:blank>
-PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank>
-PASS Parsing: <https://[0:1.00.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.290.0.0.0]> against <about:blank>
-PASS Parsing: <https://[0:1.23.23]> against <about:blank>
-PASS Parsing: <http://?> against <about:blank>
-PASS Parsing: <http://#> against <about:blank>
+PASS Parsing: <https://[0::0::0]> without base
+PASS Parsing: <https://[0:.0]> without base
+PASS Parsing: <https://[0:0:]> without base
+PASS Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> without base
+PASS Parsing: <https://[0:1.00.0.0.0]> without base
+PASS Parsing: <https://[0:1.290.0.0.0]> without base
+PASS Parsing: <https://[0:1.23.23]> without base
+PASS Parsing: <http://?> without base
+PASS Parsing: <http://#> without base
 PASS Parsing: <http://f:4294967377/c> against <http://example.org/>
 PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/>
 PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/>
-FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
-FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ?x> without base assert_equals: host expected "%C3%B1" but got ""
+FAIL Parsing: <sc://ñ#x> without base assert_equals: host expected "%C3%B1" but got ""
 FAIL Parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//"
-FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://?> without base assert_equals: pathname expected "" but got "//"
+FAIL Parsing: <sc://#> without base assert_equals: pathname expected "" but got "//"
 FAIL Parsing: <///> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////> against <sc://x/> Failed to construct 'URL': Invalid URL
 FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/"
-FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got ""
-FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got ""
-FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got ""
-FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got ""
-FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got ""
-FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got ""
-FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got ""
-FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got ""
-FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got ""
-PASS Parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//"
-FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
-FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
-FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path"
-FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
-FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
+FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> without base assert_equals: host expected "foobar.com" but got ""
+FAIL Parsing: <telnet://user:pass@foobar.com:23/> without base assert_equals: username expected "user" but got ""
+FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base assert_equals: host expected "10.10.10.10:7777" but got ""
+FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <rsync://foo@host:911/sup> without base assert_equals: username expected "foo" but got ""
+FAIL Parsing: <git://github.com/foo/bar.git> without base assert_equals: host expected "github.com" but got ""
+FAIL Parsing: <irc://myserver.com:6999/channel?passwd> without base assert_equals: host expected "myserver.com:6999" but got ""
+FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base assert_equals: host expected "fw.example.org:9999" but got ""
+FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base assert_equals: host expected "localhost:389" but got ""
+FAIL Parsing: <git+https://github.com/foo/bar> without base assert_equals: host expected "github.com" but got ""
+PASS Parsing: <urn:ietf:rfc:2648> without base
+PASS Parsing: <tag:joe@example.org,2001:foo/bar> without base
+FAIL Parsing: <non-spec:/.//> without base assert_equals: pathname expected "//" but got "/.//"
+FAIL Parsing: <non-spec:/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//"
+FAIL Parsing: <non-spec:/a/..//> without base assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//"
+FAIL Parsing: <non-spec:/.//path> without base assert_equals: pathname expected "//path" but got "/.//path"
+FAIL Parsing: <non-spec:/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
+FAIL Parsing: <non-spec:/a/..//path> without base assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path"
 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path"
@@ -627,183 +627,183 @@
 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p"
 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path"
 FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path"
-FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got ""
-FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got ""
-FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
-FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
-FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got ""
-FAIL Parsing: <non-special://[:80/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <non-special://%E2%80%A0/> without base assert_equals: host expected "%E2%80%A0" but got ""
+FAIL Parsing: <non-special://H%4fSt/path> without base assert_equals: host expected "H%4fSt" but got ""
+FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> without base assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/"
+FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> without base assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/"
+FAIL Parsing: <non-special://[1:2::3]:80/> without base assert_equals: host expected "[1:2::3]:80" but got ""
+FAIL Parsing: <non-special://[:80/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Parsing: <blob:> against <about:blank>
-PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
-PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
-PASS Parsing: <http://[::127.0.0.0.1]> against <about:blank>
-PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank>
-PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank>
-PASS Parsing: <http://example.org/test?"> against <about:blank>
-PASS Parsing: <http://example.org/test?#> against <about:blank>
-PASS Parsing: <http://example.org/test?<> against <about:blank>
-PASS Parsing: <http://example.org/test?>> against <about:blank>
-PASS Parsing: <http://example.org/test?⌣> against <about:blank>
-PASS Parsing: <http://example.org/test?%23%23> against <about:blank>
-PASS Parsing: <http://example.org/test?%GH> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%EF> against <about:blank>
-PASS Parsing: <http://example.org/test?a#%GH> against <about:blank>
-PASS Parsing: <a> against <about:blank>
-PASS Parsing: <a/> against <about:blank>
-PASS Parsing: <a//> against <about:blank>
+PASS Parsing: <blob:https://example.com:443/> without base
+PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Parsing: <blob:> without base
+PASS Parsing: <http://0x7f.0.0.0x7g> without base
+PASS Parsing: <http://0X7F.0.0.0X7G> without base
+PASS Parsing: <http://[::127.0.0.0.1]> without base
+PASS Parsing: <http://[0:1:0:1:0:1:0:1]> without base
+PASS Parsing: <http://[1:0:1:0:1:0:1:0]> without base
+PASS Parsing: <http://example.org/test?"> without base
+PASS Parsing: <http://example.org/test?#> without base
+PASS Parsing: <http://example.org/test?<> without base
+PASS Parsing: <http://example.org/test?>> without base
+PASS Parsing: <http://example.org/test?⌣> without base
+PASS Parsing: <http://example.org/test?%23%23> without base
+PASS Parsing: <http://example.org/test?%GH> without base
+PASS Parsing: <http://example.org/test?a#%EF> without base
+PASS Parsing: <http://example.org/test?a#%GH> without base
+PASS Parsing: <a> without base
+PASS Parsing: <a/> without base
+PASS Parsing: <a//> without base
 FAIL Parsing: <test-a-colon.html> against <a:> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <test-a-colon-b.html> against <a:b> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+          new URL(expected.input, base);
         }" did not throw
 FAIL Parsing: <test-a-colon-slash.html> against <a:/> assert_equals: href expected "a:/test-a-colon-slash.html" but got "file:///A:/test-a-colon-slash.html"
 FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> assert_equals: href expected "a:///test-a-colon-slash-slash.html" but got "file:///A://test-a-colon-slash-slash.html"
 FAIL Parsing: <test-a-colon-slash-b.html> against <a:/b> assert_equals: href expected "a:/test-a-colon-slash-b.html" but got "file:///A:/test-a-colon-slash-b.html"
 FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> assert_equals: href expected "a://b/test-a-colon-slash-slash-b.html" but got "file:///A://test-a-colon-slash-slash-b.html"
-PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank>
-FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got ""
-PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank>
+PASS Parsing: <http://example.org/test?a#b\0c> without base
+FAIL Parsing: <non-spec://example.org/test?a#b\0c> without base assert_equals: host expected "example.org" but got ""
+PASS Parsing: <non-spec:/test?a#b\0c> without base
 PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file>
 PASS Parsing: <#link> against <https://example.org/##link>
-PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org>
-FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
-FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
-FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
-FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
-FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
-FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
-PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got ""
-PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
+FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/"
+FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/"
+FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got ""
+FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~"
+FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~"
+FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~"
+PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base assert_equals: host expected "host" but got ""
+PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
 FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless"
 FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless"
 PASS Parsing: <abc:rootless> against <abc:path>
 FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted"
-PASS Parsing: <#> against <null>
-PASS Parsing: <?> against <null>
+PASS Parsing: <#> without base
+PASS Parsing: <?> without base
 PASS Parsing: <http://1.2.3.4.5> against <http://other.com/>
 PASS Parsing: <http://1.2.3.4.5.> against <http://other.com/>
-PASS Parsing: <http://0..0x300/> against <about:blank>
-PASS Parsing: <http://0..0x300./> against <about:blank>
+PASS Parsing: <http://0..0x300/> without base
+PASS Parsing: <http://0..0x300./> without base
 PASS Parsing: <http://256.256.256.256.256> against <http://other.com/>
 PASS Parsing: <http://256.256.256.256.256.> against <http://other.com/>
-PASS Parsing: <http://1.2.3.08> against <about:blank>
-PASS Parsing: <http://1.2.3.08.> against <about:blank>
-PASS Parsing: <http://1.2.3.09> against <about:blank>
-PASS Parsing: <http://09.2.3.4> against <about:blank>
-PASS Parsing: <http://09.2.3.4.> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5> against <about:blank>
-PASS Parsing: <http://01.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4> against <about:blank>
-PASS Parsing: <http://0x100.2.3.4.> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5> against <about:blank>
-PASS Parsing: <http://0x1.2.3.4.5.> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.1.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.2.3.4> against <about:blank>
-PASS Parsing: <http://foo.2.3.4.> against <about:blank>
-PASS Parsing: <http://foo.09> against <about:blank>
-PASS Parsing: <http://foo.09.> against <about:blank>
-PASS Parsing: <http://foo.0x4> against <about:blank>
-PASS Parsing: <http://foo.0x4.> against <about:blank>
-PASS Parsing: <http://foo.09..> against <about:blank>
-PASS Parsing: <http://0999999999999999999/> against <about:blank>
-PASS Parsing: <http://foo.0x> against <about:blank>
-PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank>
-PASS Parsing: <http://💩.123/> against <about:blank>
-PASS Parsing: <https://\0y> against <about:blank>
-FAIL Parsing: <https://x/\0y> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Parsing: <https://x/?\0y> against <about:blank>
-PASS Parsing: <https://x/?#\0y> against <about:blank>
-PASS Parsing: <https://￿y> against <about:blank>
-FAIL Parsing: <https://x/￿y> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <https://x/?￿y> against <about:blank> assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
-FAIL Parsing: <https://x/?#￿y> against <about:blank> assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
-PASS Parsing: <non-special:\0y> against <about:blank>
-PASS Parsing: <non-special:x/\0y> against <about:blank>
-PASS Parsing: <non-special:x/?\0y> against <about:blank>
-PASS Parsing: <non-special:x/?#\0y> against <about:blank>
-FAIL Parsing: <non-special:￿y> against <about:blank> assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
-FAIL Parsing: <non-special:x/￿y> against <about:blank> assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?￿y> against <about:blank> assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
-FAIL Parsing: <non-special:x/?#￿y> against <about:blank> assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
-PASS Parsing: <> against <about:blank>
-PASS Parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Parsing: <https://­/> against <about:blank>
-PASS Parsing: <https://%C2%AD/> against <about:blank>
-FAIL Parsing: <https://xn--/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <http://1.2.3.08> without base
+PASS Parsing: <http://1.2.3.08.> without base
+PASS Parsing: <http://1.2.3.09> without base
+PASS Parsing: <http://09.2.3.4> without base
+PASS Parsing: <http://09.2.3.4.> without base
+PASS Parsing: <http://01.2.3.4.5> without base
+PASS Parsing: <http://01.2.3.4.5.> without base
+PASS Parsing: <http://0x100.2.3.4> without base
+PASS Parsing: <http://0x100.2.3.4.> without base
+PASS Parsing: <http://0x1.2.3.4.5> without base
+PASS Parsing: <http://0x1.2.3.4.5.> without base
+PASS Parsing: <http://foo.1.2.3.4> without base
+PASS Parsing: <http://foo.1.2.3.4.> without base
+PASS Parsing: <http://foo.2.3.4> without base
+PASS Parsing: <http://foo.2.3.4.> without base
+PASS Parsing: <http://foo.09> without base
+PASS Parsing: <http://foo.09.> without base
+PASS Parsing: <http://foo.0x4> without base
+PASS Parsing: <http://foo.0x4.> without base
+PASS Parsing: <http://foo.09..> without base
+PASS Parsing: <http://0999999999999999999/> without base
+PASS Parsing: <http://foo.0x> without base
+PASS Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> without base
+PASS Parsing: <http://💩.123/> without base
+PASS Parsing: <https://\0y> without base
+FAIL Parsing: <https://x/\0y> without base Failed to construct 'URL': Invalid URL
+PASS Parsing: <https://x/?\0y> without base
+PASS Parsing: <https://x/?#\0y> without base
+PASS Parsing: <https://￿y> without base
+FAIL Parsing: <https://x/￿y> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <https://x/?￿y> without base assert_equals: href expected "https://x/?%EF%BF%BFy" but got "https://x/?%EF%BF%BDy"
+FAIL Parsing: <https://x/?#￿y> without base assert_equals: href expected "https://x/?#%EF%BF%BFy" but got "https://x/?#%EF%BF%BDy"
+PASS Parsing: <non-special:\0y> without base
+PASS Parsing: <non-special:x/\0y> without base
+PASS Parsing: <non-special:x/?\0y> without base
+PASS Parsing: <non-special:x/?#\0y> without base
+FAIL Parsing: <non-special:￿y> without base assert_equals: href expected "non-special:%EF%BF%BFy" but got "non-special:%EF%BF%BDy"
+FAIL Parsing: <non-special:x/￿y> without base assert_equals: href expected "non-special:x/%EF%BF%BFy" but got "non-special:x/%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?￿y> without base assert_equals: href expected "non-special:x/?%EF%BF%BFy" but got "non-special:x/?%EF%BF%BDy"
+FAIL Parsing: <non-special:x/?#￿y> without base assert_equals: href expected "non-special:x/?#%EF%BF%BFy" but got "non-special:x/?#%EF%BF%BDy"
+PASS Parsing: <> without base
+PASS Parsing: <https://example.com/"quoted"> without base
+PASS Parsing: <https://a%C2%ADb/> without base
+PASS Parsing: <https://­/> without base
+PASS Parsing: <https://%C2%AD/> without base
+FAIL Parsing: <https://xn--/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <data:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <data://test/a/../b> against <about:blank> assert_equals: href expected "data://test/b" but got "data://test/a/../b"
-FAIL Parsing: <data://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <data:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <data://test/a/../b> without base assert_equals: href expected "data://test/b" but got "data://test/a/../b"
+FAIL Parsing: <data://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <data://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <data://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <intent:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <intent://test/a/../b> against <about:blank> assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
-FAIL Parsing: <intent://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <intent:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <intent://test/a/../b> without base assert_equals: href expected "intent://test/b" but got "intent://test/a/../b"
+FAIL Parsing: <intent://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <intent://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <intent://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <urn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <urn://test/a/../b> against <about:blank> assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
-FAIL Parsing: <urn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <urn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <urn://test/a/../b> without base assert_equals: href expected "urn://test/b" but got "urn://test/a/../b"
+FAIL Parsing: <urn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <urn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <urn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <turn:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <turn://test/a/../b> against <about:blank> assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
-FAIL Parsing: <turn://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <turn:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <turn://test/a/../b> without base assert_equals: href expected "turn://test/b" but got "turn://test/a/../b"
+FAIL Parsing: <turn://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <turn://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <turn://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank> assert_equals: host expected "example.com:8080" but got ""
-FAIL Parsing: <stun:///test> against <about:blank> assert_equals: pathname expected "/test" but got "///test"
-FAIL Parsing: <stun://test/a/../b> against <about:blank> assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
-FAIL Parsing: <stun://:443> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://example.com:8080/pathname?search#hash> without base assert_equals: host expected "example.com:8080" but got ""
+FAIL Parsing: <stun:///test> without base assert_equals: pathname expected "/test" but got "///test"
+FAIL Parsing: <stun://test/a/../b> without base assert_equals: href expected "stun://test/b" but got "stun://test/a/../b"
+FAIL Parsing: <stun://:443> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://test:test> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://test:test> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <stun://[:1]> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <stun://[:1]> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_include=file-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_include=file-expected.txt
index 592f8c7..4722982c 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_include=file-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_include=file-expected.txt
@@ -2,10 +2,10 @@
 Found 126 tests; 70 PASS, 56 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 FAIL Parsing: <file:/example.com/> against <http://example.org/foo/bar> assert_equals: href expected "file:///example.com/" but got "file://example.com/"
-PASS Parsing: <file://example:1/> against <about:blank>
-PASS Parsing: <file://example:test/> against <about:blank>
-PASS Parsing: <file://example%/> against <about:blank>
-PASS Parsing: <file://[example]/> against <about:blank>
+PASS Parsing: <file://example:1/> without base
+PASS Parsing: <file://example:test/> without base
+PASS Parsing: <file://example%/> without base
+PASS Parsing: <file://[example]/> without base
 FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///C:/foo/bar.html"
 FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///C:////foo/bar.html"
 PASS Parsing: <C|/foo/bar> against <file:///tmp/mock/path>
@@ -25,24 +25,24 @@
 FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test"
 PASS Parsing: <test> against <file:///tmp/mock/path>
 PASS Parsing: <file:test> against <file:///tmp/mock/path>
-FAIL Parsing: <file:/example.com/> against <about:blank> assert_equals: href expected "file:///example.com/" but got "file://example.com/"
+FAIL Parsing: <file:/example.com/> without base assert_equals: href expected "file:///example.com/" but got "file://example.com/"
 FAIL Parsing: <file:...> against <http://www.example.com/test> assert_equals: href expected "file:///..." but got "file://.../"
 FAIL Parsing: <file:..> against <http://www.example.com/test> assert_equals: href expected "file:///" but got "file://../"
 FAIL Parsing: <file:a> against <http://www.example.com/test> assert_equals: href expected "file:///a" but got "file://a/"
-PASS Parsing: <file:///C%3A/> against <about:blank>
-PASS Parsing: <file:///C%7C/> against <about:blank>
-PASS Parsing: <file://%43%3A> against <about:blank>
-FAIL Parsing: <file://%43%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file:///C%3A/> without base
+PASS Parsing: <file:///C%7C/> without base
+PASS Parsing: <file://%43%3A> without base
+FAIL Parsing: <file://%43%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43|> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43|> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://C%7C> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://C%7C> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-FAIL Parsing: <file://%43%7C/> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+FAIL Parsing: <file://%43%7C/> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
 PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html>
 PASS Parsing: <..> against <file:///C:/>
@@ -60,15 +60,15 @@
 PASS Parsing: <file:?x> against <file:///test?test#test>
 PASS Parsing: <#x> against <file:///test?test#test>
 PASS Parsing: <file:#x> against <file:///test?test#test>
-FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///"
-FAIL Parsing: <file:\\\\?fox> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file://%23guppy/"
-PASS Parsing: <file://spider///> against <about:blank>
-FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//"
-PASS Parsing: <file:///localhost//cat> against <about:blank>
-FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file://localhost//cat"
-FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///"
+FAIL Parsing: <file:\\//> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\> without base assert_equals: href expected "file:////" but got "file:///"
+FAIL Parsing: <file:\\\\?fox> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <file:\\\\#guppy> without base assert_equals: href expected "file:////#guppy" but got "file://%23guppy/"
+PASS Parsing: <file://spider///> without base
+FAIL Parsing: <file:\\localhost//> without base assert_equals: href expected "file:////" but got "file://localhost//"
+PASS Parsing: <file:///localhost//cat> without base
+FAIL Parsing: <file://\/localhost//cat> without base assert_equals: href expected "file:////localhost//cat" but got "file://localhost//cat"
+FAIL Parsing: <file://localhost//a//../..//> without base assert_equals: href expected "file://///" but got "file://localhost///"
 FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file://mouse/"
 PASS Parsing: <\//pig> against <file://lion/>
 FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig"
@@ -91,9 +91,9 @@
 FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///C:/foo/bar"
 FAIL Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///C:/foo/bar"
 FAIL Parsing: </c:/foo/bar> against <file://host/path> assert_equals: href expected "file://host/c:/foo/bar" but got "file:///C:/foo/bar"
-PASS Parsing: <file://example.net/C:/> against <about:blank>
-PASS Parsing: <file://1.2.3.4/C:/> against <about:blank>
-PASS Parsing: <file://[1::8]/C:/> against <about:blank>
+PASS Parsing: <file://example.net/C:/> without base
+PASS Parsing: <file://1.2.3.4/C:/> without base
+PASS Parsing: <file://[1::8]/C:/> without base
 FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file:///C:/"
 FAIL Parsing: </C:/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file:///C:/"
 FAIL Parsing: <file:C:/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file:///C:/"
@@ -102,40 +102,40 @@
 PASS Parsing: <file://C:/> against <file://host/>
 PASS Parsing: <///C:/> against <file://host/>
 PASS Parsing: <file:///C:/> against <file://host/>
-PASS Parsing: <file:/C|/> against <about:blank>
-PASS Parsing: <file://C|/> against <about:blank>
-PASS Parsing: <file:> against <about:blank>
-FAIL Parsing: <file:?q=v> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Parsing: <file:#frag> against <about:blank> assert_equals: href expected "file:///#frag" but got "file://%23frag/"
-PASS Parsing: <file:///Y:> against <about:blank>
-PASS Parsing: <file:///Y:/> against <about:blank>
-PASS Parsing: <file:///./Y> against <about:blank>
-PASS Parsing: <file:///./Y:> against <about:blank>
-FAIL Parsing: <file:///y:> against <about:blank> assert_equals: href expected "file:///y:" but got "file:///Y:"
-FAIL Parsing: <file:///y:/> against <about:blank> assert_equals: href expected "file:///y:/" but got "file:///Y:/"
-PASS Parsing: <file:///./y> against <about:blank>
-FAIL Parsing: <file:///./y:> against <about:blank> assert_equals: href expected "file:///y:" but got "file:///Y:"
-FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo"
-FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo"
-FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file://foo/"
+PASS Parsing: <file:/C|/> without base
+PASS Parsing: <file://C|/> without base
+PASS Parsing: <file:> without base
+FAIL Parsing: <file:?q=v> without base Failed to construct 'URL': Invalid URL
+FAIL Parsing: <file:#frag> without base assert_equals: href expected "file:///#frag" but got "file://%23frag/"
+PASS Parsing: <file:///Y:> without base
+PASS Parsing: <file:///Y:/> without base
+PASS Parsing: <file:///./Y> without base
+PASS Parsing: <file:///./Y:> without base
+FAIL Parsing: <file:///y:> without base assert_equals: href expected "file:///y:" but got "file:///Y:"
+FAIL Parsing: <file:///y:/> without base assert_equals: href expected "file:///y:/" but got "file:///Y:/"
+PASS Parsing: <file:///./y> without base
+FAIL Parsing: <file:///./y:> without base assert_equals: href expected "file:///y:" but got "file:///Y:"
+FAIL Parsing: <file://localhost//a//../..//foo> without base assert_equals: href expected "file://///foo" but got "file://localhost///foo"
+FAIL Parsing: <file://localhost////foo> without base assert_equals: href expected "file://////foo" but got "file://localhost////foo"
+FAIL Parsing: <file:////foo> without base assert_equals: href expected "file:////foo" but got "file://foo/"
 PASS Parsing: <file:///one/two> against <file:///>
 FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file://one/two"
 PASS Parsing: <//one/two> against <file:///>
 PASS Parsing: <///one/two> against <file:///>
 FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file://one/two"
 PASS Parsing: <file:///.//> against <file:////>
-FAIL Parsing: <file:.//p> against <about:blank> assert_equals: href expected "file:////p" but got "file://.//p"
-FAIL Parsing: <file:/.//p> against <about:blank> assert_equals: href expected "file:////p" but got "file://.//p"
+FAIL Parsing: <file:.//p> without base assert_equals: href expected "file:////p" but got "file://.//p"
+FAIL Parsing: <file:/.//p> without base assert_equals: href expected "file:////p" but got "file://.//p"
 PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html>
 PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html>
-PASS Parsing: <file://a­b/p> against <about:blank>
-PASS Parsing: <file://a%C2%ADb/p> against <about:blank>
-FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> against <about:blank> assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
-PASS Parsing: <file://­/p> against <about:blank>
-PASS Parsing: <file://%C2%AD/p> against <about:blank>
-FAIL Parsing: <file://xn--/p> against <about:blank> assert_throws_js: function "function() {
-          bURL(expected.input, expected.base)
+PASS Parsing: <file://a­b/p> without base
+PASS Parsing: <file://a%C2%ADb/p> without base
+FAIL Parsing: <file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin> without base assert_equals: href expected "file:///usr/bin" but got "file://localhost/usr/bin"
+PASS Parsing: <file://­/p> without base
+PASS Parsing: <file://%C2%AD/p> without base
+FAIL Parsing: <file://xn--/p> without base assert_throws_js: function "function() {
+          new URL(expected.input, base);
         }" did not throw
-PASS Parsing: <> against <about:blank>
+PASS Parsing: <> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any-expected.txt
index f5433e8..d35126d 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-PASS Origin parsing: <https://faß.ExAmPlE/> against <about:blank>
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+PASS Origin parsing: <https://faß.ExAmPlE/> without base
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-FAIL Origin parsing: <h://.> against <about:blank> assert_equals: origin expected "null" but got "file://"
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+FAIL Origin parsing: <h://.> without base assert_equals: origin expected "null" but got "file://"
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any.worker-expected.txt
index f5433e8..d35126d 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any.worker-expected.txt
@@ -4,10 +4,10 @@
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
 PASS Origin parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar>
-PASS Origin parsing: <https://test:@test> against <about:blank>
-PASS Origin parsing: <https://:@test> against <about:blank>
-PASS Origin parsing: <non-special://test:@test/x> against <about:blank>
-PASS Origin parsing: <non-special://:@test/x> against <about:blank>
+PASS Origin parsing: <https://test:@test> without base
+PASS Origin parsing: <https://:@test> without base
+PASS Origin parsing: <non-special://test:@test/x> without base
+PASS Origin parsing: <non-special://:@test/x> without base
 PASS Origin parsing: <http:foo.com> against <http://example.org/foo/bar>
 PASS Origin parsing: <	   :foo.com   
 > against <http://example.org/foo/bar>
@@ -96,105 +96,105 @@
 PASS Origin parsing: <data:text/html,test#test> against <http://example.org/foo/bar>
 PASS Origin parsing: <tel:1234567890> against <http://example.org/foo/bar>
 PASS Origin parsing: <ssh://example.com/foo/bar.git> against <http://example.org/>
-PASS Origin parsing: <http://example.com/././foo> against <about:blank>
-PASS Origin parsing: <http://example.com/./.foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/.> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/./> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/..bar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/../../../ton> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank>
-PASS Origin parsing: <http://example.com////../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//../..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo/bar//..> against <about:blank>
-PASS Origin parsing: <http://example.com/foo> against <about:blank>
-PASS Origin parsing: <http://example.com/%20foo> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%2©zbar> against <about:blank>
-PASS Origin parsing: <http://example.com/foo%41%7a> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	‘%91> against <about:blank>
-FAIL Origin parsing: <http://example.com/foo%00%51> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <http://example.com/(%28:%3A%29)> against <about:blank>
-PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank>
-PASS Origin parsing: <http://example.com/foo	bar> against <about:blank>
-PASS Origin parsing: <http://example.com\\foo\\bar> against <about:blank>
-PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank>
-PASS Origin parsing: <http://example.com/@asdf%40> against <about:blank>
-PASS Origin parsing: <http://example.com/你好你好> against <about:blank>
-PASS Origin parsing: <http://example.com/‥/foo> against <about:blank>
-PASS Origin parsing: <http://example.com//foo> against <about:blank>
-PASS Origin parsing: <http://example.com/‮/foo/‭/bar> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz#> against <about:blank>
-PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>
-PASS Origin parsing: <data:test# »> against <about:blank>
-PASS Origin parsing: <http://www.google.com> against <about:blank>
-PASS Origin parsing: <http://192.0x00A80001> against <about:blank>
-PASS Origin parsing: <http://www/foo%2Ehtml> against <about:blank>
-PASS Origin parsing: <http://www/foo/%2E/html> against <about:blank>
-PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank>
-PASS Origin parsing: <http:\\www.google.com\foo> against <about:blank>
-PASS Origin parsing: <http://foo:80/> against <about:blank>
-PASS Origin parsing: <http://foo:81/> against <about:blank>
-PASS Origin parsing: <httpa://foo:80/> against <about:blank>
-PASS Origin parsing: <https://foo:443/> against <about:blank>
-PASS Origin parsing: <https://foo:80/> against <about:blank>
-PASS Origin parsing: <ftp://foo:21/> against <about:blank>
-PASS Origin parsing: <ftp://foo:80/> against <about:blank>
-PASS Origin parsing: <gopher://foo:70/> against <about:blank>
-PASS Origin parsing: <gopher://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:80/> against <about:blank>
-PASS Origin parsing: <ws://foo:81/> against <about:blank>
-PASS Origin parsing: <ws://foo:443/> against <about:blank>
-PASS Origin parsing: <ws://foo:815/> against <about:blank>
-PASS Origin parsing: <wss://foo:80/> against <about:blank>
-PASS Origin parsing: <wss://foo:81/> against <about:blank>
-PASS Origin parsing: <wss://foo:443/> against <about:blank>
-PASS Origin parsing: <wss://foo:815/> against <about:blank>
-PASS Origin parsing: <http:/example.com/> against <about:blank>
-PASS Origin parsing: <ftp:/example.com/> against <about:blank>
-PASS Origin parsing: <https:/example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:/example.com/> against <about:blank>
-PASS Origin parsing: <ftps:/example.com/> against <about:blank>
-PASS Origin parsing: <gopher:/example.com/> against <about:blank>
-PASS Origin parsing: <ws:/example.com/> against <about:blank>
-PASS Origin parsing: <wss:/example.com/> against <about:blank>
-PASS Origin parsing: <data:/example.com/> against <about:blank>
-PASS Origin parsing: <javascript:/example.com/> against <about:blank>
-PASS Origin parsing: <mailto:/example.com/> against <about:blank>
-PASS Origin parsing: <http:example.com/> against <about:blank>
-PASS Origin parsing: <ftp:example.com/> against <about:blank>
-PASS Origin parsing: <https:example.com/> against <about:blank>
-PASS Origin parsing: <madeupscheme:example.com/> against <about:blank>
-PASS Origin parsing: <ftps:example.com/> against <about:blank>
-PASS Origin parsing: <gopher:example.com/> against <about:blank>
-PASS Origin parsing: <ws:example.com/> against <about:blank>
-PASS Origin parsing: <wss:example.com/> against <about:blank>
-PASS Origin parsing: <data:example.com/> against <about:blank>
-PASS Origin parsing: <javascript:example.com/> against <about:blank>
-PASS Origin parsing: <mailto:example.com/> against <about:blank>
-PASS Origin parsing: <http:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://@pple.com> against <about:blank>
-PASS Origin parsing: <http::b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http://:b@www.example.com> against <about:blank>
-PASS Origin parsing: <http:a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http:/a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://a:@www.example.com> against <about:blank>
-PASS Origin parsing: <http://www.@pple.com> against <about:blank>
-PASS Origin parsing: <http://:@www.example.com> against <about:blank>
+PASS Origin parsing: <http://example.com/././foo> without base
+PASS Origin parsing: <http://example.com/./.foo> without base
+PASS Origin parsing: <http://example.com/foo/.> without base
+PASS Origin parsing: <http://example.com/foo/./> without base
+PASS Origin parsing: <http://example.com/foo/bar/..> without base
+PASS Origin parsing: <http://example.com/foo/bar/../> without base
+PASS Origin parsing: <http://example.com/foo/..bar> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton> without base
+PASS Origin parsing: <http://example.com/foo/bar/../ton/../../a> without base
+PASS Origin parsing: <http://example.com/foo/../../..> without base
+PASS Origin parsing: <http://example.com/foo/../../../ton> without base
+PASS Origin parsing: <http://example.com/foo/%2e> without base
+PASS Origin parsing: <http://example.com/foo/%2e%2> without base
+PASS Origin parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> without base
+PASS Origin parsing: <http://example.com////../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//../..> without base
+PASS Origin parsing: <http://example.com/foo/bar//..> without base
+PASS Origin parsing: <http://example.com/foo> without base
+PASS Origin parsing: <http://example.com/%20foo> without base
+PASS Origin parsing: <http://example.com/foo%> without base
+PASS Origin parsing: <http://example.com/foo%2> without base
+PASS Origin parsing: <http://example.com/foo%2zbar> without base
+PASS Origin parsing: <http://example.com/foo%2©zbar> without base
+PASS Origin parsing: <http://example.com/foo%41%7a> without base
+PASS Origin parsing: <http://example.com/foo	‘%91> without base
+FAIL Origin parsing: <http://example.com/foo%00%51> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <http://example.com/(%28:%3A%29)> without base
+PASS Origin parsing: <http://example.com/%3A%3a%3C%3c> without base
+PASS Origin parsing: <http://example.com/foo	bar> without base
+PASS Origin parsing: <http://example.com\\foo\\bar> without base
+PASS Origin parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> without base
+PASS Origin parsing: <http://example.com/@asdf%40> without base
+PASS Origin parsing: <http://example.com/你好你好> without base
+PASS Origin parsing: <http://example.com/‥/foo> without base
+PASS Origin parsing: <http://example.com//foo> without base
+PASS Origin parsing: <http://example.com/‮/foo/‭/bar> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz#> without base
+PASS Origin parsing: <http://www.google.com/foo?bar=baz# »> without base
+PASS Origin parsing: <data:test# »> without base
+PASS Origin parsing: <http://www.google.com> without base
+PASS Origin parsing: <http://192.0x00A80001> without base
+PASS Origin parsing: <http://www/foo%2Ehtml> without base
+PASS Origin parsing: <http://www/foo/%2E/html> without base
+PASS Origin parsing: <http://%25DOMAIN:foobar@foodomain.com/> without base
+PASS Origin parsing: <http:\\www.google.com\foo> without base
+PASS Origin parsing: <http://foo:80/> without base
+PASS Origin parsing: <http://foo:81/> without base
+PASS Origin parsing: <httpa://foo:80/> without base
+PASS Origin parsing: <https://foo:443/> without base
+PASS Origin parsing: <https://foo:80/> without base
+PASS Origin parsing: <ftp://foo:21/> without base
+PASS Origin parsing: <ftp://foo:80/> without base
+PASS Origin parsing: <gopher://foo:70/> without base
+PASS Origin parsing: <gopher://foo:443/> without base
+PASS Origin parsing: <ws://foo:80/> without base
+PASS Origin parsing: <ws://foo:81/> without base
+PASS Origin parsing: <ws://foo:443/> without base
+PASS Origin parsing: <ws://foo:815/> without base
+PASS Origin parsing: <wss://foo:80/> without base
+PASS Origin parsing: <wss://foo:81/> without base
+PASS Origin parsing: <wss://foo:443/> without base
+PASS Origin parsing: <wss://foo:815/> without base
+PASS Origin parsing: <http:/example.com/> without base
+PASS Origin parsing: <ftp:/example.com/> without base
+PASS Origin parsing: <https:/example.com/> without base
+PASS Origin parsing: <madeupscheme:/example.com/> without base
+PASS Origin parsing: <ftps:/example.com/> without base
+PASS Origin parsing: <gopher:/example.com/> without base
+PASS Origin parsing: <ws:/example.com/> without base
+PASS Origin parsing: <wss:/example.com/> without base
+PASS Origin parsing: <data:/example.com/> without base
+PASS Origin parsing: <javascript:/example.com/> without base
+PASS Origin parsing: <mailto:/example.com/> without base
+PASS Origin parsing: <http:example.com/> without base
+PASS Origin parsing: <ftp:example.com/> without base
+PASS Origin parsing: <https:example.com/> without base
+PASS Origin parsing: <madeupscheme:example.com/> without base
+PASS Origin parsing: <ftps:example.com/> without base
+PASS Origin parsing: <gopher:example.com/> without base
+PASS Origin parsing: <ws:example.com/> without base
+PASS Origin parsing: <wss:example.com/> without base
+PASS Origin parsing: <data:example.com/> without base
+PASS Origin parsing: <javascript:example.com/> without base
+PASS Origin parsing: <mailto:example.com/> without base
+PASS Origin parsing: <http:@www.example.com> without base
+PASS Origin parsing: <http:/@www.example.com> without base
+PASS Origin parsing: <http://@www.example.com> without base
+PASS Origin parsing: <http:a:b@www.example.com> without base
+PASS Origin parsing: <http:/a:b@www.example.com> without base
+PASS Origin parsing: <http://a:b@www.example.com> without base
+PASS Origin parsing: <http://@pple.com> without base
+PASS Origin parsing: <http::b@www.example.com> without base
+PASS Origin parsing: <http:/:b@www.example.com> without base
+PASS Origin parsing: <http://:b@www.example.com> without base
+PASS Origin parsing: <http:a:@www.example.com> without base
+PASS Origin parsing: <http:/a:@www.example.com> without base
+PASS Origin parsing: <http://a:@www.example.com> without base
+PASS Origin parsing: <http://www.@pple.com> without base
+PASS Origin parsing: <http://:@www.example.com> without base
 PASS Origin parsing: </> against <http://www.example.com/test>
 PASS Origin parsing: </test.txt> against <http://www.example.com/test>
 PASS Origin parsing: <.> against <http://www.example.com/test>
@@ -209,19 +209,19 @@
 PASS Origin parsing: <//www.example2.com> against <http://www.example.com/test>
 PASS Origin parsing: <http://ExAmPlE.CoM> against <http://other.com/>
 PASS Origin parsing: <http://GOO​⁠goo.com> against <http://other.com/>
-PASS Origin parsing: <\0 http://example.com/ \r > against <about:blank>
+PASS Origin parsing: <\0 http://example.com/ \r > without base
 PASS Origin parsing: <http://www.foo。bar.com> against <http://other.com/>
-PASS Origin parsing: <https://x/�?�#�> against <about:blank>
+PASS Origin parsing: <https://x/�?�#�> without base
 PASS Origin parsing: <http://Go.com> against <http://other.com/>
 PASS Origin parsing: <http://你好你好> against <http://other.com/>
-PASS Origin parsing: <https://faß.ExAmPlE/> against <about:blank>
-PASS Origin parsing: <sc://faß.ExAmPlE/> against <about:blank>
+PASS Origin parsing: <https://faß.ExAmPlE/> without base
+PASS Origin parsing: <sc://faß.ExAmPlE/> without base
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/>
 PASS Origin parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/>
 PASS Origin parsing: <http://0Xc0.0250.01> against <http://other.com/>
-PASS Origin parsing: <http://./> against <about:blank>
-PASS Origin parsing: <http://../> against <about:blank>
-FAIL Origin parsing: <h://.> against <about:blank> assert_equals: origin expected "null" but got "file://"
+PASS Origin parsing: <http://./> without base
+PASS Origin parsing: <http://../> without base
+FAIL Origin parsing: <h://.> without base assert_equals: origin expected "null" but got "file://"
 PASS Origin parsing: <http://foo:💩@example.com/bar> against <http://other.com/>
 PASS Origin parsing: <#> against <test:test>
 PASS Origin parsing: <#x> against <mailto:x@x.com>
@@ -231,8 +231,8 @@
 PASS Origin parsing: <https://@test@test@example:800/> against <http://doesnotmatter/>
 PASS Origin parsing: <https://@@@example> against <http://doesnotmatter/>
 PASS Origin parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/>
-PASS Origin parsing: <http://host/?'> against <about:blank>
-PASS Origin parsing: <notspecial://host/?'> against <about:blank>
+PASS Origin parsing: <http://host/?'> without base
+PASS Origin parsing: <notspecial://host/?'> without base
 PASS Origin parsing: </some/path> against <http://user@example.org/smth>
 PASS Origin parsing: <> against <http://user:pass@example.org:21/smth>
 PASS Origin parsing: </some/path> against <http://user:pass@example.org:21/smth>
@@ -253,41 +253,41 @@
 PASS Origin parsing: <#i> against <sc:/pa/pa>
 PASS Origin parsing: <#i> against <sc://ho/pa>
 PASS Origin parsing: <#i> against <sc:///pa/pa>
-PASS Origin parsing: <about:/../> against <about:blank>
-PASS Origin parsing: <data:/../> against <about:blank>
-PASS Origin parsing: <javascript:/../> against <about:blank>
-PASS Origin parsing: <mailto:/../> against <about:blank>
-PASS Origin parsing: <sc://ñ.test/> against <about:blank>
+PASS Origin parsing: <about:/../> without base
+PASS Origin parsing: <data:/../> without base
+PASS Origin parsing: <javascript:/../> without base
+PASS Origin parsing: <mailto:/../> without base
+PASS Origin parsing: <sc://ñ.test/> without base
 FAIL Origin parsing: <x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc:\../> against <about:blank>
-PASS Origin parsing: <sc::a@example.net> against <about:blank>
-PASS Origin parsing: <wow:%NBD> against <about:blank>
-PASS Origin parsing: <wow:%1G> against <about:blank>
-PASS Origin parsing: <wow:￿> against <about:blank>
-FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> against <about:blank> Failed to construct 'URL': Invalid URL
-FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-PASS Origin parsing: <ftp://%e2%98%83> against <about:blank>
-PASS Origin parsing: <https://%e2%98%83> against <about:blank>
-PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
-PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank>
-PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank>
+PASS Origin parsing: <sc:\../> without base
+PASS Origin parsing: <sc::a@example.net> without base
+PASS Origin parsing: <wow:%NBD> without base
+PASS Origin parsing: <wow:%1G> without base
+PASS Origin parsing: <wow:￿> without base
+FAIL Origin parsing: <http://example.com/U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿?U+d800𐟾U+dfff﷐﷏﷯ﷰ￾￿> without base Failed to construct 'URL': Invalid URL
+FAIL Origin parsing: <http://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <sc://!"$%&'()*+,-.;=_`{}~/> without base
+PASS Origin parsing: <ftp://%e2%98%83> without base
+PASS Origin parsing: <https://%e2%98%83> without base
+PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> without base
+PASS Origin parsing: <http://facebook.com/?foo=%7B%22abc%22> without base
+PASS Origin parsing: <https://localhost:3000/jqueryui@1.2.3> without base
 PASS Origin parsing: <h	t
 t\rp://h	o
 s\rt:9	0
 0\r0/p	a
 t\rh?q	u
 e\rry#f	r
-a\rg> against <about:blank>
+a\rg> without base
 PASS Origin parsing: <?a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <??a=b&c=d> against <http://example.org/foo/bar>
 PASS Origin parsing: <http:> against <http://example.org/foo/bar>
 PASS Origin parsing: <sc:> against <https://example.org/foo/bar>
-PASS Origin parsing: <http://foo.bar/baz?qux#foobar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>
-PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>
+PASS Origin parsing: <http://foo.bar/baz?qux#foobar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo"bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo<bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo>bar> without base
+PASS Origin parsing: <http://foo.bar/baz?qux#foo`bar> without base
 PASS Origin parsing: <http://1.2.3.4/> against <http://other.com/>
 PASS Origin parsing: <http://1.2.3.4./> against <http://other.com/>
 PASS Origin parsing: <http://192.168.257> against <http://other.com/>
@@ -301,66 +301,66 @@
 PASS Origin parsing: <http://10000000000.com> against <http://other.com/>
 PASS Origin parsing: <http://4294967295> against <http://other.com/>
 PASS Origin parsing: <http://0xffffffff> against <http://other.com/>
-PASS Origin parsing: <https://0x.0x.0> against <about:blank>
-PASS Origin parsing: <asdf://%43%7C/> against <about:blank>
+PASS Origin parsing: <https://0x.0x.0> without base
+PASS Origin parsing: <asdf://%43%7C/> without base
 PASS Origin parsing: <http://[1:0::]> against <http://example.net/>
-PASS Origin parsing: <sc://ñ> against <about:blank>
-PASS Origin parsing: <sc://ñ?x> against <about:blank>
-PASS Origin parsing: <sc://ñ#x> against <about:blank>
+PASS Origin parsing: <sc://ñ> without base
+PASS Origin parsing: <sc://ñ?x> without base
+PASS Origin parsing: <sc://ñ#x> without base
 FAIL Origin parsing: <#x> against <sc://ñ> Failed to construct 'URL': Invalid URL
 FAIL Origin parsing: <?x> against <sc://ñ> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank>
-PASS Origin parsing: <telnet://user:pass@foobar.com:23/> against <about:blank>
-PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank>
-PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank>
-PASS Origin parsing: <rsync://foo@host:911/sup> against <about:blank>
-PASS Origin parsing: <git://github.com/foo/bar.git> against <about:blank>
-PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank>
-PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank>
-PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank>
-PASS Origin parsing: <git+https://github.com/foo/bar> against <about:blank>
-PASS Origin parsing: <urn:ietf:rfc:2648> against <about:blank>
-PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank>
-PASS Origin parsing: <blob:https://example.com:443/> against <about:blank>
-PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank>
-PASS Origin parsing: <blob:> against <about:blank>
-PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
-PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
+PASS Origin parsing: <tftp://foobar.com/someconfig;mode=netascii> without base
+PASS Origin parsing: <telnet://user:pass@foobar.com:23/> without base
+PASS Origin parsing: <ut2004://10.10.10.10:7777/Index.ut2> without base
+PASS Origin parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> without base
+PASS Origin parsing: <rsync://foo@host:911/sup> without base
+PASS Origin parsing: <git://github.com/foo/bar.git> without base
+PASS Origin parsing: <irc://myserver.com:6999/channel?passwd> without base
+PASS Origin parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> without base
+PASS Origin parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> without base
+PASS Origin parsing: <git+https://github.com/foo/bar> without base
+PASS Origin parsing: <urn:ietf:rfc:2648> without base
+PASS Origin parsing: <tag:joe@example.org,2001:foo/bar> without base
+PASS Origin parsing: <blob:https://example.com:443/> without base
+PASS Origin parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> without base
+PASS Origin parsing: <blob:> without base
+PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
+PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
-PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank>
-PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank>
-FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> Failed to construct 'URL': Invalid URL
-PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank>
-PASS Origin parsing: <https://example.com/"quoted"> against <about:blank>
-PASS Origin parsing: <https://a%C2%ADb/> against <about:blank>
-PASS Origin parsing: <data://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <data:///test> against <about:blank>
-PASS Origin parsing: <data://test/a/../b> against <about:blank>
-PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <javascript:///test> against <about:blank>
-PASS Origin parsing: <javascript://test/a/../b> against <about:blank>
-PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <mailto:///test> against <about:blank>
-PASS Origin parsing: <mailto://test/a/../b> against <about:blank>
-PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <intent:///test> against <about:blank>
-PASS Origin parsing: <intent://test/a/../b> against <about:blank>
-PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <urn:///test> against <about:blank>
-PASS Origin parsing: <urn://test/a/../b> against <about:blank>
-PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <turn:///test> against <about:blank>
-PASS Origin parsing: <turn://test/a/../b> against <about:blank>
-PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> against <about:blank>
-PASS Origin parsing: <stun:///test> against <about:blank>
-PASS Origin parsing: <stun://test/a/../b> against <about:blank>
+PASS Origin parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> without base
+PASS Origin parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> without base
+PASS Origin parsing: <foo://!"$%&'()*+,-.;=_`{}~/> without base
+FAIL Origin parsing: <wss://!"$&'()*+,-.;=_`{}~/> without base Failed to construct 'URL': Invalid URL
+PASS Origin parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> without base
+PASS Origin parsing: <https://example.com/"quoted"> without base
+PASS Origin parsing: <https://a%C2%ADb/> without base
+PASS Origin parsing: <data://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <data:///test> without base
+PASS Origin parsing: <data://test/a/../b> without base
+PASS Origin parsing: <javascript://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <javascript:///test> without base
+PASS Origin parsing: <javascript://test/a/../b> without base
+PASS Origin parsing: <mailto://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <mailto:///test> without base
+PASS Origin parsing: <mailto://test/a/../b> without base
+PASS Origin parsing: <intent://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <intent:///test> without base
+PASS Origin parsing: <intent://test/a/../b> without base
+PASS Origin parsing: <urn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <urn:///test> without base
+PASS Origin parsing: <urn://test/a/../b> without base
+PASS Origin parsing: <turn://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <turn:///test> without base
+PASS Origin parsing: <turn://test/a/../b> without base
+PASS Origin parsing: <stun://example.com:8080/pathname?search#hash> without base
+PASS Origin parsing: <stun:///test> without base
+PASS Origin parsing: <stun://test/a/../b> without base
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt
index f872463..e778ffc 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 403 tests; 250 PASS, 153 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 403 tests; 252 PASS, 151 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: The input layout nchw is not supported."
 PASS idl_test validation
 PASS Partial interface MLContext: original interface defined
@@ -222,7 +222,7 @@
 FAIL MLGraphBuilder interface: operation lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstm" missing
 FAIL MLGraphBuilder interface: operation lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstmCell" missing
 FAIL MLGraphBuilder interface: operation matmul(MLOperand, MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "matmul" missing
-FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_own_property: interface prototype object missing non-static operation expected property "pad" missing
+FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_equals: property has wrong .length expected 2 but got 3
 PASS MLGraphBuilder interface: operation averagePool2d(MLOperand, optional MLPool2dOptions)
 FAIL MLGraphBuilder interface: operation l2Pool2d(MLOperand, optional MLPool2dOptions) assert_own_property: interface prototype object missing non-static operation expected property "l2Pool2d" missing
 PASS MLGraphBuilder interface: operation maxPool2d(MLOperand, optional MLPool2dOptions)
@@ -342,8 +342,8 @@
 FAIL MLGraphBuilder interface: calling lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) on builder with too few arguments must throw TypeError assert_inherits: property "lstmCell" not found in prototype chain
 FAIL MLGraphBuilder interface: builder must inherit property "matmul(MLOperand, MLOperand)" with the proper type assert_inherits: property "matmul" not found in prototype chain
 FAIL MLGraphBuilder interface: calling matmul(MLOperand, MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "matmul" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type assert_inherits: property "pad" not found in prototype chain
-FAIL MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError assert_inherits: property "pad" not found in prototype chain
+PASS MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type
+PASS MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "averagePool2d(MLOperand, optional MLPool2dOptions)" with the proper type
 PASS MLGraphBuilder interface: calling averagePool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError
 FAIL MLGraphBuilder interface: builder must inherit property "l2Pool2d(MLOperand, optional MLPool2dOptions)" with the proper type assert_inherits: property "l2Pool2d" not found in prototype chain
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt
index 809388af..7d2b0f5 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 409 tests; 255 PASS, 154 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 409 tests; 257 PASS, 152 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'buildSync' on 'MLGraphBuilder': The input layout nchw is not supported."
 PASS idl_test validation
 PASS Partial interface MLContext: original interface defined
@@ -227,7 +227,7 @@
 FAIL MLGraphBuilder interface: operation lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstm" missing
 FAIL MLGraphBuilder interface: operation lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstmCell" missing
 FAIL MLGraphBuilder interface: operation matmul(MLOperand, MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "matmul" missing
-FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_own_property: interface prototype object missing non-static operation expected property "pad" missing
+FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_equals: property has wrong .length expected 2 but got 3
 PASS MLGraphBuilder interface: operation averagePool2d(MLOperand, optional MLPool2dOptions)
 FAIL MLGraphBuilder interface: operation l2Pool2d(MLOperand, optional MLPool2dOptions) assert_own_property: interface prototype object missing non-static operation expected property "l2Pool2d" missing
 PASS MLGraphBuilder interface: operation maxPool2d(MLOperand, optional MLPool2dOptions)
@@ -348,8 +348,8 @@
 FAIL MLGraphBuilder interface: calling lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) on builder with too few arguments must throw TypeError assert_inherits: property "lstmCell" not found in prototype chain
 FAIL MLGraphBuilder interface: builder must inherit property "matmul(MLOperand, MLOperand)" with the proper type assert_inherits: property "matmul" not found in prototype chain
 FAIL MLGraphBuilder interface: calling matmul(MLOperand, MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "matmul" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type assert_inherits: property "pad" not found in prototype chain
-FAIL MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError assert_inherits: property "pad" not found in prototype chain
+PASS MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type
+PASS MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "averagePool2d(MLOperand, optional MLPool2dOptions)" with the proper type
 PASS MLGraphBuilder interface: calling averagePool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError
 FAIL MLGraphBuilder interface: builder must inherit property "l2Pool2d(MLOperand, optional MLPool2dOptions)" with the proper type assert_inherits: property "l2Pool2d" not found in prototype chain
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 8ef051b..77e02e1 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
@@ -1181,6 +1181,7 @@
 [Worker]     method maxPool2d
 [Worker]     method min
 [Worker]     method mul
+[Worker]     method pad
 [Worker]     method relu
 [Worker]     method resample2d
 [Worker]     method reshape
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 87a28bd..32312b2 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
@@ -5524,6 +5524,7 @@
     method maxPool2d
     method min
     method mul
+    method pad
     method relu
     method resample2d
     method reshape
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-nesting/ident/implicit-nesting-ident.html.ini b/third_party/blink/web_tests/wpt_internal/css/css-nesting/ident/implicit-nesting-ident.html.ini
new file mode 100644
index 0000000..2880d272
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-nesting/ident/implicit-nesting-ident.html.ini
@@ -0,0 +1,3 @@
+[implicit-nesting-ident.html]
+  [Nested rule starting with tag]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.draw.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.draw.https.html
new file mode 100644
index 0000000..d11e4c62
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.draw.https.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+function optimizedMethodCall(renderEncoder, vertexCount, instanceCount, firstVertex, firstInstance) {
+  renderEncoder.draw(vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+function test(t, hotLoop, renderEncoder, vertexCount, instanceCount, firstVertex, firstInstance) {
+  try {
+    hotLoop(1, renderEncoder, vertexCount, instanceCount, firstVertex, firstInstance);
+  } catch(e) {
+    assert_true(e instanceof TypeError);
+    return;
+  }
+  assert_unreached("A TypeError should be thrown.");
+}
+
+async function testRenderEncoder(t, device, renderEncoder) {
+  function hotLoop(count, renderEncoder, vertexCount, instanceCount, firstVertex, firstInstance) {
+    for (let i = 0; i < count; ++i) {
+      optimizedMethodCall(renderEncoder, vertexCount, instanceCount, firstVertex, firstInstance);
+    }
+  }
+  hotLoop(100, renderEncoder, 1, 2, 3, 4);
+
+  // Wait a bit for V8 to optimize. Then call again with an out-of-bounds value.
+  // An exception should be thrown.
+  await new Promise(resolve => t.step_timeout(resolve, 50));
+
+  test(t, hotLoop, renderEncoder, 0xFFFFFFFF + 1, 2, 3, 4);
+  test(t, hotLoop, renderEncoder, 1, 0xFFFFFFFF + 1, 3, 4);
+  test(t, hotLoop, renderEncoder, 1, 2, 0xFFFFFFFF + 1, 4);
+  test(t, hotLoop, renderEncoder, 1, 2, 3, 0xFFFFFFFF + 1);
+}
+
+async function testRenderPassEncoder(t, device) {
+  const encoder = device.createCommandEncoder();
+
+  const colorTexture = device.createTexture({
+    format: 'rgba8unorm',
+    size: [4, 4, 1],
+    usage: GPUTextureUsage.RENDER_ATTACHMENT,
+  });
+  const renderPassEncoder = encoder.beginRenderPass({
+    colorAttachments: [{
+      view: colorTexture.createView(),
+      loadOp: 'load',
+      storeOp: 'store',
+    }],
+  });
+  await testRenderEncoder(t, device, renderPassEncoder);
+}
+
+async function testRenderBundleEncoder(t, device) {
+  const renderBundleEncoder = device.createRenderBundleEncoder({
+    colorFormats: ['rgba8unorm'],
+  });
+  await testRenderEncoder(t, device, renderBundleEncoder);
+}
+
+promise_test(async t => {
+  const adapter = await navigator.gpu.requestAdapter();
+  assert_true(adapter instanceof GPUAdapter, 'Failed to request WebGPU adapter');
+  const device = await adapter.requestDevice();
+  assert_true(device instanceof GPUDevice, 'Failed to request WebGPU device');
+
+  await testRenderPassEncoder(t, device);
+  await testRenderBundleEncoder(t, device);
+});
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.drawIndexed.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.drawIndexed.https.html
new file mode 100644
index 0000000..c341fd0
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.drawIndexed.https.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+function optimizedMethodCall(renderEncoder, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) {
+  renderEncoder.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
+}
+
+function test(t, hotLoop, renderEncoder, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) {
+  try {
+    hotLoop(1, renderEncoder, indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
+  } catch(e) {
+    assert_true(e instanceof TypeError);
+    return;
+  }
+  assert_unreached("A TypeError should be thrown.");
+}
+
+async function testRenderEncoder(t, device, renderEncoder) {
+  function hotLoop(count, renderEncoder, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) {
+    for (let i = 0; i < count; ++i) {
+      optimizedMethodCall(renderEncoder, indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
+    }
+  }
+  hotLoop(100, renderEncoder, 1, 2, 3, 4, 5);
+
+  // Wait a bit for V8 to optimize. Then call again with an out-of-bounds value.
+  // An exception should be thrown.
+  await new Promise(resolve => t.step_timeout(resolve, 50));
+
+  test(t, hotLoop, renderEncoder, 0xFFFFFFFF + 1, 2, 3, 4, 5);
+  test(t, hotLoop, renderEncoder, 1, 0xFFFFFFFF + 1, 3, 4, 5);
+  test(t, hotLoop, renderEncoder, 1, 2, 0xFFFFFFFF + 1, 4, 5);
+  test(t, hotLoop, renderEncoder, 1, 2, 3, 4, 0xFFFFFFFF + 1);
+
+  // baseVertex is a GPUSignedOffset32
+  test(t, hotLoop, renderEncoder, 1, 2, 3, 0x7FFFFFFF + 1, 5);
+  test(t, hotLoop, renderEncoder, 1, 2, 3, -0x80000000 - 1, 5);
+}
+
+async function testRenderPassEncoder(t, device) {
+  const encoder = device.createCommandEncoder();
+
+  const colorTexture = device.createTexture({
+    format: 'rgba8unorm',
+    size: [4, 4, 1],
+    usage: GPUTextureUsage.RENDER_ATTACHMENT,
+  });
+  const renderPassEncoder = encoder.beginRenderPass({
+    colorAttachments: [{
+      view: colorTexture.createView(),
+      loadOp: 'load',
+      storeOp: 'store',
+    }],
+  });
+  await testRenderEncoder(t, device, renderPassEncoder);
+}
+
+async function testRenderBundleEncoder(t, device) {
+  const renderBundleEncoder = device.createRenderBundleEncoder({
+    colorFormats: ['rgba8unorm'],
+  });
+  await testRenderEncoder(t, device, renderBundleEncoder);
+}
+
+promise_test(async t => {
+  const adapter = await navigator.gpu.requestAdapter();
+  assert_true(adapter instanceof GPUAdapter, 'Failed to request WebGPU adapter');
+  const device = await adapter.requestDevice();
+  assert_true(device instanceof GPUDevice, 'Failed to request WebGPU device');
+
+  await testRenderPassEncoder(t, device);
+  await testRenderBundleEncoder(t, device);
+});
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.drawIndexedIndirect.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.drawIndexedIndirect.https.html
new file mode 100644
index 0000000..6d69a2ae
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.drawIndexedIndirect.https.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+function optimizedMethodCall(renderEncoder, indirectBuffer, indirectOffset) {
+  renderEncoder.drawIndexedIndirect(indirectBuffer, indirectOffset);
+}
+
+function test(t, hotLoop, renderEncoder, indirectBuffer, indirectOffset) {
+  try {
+    hotLoop(1, renderEncoder, indirectBuffer, indirectOffset);
+  } catch(e) {
+    assert_true(e instanceof TypeError);
+    return;
+  }
+  assert_unreached("A TypeError should be thrown.");
+}
+
+async function testRenderEncoder(t, device, renderEncoder, indirectBuffer) {
+  function hotLoop(count, renderEncoder, indirectBuffer, indirectOffset) {
+    for (let i = 0; i < count; ++i) {
+      optimizedMethodCall(renderEncoder, indirectBuffer, indirectOffset);
+    }
+  }
+  hotLoop(100, renderEncoder, indirectBuffer, 4);
+
+  // Wait a bit for V8 to optimize. Then call again with an out-of-bounds value.
+  // An exception should be thrown.
+  await new Promise(resolve => t.step_timeout(resolve, 50));
+
+  // kJSMaxInteger = 0x20000000000000 - 1;
+  test(t, hotLoop, renderEncoder, indirectBuffer, 0x20000000000000);
+}
+
+async function testRenderPassEncoder(t, device, indirectBuffer) {
+  const encoder = device.createCommandEncoder();
+
+  const colorTexture = device.createTexture({
+    format: 'rgba8unorm',
+    size: [4, 4, 1],
+    usage: GPUTextureUsage.RENDER_ATTACHMENT,
+  });
+  const renderPassEncoder = encoder.beginRenderPass({
+    colorAttachments: [{
+      view: colorTexture.createView(),
+      loadOp: 'load',
+      storeOp: 'store',
+    }],
+  });
+  await testRenderEncoder(t, device, renderPassEncoder, indirectBuffer);
+}
+
+async function testRenderBundleEncoder(t, device, indirectBuffer) {
+  const renderBundleEncoder = device.createRenderBundleEncoder({
+    colorFormats: ['rgba8unorm'],
+  });
+  await testRenderEncoder(t, device, renderBundleEncoder, indirectBuffer);
+}
+
+promise_test(async t => {
+  const adapter = await navigator.gpu.requestAdapter();
+  assert_true(adapter instanceof GPUAdapter, 'Failed to request WebGPU adapter');
+  const device = await adapter.requestDevice();
+  assert_true(device instanceof GPUDevice, 'Failed to request WebGPU device');
+
+  const indirectBuffer = device.createBuffer({
+    size: 32,
+    usage: GPUBufferUsage.INDIRECT,
+  });
+  await testRenderPassEncoder(t, device, indirectBuffer);
+  await testRenderBundleEncoder(t, device, indirectBuffer);
+});
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.drawIndirect.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.drawIndirect.https.html
new file mode 100644
index 0000000..1e85dfd
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.drawIndirect.https.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+function optimizedMethodCall(renderEncoder, indirectBuffer, indirectOffset) {
+  renderEncoder.drawIndirect(indirectBuffer, indirectOffset);
+}
+
+function test(t, hotLoop, renderEncoder, indirectBuffer, indirectOffset) {
+  try {
+    hotLoop(1, renderEncoder, indirectBuffer, indirectOffset);
+  } catch(e) {
+    assert_true(e instanceof TypeError);
+    return;
+  }
+  assert_unreached("A TypeError should be thrown.");
+}
+
+async function testRenderEncoder(t, device, renderEncoder, indirectBuffer) {
+  function hotLoop(count, renderEncoder, indirectBuffer, indirectOffset) {
+    for (let i = 0; i < count; ++i) {
+      optimizedMethodCall(renderEncoder, indirectBuffer, indirectOffset);
+    }
+  }
+  hotLoop(100, renderEncoder, indirectBuffer, 4);
+
+  // Wait a bit for V8 to optimize. Then call again with an out-of-bounds value.
+  // An exception should be thrown.
+  await new Promise(resolve => t.step_timeout(resolve, 50));
+
+  // kJSMaxInteger = 0x20000000000000 - 1;
+  test(t, hotLoop, renderEncoder, indirectBuffer, 0x20000000000000);
+}
+
+async function testRenderPassEncoder(t, device, indirectBuffer) {
+  const encoder = device.createCommandEncoder();
+
+  const colorTexture = device.createTexture({
+    format: 'rgba8unorm',
+    size: [4, 4, 1],
+    usage: GPUTextureUsage.RENDER_ATTACHMENT,
+  });
+  const renderPassEncoder = encoder.beginRenderPass({
+    colorAttachments: [{
+      view: colorTexture.createView(),
+      loadOp: 'load',
+      storeOp: 'store',
+    }],
+  });
+  await testRenderEncoder(t, device, renderPassEncoder, indirectBuffer);
+}
+
+async function testRenderBundleEncoder(t, device, indirectBuffer) {
+  const renderBundleEncoder = device.createRenderBundleEncoder({
+    colorFormats: ['rgba8unorm'],
+  });
+  await testRenderEncoder(t, device, renderBundleEncoder, indirectBuffer);
+}
+
+promise_test(async t => {
+  const adapter = await navigator.gpu.requestAdapter();
+  assert_true(adapter instanceof GPUAdapter, 'Failed to request WebGPU adapter');
+  const device = await adapter.requestDevice();
+  assert_true(device instanceof GPUDevice, 'Failed to request WebGPU device');
+
+  const indirectBuffer = device.createBuffer({
+    size: 32,
+    usage: GPUBufferUsage.INDIRECT,
+  });
+  await testRenderPassEncoder(t, device, indirectBuffer);
+  await testRenderBundleEncoder(t, device, indirectBuffer);
+});
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.setVertexBuffer.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.setVertexBuffer.https.html
new file mode 100644
index 0000000..98c1d1de
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPURenderEncoderBase.setVertexBuffer.https.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+function optimizedMethodCall(renderEncoder, slot, buffer, offset, size) {
+  renderEncoder.setVertexBuffer(slot, buffer, offset, size);
+}
+
+function test(t, hotLoop, renderEncoder, slot, buffer, offset, size) {
+  try {
+    hotLoop(1, renderEncoder, slot, buffer, offset, size);
+  } catch(e) {
+    assert_true(e instanceof TypeError);
+    return;
+  }
+  assert_unreached("A TypeError should be thrown.");
+}
+
+async function testRenderEncoder(t, device, renderEncoder, vertexBuffer) {
+  function hotLoop(count, renderEncoder, slot, buffer, offset, size) {
+    for (let i = 0; i < count; ++i) {
+      optimizedMethodCall(renderEncoder, slot, buffer, offset, size);
+    }
+  }
+  hotLoop(100, renderEncoder, 1, vertexBuffer, 4, 4);
+
+  // Wait a bit for V8 to optimize. Then call again with an out-of-bounds value.
+  // An exception should be thrown.
+  await new Promise(resolve => t.step_timeout(resolve, 50));
+
+  // kJSMaxInteger = 0x20000000000000 - 1;
+  test(t, hotLoop, renderEncoder, 0xFFFFFFFF + 1, vertexBuffer, 4, 4);
+  test(t, hotLoop, renderEncoder, 1, vertexBuffer, 0x20000000000000, 4);
+  test(t, hotLoop, renderEncoder, 1, vertexBuffer, 4, 0x20000000000000);
+}
+
+async function testRenderPassEncoder(t, device, vertexBuffer) {
+  const encoder = device.createCommandEncoder();
+
+  const colorTexture = device.createTexture({
+    format: 'rgba8unorm',
+    size: [4, 4, 1],
+    usage: GPUTextureUsage.RENDER_ATTACHMENT,
+  });
+  const renderPassEncoder = encoder.beginRenderPass({
+    colorAttachments: [{
+      view: colorTexture.createView(),
+      loadOp: 'load',
+      storeOp: 'store',
+    }],
+  });
+  await testRenderEncoder(t, device, renderPassEncoder, vertexBuffer);
+}
+
+async function testRenderBundleEncoder(t, device, vertexBuffer) {
+  const renderBundleEncoder = device.createRenderBundleEncoder({
+    colorFormats: ['rgba8unorm'],
+  });
+  await testRenderEncoder(t, device, renderBundleEncoder, vertexBuffer);
+}
+
+promise_test(async t => {
+  const adapter = await navigator.gpu.requestAdapter();
+  assert_true(adapter instanceof GPUAdapter, 'Failed to request WebGPU adapter');
+  const device = await adapter.requestDevice();
+  assert_true(device instanceof GPUDevice, 'Failed to request WebGPU device');
+
+  const vertexBuffer = device.createBuffer({
+    size: 8,
+    usage: GPUBufferUsage.VERTEX,
+  });
+  await testRenderPassEncoder(t, device, vertexBuffer);
+  await testRenderBundleEncoder(t, device, vertexBuffer);
+});
+</script>
+</body>
+</html>
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js
index 1298f02c..d2bc39f 100644
--- a/third_party/closure_compiler/externs/automation.js
+++ b/third_party/closure_compiler/externs/automation.js
@@ -457,6 +457,7 @@
   RELATED_ELEMENT: 'relatedElement',
   TITLE: 'title',
   VALUE: 'value',
+  POPOVER_ATTRIBUTE: 'popoverAttribute',
 };
 
 /**
diff --git a/third_party/libei/3pp/install.sh b/third_party/libei/3pp/install.sh
index ec6b57d..9c4eea2 100755
--- a/third_party/libei/3pp/install.sh
+++ b/third_party/libei/3pp/install.sh
@@ -68,7 +68,6 @@
 echo "Building libei"
 tar xf libei-main.tar.gz
 cd libei-main
-patch -p1 < ${SCRIPT_DIR}/patches/0001-config-Make-memfd_create-optional.patch
 
 echo "Compiler details (including search paths):"
 `gcc -print-prog-name=cpp` -v
diff --git a/third_party/libei/3pp/patches/0001-config-Make-memfd_create-optional.patch b/third_party/libei/3pp/patches/0001-config-Make-memfd_create-optional.patch
deleted file mode 100644
index de7c328b..0000000
--- a/third_party/libei/3pp/patches/0001-config-Make-memfd_create-optional.patch
+++ /dev/null
@@ -1,125 +0,0 @@
-From 6b59355bac02d02048dc0cff5ec28f196467aea3 Mon Sep 17 00:00:00 2001
-From: Salman Malik <salmanmalik@chromium.org>
-Date: Sat, 25 Mar 2023 23:22:01 +0000
-Subject: [PATCH] config: Make memfd_create optional
-
-`memfd_create` doesn't seem to be supported on
-all platforms (e.g. ubuntu 18 has trouble with it).
-Even though, I was able to substitute `memfd_create`
-with a direct system call, I was not able to get
-the `MFD_CLOXEC` flag (from fcntl.h) working cleanly
-(there were redefinitions/conflicts for other
-structures when trying to use <linux/*> headers).
-Making it optional for time being till we have
-figured out how to make it work broadly.
----
- meson.build             | 3 +++
- src/util-memfile.c      | 7 ++++++-
- src/util-memfile.h      | 2 ++
- test/test-ei-device.c   | 2 ++
- tools/eis-demo-server.c | 2 ++
- 5 files changed, 15 insertions(+), 1 deletion(-)
-
-diff --git a/meson.build b/meson.build
-index 61d78f8..63bafc8 100644
---- a/meson.build
-+++ b/meson.build
-@@ -51,6 +51,9 @@ config_h = configuration_data()
- config_h.set('_GNU_SOURCE', '1')
- config_h.set_quoted('EI_VERSION', meson.project_version())
- config_h.set_quoted('EIS_VERSION', meson.project_version())
-+if cc.has_function('memfd_create', prefix: '#define _GNU_SOURCE\n#include <sys/mman.h>')
-+  config_h.set('HAVE_MEMFD_CREATE', true)
-+endif
- 
- dep_libxkbcommon = dependency('xkbcommon', required: false)
- config_h.set10('HAVE_LIBXKBCOMMON', dep_libxkbcommon.found())
-diff --git a/src/util-memfile.c b/src/util-memfile.c
-index c4b8270..f74f7ec 100644
---- a/src/util-memfile.c
-+++ b/src/util-memfile.c
-@@ -26,9 +26,12 @@
- 
- #include <stddef.h>
- #include <unistd.h>
--#include <sys/mman.h>
- #include <fcntl.h>
- 
-+#ifdef HAVE_MEMFD_CREATE
-+#include <sys/mman.h>
-+#endif
-+
- #include "util-memfile.h"
- #include "util-mem.h"
- #include "util-io.h"
-@@ -55,6 +58,7 @@ OBJECT_IMPLEMENT_REF(memfile);
- OBJECT_IMPLEMENT_GETTER(memfile, fd, int);
- OBJECT_IMPLEMENT_GETTER(memfile, size, size_t);
- 
-+#ifdef HAVE_MEMFD_CREATE
- struct memfile *
- memfile_new(const char *data, size_t sz) {
- 	_unref_(memfile) *memfile = memfile_create(NULL);
-@@ -81,3 +85,4 @@ memfile_new(const char *data, size_t sz) {
- 
- 	return steal(&memfile);
- }
-+#endif
-diff --git a/src/util-memfile.h b/src/util-memfile.h
-index 66bdc28..51673f9 100644
---- a/src/util-memfile.h
-+++ b/src/util-memfile.h
-@@ -28,8 +28,10 @@
- 
- struct memfile;
- 
-+#ifdef HAVE_MEMFD_CREATE
- struct memfile *
- memfile_new(const char *data, size_t sz);
-+#endif
- 
- struct memfile *
- memfile_ref(struct memfile *memfile);
-diff --git a/test/test-ei-device.c b/test/test-ei-device.c
-index ae7e698..529cc68 100644
---- a/test/test-ei-device.c
-+++ b/test/test-ei-device.c
-@@ -1015,6 +1015,7 @@ MUNIT_TEST(test_ei_device_multitouch)
- 	return MUNIT_OK;
- }
- 
-+#ifdef HAVE_MEMFD_CREATE
- MUNIT_TEST(test_ei_keymap_invalid)
- {
- 	_unref_(peck) *peck = peck_new();
-@@ -1121,6 +1122,7 @@ MUNIT_TEST(test_ei_keymap_set)
- 
- 	return MUNIT_OK;
- }
-+#endif
- 
- MUNIT_TEST(test_ei_keyboard_modifiers)
- {
-diff --git a/tools/eis-demo-server.c b/tools/eis-demo-server.c
-index 14195d6..b2a3acc 100644
---- a/tools/eis-demo-server.c
-+++ b/tools/eis-demo-server.c
-@@ -207,6 +207,7 @@ setup_keymap(struct eis_demo_server *server, struct eis_device *device)
- 	const char *str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
- 	size_t len = strlen(str) - 1;
- 
-+#ifdef HAVE_MEMFD_CREATE
- 	struct memfile *f = memfile_new(str, len);
- 	if (!f)
- 		return;
-@@ -216,6 +217,7 @@ setup_keymap(struct eis_demo_server *server, struct eis_device *device)
- 						memfile_get_size(f));
- 	eis_keymap_add(k);
- 	memfile_unref(f);
-+#endif
- 
- 	_unref_(xkb_state) *state = xkb_state_new(keymap);
- 	if (!state)
--- 
-2.40.0.348.gf938b09366-goog
-
diff --git a/third_party/r8/BUILD.gn b/third_party/r8/BUILD.gn
index be70d1b..3761b65 100644
--- a/third_party/r8/BUILD.gn
+++ b/third_party/r8/BUILD.gn
@@ -11,9 +11,10 @@
 
   # Avoid using java_prebuilt() to ensure all uses go through the checked-in
   # version.
-  input_jars_paths = [ "//third_party/r8/lib/r8.jar" ]
+  input_jars_paths = [ "d8/lib/r8.jar" ]
 }
 
+# Use the non-d8 one since this is currently used only by unused_resources.
 java_prebuilt("r8_java") {
-  jar_path = "//third_party/r8/lib/r8.jar"
+  jar_path = "lib/r8.jar"
 }
diff --git a/third_party/ruy/BUILD.gn b/third_party/ruy/BUILD.gn
index 59bd67e..501c52b 100644
--- a/third_party/ruy/BUILD.gn
+++ b/third_party/ruy/BUILD.gn
@@ -50,7 +50,8 @@
 
 # Analogous to cmake's |ruy_8_mavx2_mfma_arch_AVX2|.
 config("ruy_avx2_flags") {
-  if (current_cpu == "x86_64" || current_cpu == "amd64") {
+  if (current_cpu == "x86_64" || current_cpu == "x64" ||
+      current_cpu == "amd64") {
     if (is_win) {
       cflags = [ "/arch:AVX2" ]
     } else {
@@ -64,7 +65,8 @@
 
 # Analogous to cmake's |ruy_9_mavx_arch_AVX|.
 config("ruy_avx_flags") {
-  if (current_cpu == "x86_64" || current_cpu == "amd64") {
+  if (current_cpu == "x86_64" || current_cpu == "x64" ||
+      current_cpu == "amd64") {
     if (is_win) {
       cflags = [ "/arch:AVX" ]
     } else {
diff --git a/tools/cast3p/runtime.version b/tools/cast3p/runtime.version
index 230e423..dd603331 100644
--- a/tools/cast3p/runtime.version
+++ b/tools/cast3p/runtime.version
@@ -1 +1 @@
-352020
+352175
diff --git a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
index e118f2c..ac127aea 100644
--- a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
+++ b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
@@ -1205,7 +1205,7 @@
                                exclude_fields_param.ArgStr.str());
 
   std::unique_ptr<FilterFile> paths_to_exclude;
-  if (override_exclude_paths_param.ValueStr.empty()) {
+  if (override_exclude_paths_param == "") {
     std::vector<std::string> paths_to_exclude_lines;
     for (auto* const line : kRawPtrManualPathsToIgnore) {
       paths_to_exclude_lines.push_back(line);
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py
index 21a3090d..28973be 100644
--- a/tools/json_schema_compiler/cc_generator.py
+++ b/tools/json_schema_compiler/cc_generator.py
@@ -159,6 +159,7 @@
             classname_in_namespace, type_.properties.values()))
 
       if type_.origin.from_json:
+        c.Cblock(self._GenerateClone(classname_in_namespace, type_))
         if type_.property_type is not PropertyType.CHOICES:
           c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_))
         c.Cblock(self._GenerateTypePopulateFromValue(
@@ -189,13 +190,7 @@
 
       real_t = self._type_helper.FollowRef(t)
       if real_t.property_type == PropertyType.ENUM:
-        namespace_prefix = ('%s::' % real_t.namespace.unix_name
-                            if real_t.namespace != self._namespace
-                            else '')
-        items.append('{var_name}({namespace}{inti_value})'.format(
-                      var_name=prop.unix_name,
-                      namespace=namespace_prefix,
-                      inti_value=self._type_helper.GetEnumNoneValue(real_t)))
+        items.append('{var_name}()'.format(var_name=prop.unix_name))
       elif prop.optional:
         continue
       elif t.property_type == PropertyType.INTEGER:
@@ -226,6 +221,70 @@
     s = s + ' {}'
     return Code().Append(s)
 
+  def _GenerateCloneItem(self, type_, field_name, is_optional):
+    """Generates the cloning statement for an individual data member.
+    """
+
+    underlying_type = self._type_helper.FollowRef(type_)
+    c = Code()
+
+    if (type_.property_type == PropertyType.ARRAY and
+        self._type_helper.FollowRef(type_.item_type).property_type in (
+            PropertyType.ANY,
+            PropertyType.OBJECT)):
+      if is_optional:
+        (c.Sblock('if (%(name)s) {')
+            .Append('out.%(name)s.emplace();')
+            .Append('out.%(name)s->reserve(%(name)s->size());')
+            .Sblock('for (const auto& element : *%(name)s) {')
+              .Append('out.%(name)s->push_back(element.Clone());')
+            .Eblock('}')
+          .Eblock('}'))
+      else:
+        (c.Append('out.%(name)s.reserve(%(name)s.size());')
+          .Sblock('for (const auto& element : %(name)s) {')
+            .Append('out.%(name)s.push_back(element.Clone());')
+          .Eblock('}'))
+    elif (underlying_type.property_type == PropertyType.OBJECT or
+          underlying_type.property_type == PropertyType.ANY or
+          underlying_type.property_type == PropertyType.CHOICES or
+          (underlying_type.property_type == PropertyType.FUNCTION and not
+          type_.is_serializable_function)):
+      if is_optional:
+        (c.Sblock('if (%(name)s) {')
+          .Append('out.%(name)s = %(name)s->Clone();')
+          .Eblock('}'))
+      else:
+        c.Append('out.%(name)s = %(name)s.Clone();')
+    else:
+      c.Append('out.%(name)s = %(name)s;')
+
+    c.Substitute({'name': field_name})
+    return c
+
+  def _GenerateClone(self, cpp_namespace, type_):
+    """Generates the function for cloning a type.
+    """
+    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
+    c = Code()
+    c.Sblock('%(namespace)s %(namespace)s::Clone() const {')
+    c.Append('%(classname)s out;')
+
+    if type_.property_type is PropertyType.CHOICES:
+      for choice in type_.choices:
+        c.Concat(self._GenerateCloneItem(
+          choice, 'as_%s' % choice.unix_name, is_optional=True))
+    else:
+      for prop in type_.properties.values():
+        c.Concat(self._GenerateCloneItem(
+          prop.type_, prop.type_.unix_name, is_optional=prop.optional))
+
+    (c.Append('return out;')
+      .Eblock('}')
+      .Substitute({'namespace': cpp_namespace, 'classname': classname}))
+    return c
+
+
   def _GenerateTypePopulate(self, cpp_namespace, type_):
     """Generates the function for populating a type given a pointer to it.
 
@@ -337,13 +396,10 @@
             prop, '(*%s)' % value_var, dst, 'false')))
       underlying_type = self._type_helper.FollowRef(prop.type_)
       if underlying_type.property_type == PropertyType.ENUM:
-        namespace_prefix = ('%s::' % underlying_type.namespace.unix_name
-                            if underlying_type.namespace != self._namespace
-                            else '')
         (c.Append('} else {')
-          .Append('%%(dst)s.%%(name)s = %s%s;' %
-             (namespace_prefix,
-              self._type_helper.GetEnumNoneValue(underlying_type))))
+          .Append('%%(dst)s.%%(name)s = %s;' %
+            self._type_helper.GetEnumDefaultValue(underlying_type,
+                                                  self._namespace)))
       c.Eblock('}')
     else:
       (c.Sblock(
@@ -630,8 +686,8 @@
       if include_optional_param:
         params.append('true' if property.optional else 'false')
       params += [
-        '%s%s' % (cpp_type_namespace,
-                  self._type_helper.GetEnumNoneValue(enum_type)),
+        '%s' % self._type_helper.GetEnumDefaultValue(enum_type,
+                                                     self._namespace),
         '%s' % out_expression,
         'error',
         'error_path_reversed'
@@ -686,15 +742,12 @@
       if prop.optional:
         underlying_type = self._type_helper.FollowRef(prop.type_)
         if underlying_type.property_type == PropertyType.ENUM:
-          # Optional enum values are generated with a NONE enum value,
-          # potentially from another namespace.
-          maybe_namespace = ''
-          if underlying_type.namespace != self._namespace:
-            maybe_namespace = '%s::' % underlying_type.namespace.unix_name
-          c.Sblock('if (%s != %s%s) {' %
+          # Optional enum values are generated with default initialisation (e.g.
+          # kNone), potentially from another namespace.
+          c.Sblock('if (%s != %s) {' %
               (prop_var,
-               maybe_namespace,
-               self._type_helper.GetEnumNoneValue(underlying_type)))
+               self._type_helper.GetEnumDefaultValue(underlying_type,
+                                                     self._namespace)))
         else:
           c.Sblock('if (%s) {' % prop_var)
 
@@ -743,7 +796,8 @@
                                             PropertyType.ENUM):
         comparison_expr = '{enum_var} != {default_value}'.format(
           enum_var=choice_var,
-          default_value=self._type_helper.GetEnumNoneValue(choice))
+          default_value=self._type_helper.GetEnumDefaultValue(choice,
+                                                              self._namespace))
       else:
         comparison_expr = choice_var
 
@@ -1212,9 +1266,9 @@
                                        cpp_type_namespace,
                                        cpp_util.Classname(type_.name),
                                        enum_as_string))
-      .Sblock('if (%s == %s%s) {' % (dst_var,
-                                     cpp_type_namespace,
-                                     self._type_helper.GetEnumNoneValue(type_)))
+      .Sblock('if (%s == %s) {' % (dst_var,
+                        self._type_helper.GetEnumDefaultValue(type_,
+                          self._namespace)))
       .Concat(self._AppendError16(
         'u\"\'%%(key)s\': expected \\"' +
         '\\" or \\"'.join(
@@ -1350,14 +1404,11 @@
     underlying_type = self._type_helper.FollowRef(prop.type_)
     if (underlying_type.property_type == PropertyType.ENUM and
         prop.optional):
-      namespace_prefix = ('%s::' % underlying_type.namespace.unix_name
-                          if underlying_type.namespace != self._namespace
-                          else '')
-      c.Append('%s.%s = %s%s;' % (
+      c.Append('%s.%s = %s;' % (
         dst,
         prop.unix_name,
-        namespace_prefix,
-        self._type_helper.GetEnumNoneValue(underlying_type)))
+        self._type_helper.GetEnumDefaultValue(underlying_type,
+                                              self._namespace)))
     return c
 
   def _AppendError16(self, error16):
diff --git a/tools/json_schema_compiler/cpp_type_generator.py b/tools/json_schema_compiler/cpp_type_generator.py
index 293985d..bede9d1 100644
--- a/tools/json_schema_compiler/cpp_type_generator.py
+++ b/tools/json_schema_compiler/cpp_type_generator.py
@@ -56,6 +56,16 @@
 
     return '%s_NONE' % self.FollowRef(type_).unix_name.upper()
 
+  def GetEnumDefaultValue(self, type_, current_namespace):
+    """Gets the representation for an enum default initialised, which is the
+    typename with a default initialiser. e.g. MyEnum().
+    """
+    namespace = ('%s::' % type_.namespace.unix_name
+      if current_namespace and current_namespace != type_.namespace else '')
+
+    return '{namespace}{typename}()'.format(
+      namespace=namespace,typename=cpp_util.Classname(type_.name))
+
   def FormatStringForEnumValue(self, name):
     """Formats a string enum entry to the common constant format favoured by the
     style guide.
@@ -91,8 +101,8 @@
     """Gets the enum value in the given model.Property indicating the last value
     for the type.
     """
-    if self.IsEnumModernised(type_):
-      return 'kLast'
+    # TODO(crbug.com/1421546): This function should be deleted once all enums
+    # are migrated to scoped ones.
     return '%s_LAST' % self.FollowRef(type_).unix_name.upper()
 
   def GetEnumValue(self, type_, enum_value, full_name=True):
diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py
index 1c3ddea..981d5d2 100644
--- a/tools/json_schema_compiler/h_generator.py
+++ b/tools/json_schema_compiler/h_generator.py
@@ -153,16 +153,26 @@
     c.Sblock('enum {enum_type} {name} {{'.format(
       enum_type=('class' if self._modernised_enums else ''),
       name=enum_name))
-    c.Append(self._type_helper.GetEnumNoneValue(type_, full_name=False) + ',')
+
+    # Explicitly initialize kNone to 0, since we rely on default initialization
+    # for enum members. Otherwise, default initialization will always set a
+    # value to 0, even if it's not a valid enum entry.
+    c.Append(
+      self._type_helper.GetEnumNoneValue(type_, full_name=False) + ' = 0,')
 
     for value in type_.enum_values:
       current_enum_string = (
         self._type_helper.GetEnumValue(type_, value, full_name=False))
       c.Append(current_enum_string + ',')
 
-    c.Append('{last_key} = {last_key_value},'.format(
-        last_key=self._type_helper.GetEnumLastValue(type_),
-        last_key_value=current_enum_string))
+    # Adding kMaxValue, which is friendly to enumaration histogram macros.
+    if self._modernised_enums:
+      c.Append('kMaxValue = {last_key_value},'.format(
+                last_key_value=current_enum_string))
+    else:
+      c.Append('{last_key} = {last_key_value},'.format(
+          last_key=self._type_helper.GetEnumLastValue(type_),
+          last_key_value=current_enum_string))
 
     c.Eblock('};')
     return c
@@ -269,6 +279,10 @@
             .Append('static bool Populate(%s);' % self._GenerateParams(
                 ('const base::Value::Dict& value', '%s& out' % classname)))
           )
+        (c.Append()
+          .Comment('Creates a deep copy of %s.' % classname)
+          .Append('%s Clone() const;' % classname)
+        )
         if is_toplevel:
           (c.Append()
             .Comment('Creates a %s object from a base::Value, or NULL on '
diff --git a/tools/json_schema_compiler/model.py b/tools/json_schema_compiler/model.py
index c8658c7..10c01e2 100644
--- a/tools/json_schema_compiler/model.py
+++ b/tools/json_schema_compiler/model.py
@@ -40,13 +40,10 @@
   def AddNamespace(self,
                    json,
                    source_file,
-                   include_compiler_options=True,
+                   include_compiler_options=False,
                    environment=None):
     """Add a namespace's json to the model and returns the namespace.
     """
-    # TODO(crbug.com/1421546): Revert to include_compiler_options=False once all
-    # enums are migrated to enum modernised codegen.
-
     namespace = Namespace(json,
                           source_file,
                           include_compiler_options=include_compiler_options,
diff --git a/tools/json_schema_compiler/test/any_unittest.cc b/tools/json_schema_compiler/test/any_unittest.cc
index 6e6645f..d481795 100644
--- a/tools/json_schema_compiler/test/any_unittest.cc
+++ b/tools/json_schema_compiler/test/any_unittest.cc
@@ -9,7 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "tools/json_schema_compiler/test/any.h"
 
-TEST(JsonSchemaCompilerAnyTest, AnyTypePopulate) {
+TEST(JsonSchemaCompilerAnyTest, PopulateAndClone) {
   {
     test::api::any::AnyType any_type;
     base::Value::Dict any_type_dict;
@@ -17,6 +17,9 @@
     EXPECT_TRUE(test::api::any::AnyType::Populate(any_type_dict, any_type));
     base::Value::Dict any_type_to_value(any_type.ToValue());
     EXPECT_EQ(any_type_dict, any_type_to_value);
+
+    test::api::any::AnyType any_type_copy = any_type.Clone();
+    EXPECT_EQ(any_type_dict, any_type_copy.ToValue());
   }
   {
     test::api::any::AnyType any_type;
@@ -25,6 +28,9 @@
     EXPECT_TRUE(test::api::any::AnyType::Populate(any_type_dict, any_type));
     base::Value::Dict any_type_to_value(any_type.ToValue());
     EXPECT_EQ(any_type_dict, any_type_to_value);
+
+    test::api::any::AnyType any_type_copy = any_type.Clone();
+    EXPECT_EQ(any_type_dict, any_type_copy.ToValue());
   }
 }
 
diff --git a/tools/json_schema_compiler/test/arrays_unittest.cc b/tools/json_schema_compiler/test/arrays_unittest.cc
index 176a422e1..47b3334 100644
--- a/tools/json_schema_compiler/test/arrays_unittest.cc
+++ b/tools/json_schema_compiler/test/arrays_unittest.cc
@@ -55,6 +55,8 @@
     arrays::BasicArrayType basic_array_type;
     ASSERT_TRUE(arrays::BasicArrayType::Populate(value, basic_array_type));
     EXPECT_EQ(value, basic_array_type.ToValue());
+
+    EXPECT_EQ(basic_array_type.Clone().ToValue(), basic_array_type.ToValue());
   }
 }
 
@@ -83,6 +85,9 @@
   // Test ToValue.
   base::Value::Dict as_value(enum_array_reference.ToValue());
   EXPECT_EQ(value, as_value);
+
+  EXPECT_EQ(enum_array_reference.Clone().ToValue(),
+            enum_array_reference.ToValue());
 }
 
 TEST(JsonSchemaCompilerArrayTest, EnumArrayMixed) {
@@ -125,6 +130,8 @@
   // Test ToValue.
   base::Value::Dict as_value(enum_array_mixed.ToValue());
   EXPECT_EQ(value, as_value);
+
+  EXPECT_EQ(enum_array_mixed.Clone().ToValue(), enum_array_mixed.ToValue());
 }
 
 TEST(JsonSchemaCompilerArrayTest, OptionalEnumArrayType) {
@@ -145,6 +152,8 @@
     ASSERT_TRUE(
         arrays::OptionalEnumArrayType::Populate(value, enum_array_type));
     EXPECT_EQ(enums, *enum_array_type.types);
+
+    EXPECT_EQ(enum_array_type.Clone().ToValue(), enum_array_type.ToValue());
   }
   {
     base::Value::Dict value;
@@ -173,6 +182,8 @@
     EXPECT_EQ(1, ref_array_type.refs[0].val);
     EXPECT_EQ(2, ref_array_type.refs[1].val);
     EXPECT_EQ(3, ref_array_type.refs[2].val);
+
+    EXPECT_EQ(ref_array_type.Clone().ToValue(), ref_array_type.ToValue());
   }
   {
     base::Value::Dict value;
diff --git a/tools/json_schema_compiler/test/choices_unittest.cc b/tools/json_schema_compiler/test/choices_unittest.cc
index d475fb6..9f882fc 100644
--- a/tools/json_schema_compiler/test/choices_unittest.cc
+++ b/tools/json_schema_compiler/test/choices_unittest.cc
@@ -27,6 +27,12 @@
   {
     absl::optional<TakesIntegers::Params> params(
         TakesIntegers::Params::Create(List(base::Value(true)).GetList()));
+
+    static_assert(!std::is_copy_constructible_v<TakesIntegers::Params>);
+    static_assert(!std::is_copy_assignable_v<TakesIntegers::Params>);
+    static_assert(std::is_move_constructible_v<TakesIntegers::Params>);
+    static_assert(std::is_move_assignable_v<TakesIntegers::Params>);
+
     EXPECT_FALSE(params);
   }
   {
@@ -35,6 +41,7 @@
     ASSERT_TRUE(params);
     EXPECT_FALSE(params->nums.as_integers);
     EXPECT_EQ(6, *params->nums.as_integer);
+    EXPECT_EQ(6, *params->nums.Clone().as_integer);
   }
   {
     absl::optional<TakesIntegers::Params> params(TakesIntegers::Params::Create(
@@ -42,6 +49,7 @@
     ASSERT_TRUE(params);
     ASSERT_TRUE(params->nums.as_integers);
     EXPECT_EQ(Vector(2, 6, 8), *params->nums.as_integers);
+    EXPECT_EQ(Vector(2, 6, 8), *params->nums.Clone().as_integers);
   }
 }
 
@@ -53,6 +61,7 @@
     ASSERT_TRUE(params);
     EXPECT_FALSE(params->string_info.strings.as_strings);
     EXPECT_EQ("asdf", *params->string_info.strings.as_string);
+    EXPECT_EQ("asdf", *params->string_info.Clone().strings.as_string);
     EXPECT_FALSE(params->string_info.integers);
   }
   {
@@ -64,9 +73,11 @@
     ASSERT_TRUE(params);
     EXPECT_FALSE(params->string_info.strings.as_strings);
     EXPECT_EQ("asdf", *params->string_info.strings.as_string);
+    EXPECT_EQ("asdf", *params->string_info.Clone().strings.as_string);
     ASSERT_TRUE(params->string_info.integers);
     EXPECT_FALSE(params->string_info.integers->as_integers);
     EXPECT_EQ(6, *params->string_info.integers->as_integer);
+    EXPECT_EQ(6, *params->string_info.Clone().integers->as_integer);
   }
 }
 
@@ -121,6 +132,12 @@
   dict.Set("strings", std::move(strings_value));
 
   choices::ChoiceType out;
+
+  static_assert(!std::is_copy_constructible_v<choices::ChoiceType>);
+  static_assert(!std::is_copy_assignable_v<choices::ChoiceType>);
+  static_assert(std::is_move_constructible_v<choices::ChoiceType>);
+  static_assert(std::is_move_assignable_v<choices::ChoiceType>);
+
   ASSERT_TRUE(choices::ChoiceType::Populate(dict, out));
   ASSERT_TRUE(out.integers.as_integer);
   EXPECT_FALSE(out.integers.as_integers);
diff --git a/tools/json_schema_compiler/test/crossref_unittest.cc b/tools/json_schema_compiler/test/crossref_unittest.cc
index 4580886..9d3354e 100644
--- a/tools/json_schema_compiler/test/crossref_unittest.cc
+++ b/tools/json_schema_compiler/test/crossref_unittest.cc
@@ -48,6 +48,8 @@
   // Test ToValue of the compiled type --> value.
   base::Value::Dict crossref_value = crossref_type.ToValue();
   EXPECT_EQ(crossref_orig, crossref_value);
+
+  EXPECT_EQ(crossref_type.Clone().ToValue(), crossref_type.ToValue());
 }
 
 TEST(JsonSchemaCompilerCrossrefTest, TestTypeOptionalParamCreate) {
diff --git a/tools/json_schema_compiler/test/enums_unittest.cc b/tools/json_schema_compiler/test/enums_unittest.cc
index 67af1791..9bb73eb4 100644
--- a/tools/json_schema_compiler/test/enums_unittest.cc
+++ b/tools/json_schema_compiler/test/enums_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "base/types/cxx23_to_underlying.h"
 #include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "tools/json_schema_compiler/test/test_util.h"
@@ -21,6 +22,7 @@
     EXPECT_TRUE(enums::EnumType::Populate(value.GetDict(), enum_type));
     EXPECT_EQ(enums::Enumeration::kOne, enum_type.type);
     EXPECT_EQ(value, enum_type.ToValue());
+    EXPECT_EQ(enum_type.Clone().ToValue(), enum_type.ToValue());
   }
   {
     enums::EnumType enum_type;
@@ -30,6 +32,8 @@
 }
 
 TEST(JsonSchemaCompilerEnumsTest, EnumsAsTypes) {
+  static_assert(0 == base::to_underlying(enums::Enumeration::kNone));
+
   {
     base::Value::List args;
     args.Append("one");
@@ -55,10 +59,12 @@
     value.Set("enumeration", "one");
     ASSERT_TRUE(enums::HasEnumeration::Populate(value, enumeration));
     EXPECT_EQ(value, enumeration.ToValue());
+    EXPECT_EQ(enumeration.Clone().ToValue(), enumeration.ToValue());
 
     value.Set("optional_enumeration", "two");
     ASSERT_TRUE(enums::HasEnumeration::Populate(value, enumeration));
     EXPECT_EQ(value, enumeration.ToValue());
+    EXPECT_EQ(enumeration.Clone().ToValue(), enumeration.ToValue());
   }
   {
     enums::ReferenceEnum enumeration;
@@ -68,6 +74,7 @@
     value.Set("reference_enum", "one");
     ASSERT_TRUE(enums::ReferenceEnum::Populate(value, enumeration));
     EXPECT_EQ(value, enumeration.ToValue());
+    EXPECT_EQ(enumeration.Clone().ToValue(), enumeration.ToValue());
   }
 }
 
@@ -125,6 +132,7 @@
     EXPECT_TRUE(enums::OptionalEnumType::Populate(value.GetDict(), enum_type));
     EXPECT_EQ(enums::Enumeration::kTwo, enum_type.type);
     EXPECT_EQ(value, enum_type.ToValue());
+    EXPECT_EQ(enum_type.Clone().ToValue(), enum_type.ToValue());
   }
   {
     enums::OptionalEnumType enum_type;
@@ -132,6 +140,7 @@
     EXPECT_TRUE(enums::OptionalEnumType::Populate(value.GetDict(), enum_type));
     EXPECT_EQ(enums::Enumeration::kNone, enum_type.type);
     EXPECT_EQ(value, enum_type.ToValue());
+    EXPECT_EQ(enum_type.Clone().ToValue(), enum_type.ToValue());
   }
   {
     enums::OptionalEnumType enum_type;
diff --git a/tools/json_schema_compiler/test/functions_as_parameters_unittest.cc b/tools/json_schema_compiler/test/functions_as_parameters_unittest.cc
index 4002420..c0391759 100644
--- a/tools/json_schema_compiler/test/functions_as_parameters_unittest.cc
+++ b/tools/json_schema_compiler/test/functions_as_parameters_unittest.cc
@@ -51,6 +51,7 @@
     FunctionType out;
     ASSERT_TRUE(FunctionType::Populate(value, out));
     EXPECT_EQ(expected_value, out.ToValue());
+    EXPECT_EQ(out.Clone().ToValue(), out.ToValue());
   }
 }
 
@@ -60,6 +61,7 @@
     OptionalFunctionType out;
     ASSERT_TRUE(OptionalFunctionType::Populate(empty_dictionary, out));
     EXPECT_FALSE(out.event_callback.has_value());
+    EXPECT_EQ(out.Clone().ToValue(), out.ToValue());
   }
   {
     base::Value::Dict value;
@@ -68,6 +70,7 @@
     OptionalFunctionType out;
     ASSERT_TRUE(OptionalFunctionType::Populate(value, out));
     EXPECT_TRUE(out.event_callback.has_value());
+    EXPECT_EQ(out.Clone().ToValue(), out.ToValue());
   }
   {
     base::Value::Dict value;
@@ -76,6 +79,7 @@
     OptionalFunctionType out;
     ASSERT_TRUE(OptionalFunctionType::Populate(value, out));
     EXPECT_TRUE(out.event_callback.has_value());
+    EXPECT_EQ(out.Clone().ToValue(), out.ToValue());
   }
 }
 
@@ -106,6 +110,7 @@
   ASSERT_TRUE(
       SerializableFunctionType::Populate(std::move(serialized), deserialized));
   EXPECT_EQ(kFunction, serializable_type.function_property);
+  EXPECT_EQ(serializable_type.Clone().ToValue(), serializable_type.ToValue());
 }
 
 TEST(JsonSchemaCompilerFunctionsAsParametersTest,
@@ -121,6 +126,7 @@
         std::move(serialized), deserialized));
     ASSERT_TRUE(serializable_type.function_property);
     EXPECT_EQ(kFunction, *serializable_type.function_property);
+    EXPECT_EQ(serializable_type.Clone().ToValue(), serializable_type.ToValue());
   }
   {
     // Test without the property set.
@@ -130,5 +136,6 @@
     ASSERT_TRUE(OptionalSerializableFunctionType::Populate(
         std::move(serialized), deserialized));
     EXPECT_FALSE(serializable_type.function_property);
+    EXPECT_EQ(serializable_type.Clone().ToValue(), serializable_type.ToValue());
   }
 }
diff --git a/tools/json_schema_compiler/test/idl_schemas_unittest.cc b/tools/json_schema_compiler/test/idl_schemas_unittest.cc
index 88b53ee..8cf6dae 100644
--- a/tools/json_schema_compiler/test/idl_schemas_unittest.cc
+++ b/tools/json_schema_compiler/test/idl_schemas_unittest.cc
@@ -31,6 +31,11 @@
 
 TEST(IdlCompiler, Basics) {
   // Test MyType1.
+  static_assert(!std::is_copy_constructible_v<MyType1>);
+  static_assert(!std::is_copy_assignable_v<MyType1>);
+  static_assert(std::is_move_constructible_v<MyType1>);
+  static_assert(std::is_move_assignable_v<MyType1>);
+
   MyType1 a;
   a.x = 5;
   a.y = std::string("foo");
@@ -38,6 +43,7 @@
   EXPECT_TRUE(MyType1::Populate(a.ToValue(), b));
   EXPECT_EQ(a.x, b.x);
   EXPECT_EQ(a.y, b.y);
+  EXPECT_EQ(a.Clone().ToValue(), a.ToValue());
 
   // Test Function2, which takes an integer parameter.
   base::Value::List list;
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index b494080..4c74a28 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -2452,7 +2452,7 @@
     ],
 
     'codesearch_gen_chromium_ios_bot': [
-      'codesearch_ios', 'ios',
+      'codesearch_ios', 'ios', 'ios_disable_code_signing'
     ],
 
     # Lacros uses different gn args to build for chromeOS device vs. Linux. For
diff --git a/tools/mb/mb_config_expectations/chromium.infra.codesearch.json b/tools/mb/mb_config_expectations/chromium.infra.codesearch.json
index 035cb03..465e1cb 100644
--- a/tools/mb/mb_config_expectations/chromium.infra.codesearch.json
+++ b/tools/mb/mb_config_expectations/chromium.infra.codesearch.json
@@ -44,6 +44,7 @@
       "blink_enable_generated_code_formatting": true,
       "clang_use_chrome_plugins": false,
       "enable_kythe_annotations": true,
+      "ios_enable_code_signing": false,
       "is_clang": true,
       "is_debug": true,
       "symbol_level": 1,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.codesearch.json b/tools/mb/mb_config_expectations/tryserver.chromium.codesearch.json
index 09ace9c..c371308 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.codesearch.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.codesearch.json
@@ -44,6 +44,7 @@
       "blink_enable_generated_code_formatting": true,
       "clang_use_chrome_plugins": false,
       "enable_kythe_annotations": true,
+      "ios_enable_code_signing": false,
       "is_clang": true,
       "is_debug": true,
       "symbol_level": 1,
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index b1d4bb6d..8c231c6 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -27666,6 +27666,12 @@
   </description>
 </action>
 
+<action name="SafeBrowsing.AccountIntegration.DisabledDialog.Dismissed">
+  <owner>jacastro@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <description>The ESB disabled dialog was dismissed.</description>
+</action>
+
 <action name="SafeBrowsing.AccountIntegration.DisabledDialog.OkButtonClicked">
   <owner>jacastro@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
@@ -27690,6 +27696,12 @@
   <description>The ESB disabled dialog was shown to the user.</description>
 </action>
 
+<action name="SafeBrowsing.AccountIntegration.EnabledDialog.Dismissed">
+  <owner>jacastro@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <description>The ESB enabled dialog was dismissed.</description>
+</action>
+
 <action name="SafeBrowsing.AccountIntegration.EnabledDialog.OkButtonClicked">
   <owner>jacastro@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 92120e8..6d885bda 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -19561,7 +19561,7 @@
 <enum name="ConversionNavigationDataHostStatus">
   <int value="0" label="Registered"/>
   <int value="1" label="Not found"/>
-  <int value="2" label="Navigation failed"/>
+  <int value="2" label="Ineligible"/>
   <int value="3" label="Processed"/>
 </enum>
 
@@ -41896,6 +41896,7 @@
   <int value="4526" label="FullscreenAllowedByWindowOpen"/>
   <int value="4527" label="AttributeValueContainsLtOrGt"/>
   <int value="4528" label="V8ImportAssertionDeprecatedSyntax"/>
+  <int value="4529" label="ImageCaptureBackgroundBlur"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
@@ -62824,6 +62825,7 @@
   <int value="638865852" label="UsePreferredIntervalForVideo:disabled"/>
   <int value="639765450" label="AccessCodeCastTabSwitchingUI:enabled"/>
   <int value="640174751" label="AndroidMultipleDisplay:enabled"/>
+  <int value="640256251" label="RemotePageMetadata:enabled"/>
   <int value="642037198" label="SoleIntegration:disabled"/>
   <int value="642601306" label="ForceInitialSyncWhenDecryptionFails:enabled"/>
   <int value="642678255" label="ExoGamepadVibration:disabled"/>
@@ -65315,6 +65317,7 @@
   <int value="1996125159" label="AutoplayMutedVideos:enabled"/>
   <int value="1997047666" label="NTPSnippetsIncreasedVisibility:disabled"/>
   <int value="1997347809" label="FedCmIdPregistration:enabled"/>
+  <int value="1997457877" label="RemotePageMetadata:disabled"/>
   <int value="1997931863" label="OmniboxContextMenuShowFullUrls:enabled"/>
   <int value="1998568354" label="DocumentPictureInPictureAPI:enabled"/>
   <int value="1998917160" label="AppServiceAdaptiveIcon:enabled"/>
@@ -75782,6 +75785,8 @@
   <int value="10" label="Launched new incognito tab."/>
   <int value="11" label="Menu or keyboard action."/>
   <int value="12" label="Unfocus."/>
+  <int value="13" label="Query tiles NTP omnibox tapped."/>
+  <int value="14" label="Focus restored on fold configuration change."/>
 </enum>
 
 <enum name="OmniboxFocusType">
@@ -84246,7 +84251,7 @@
   <int value="-2012727489" label="device.mojom.ScreenOrientation"/>
   <int value="-1354302262" label="blink.mojom.BackForwardCacheControllerHost"/>
   <int value="-71187962" label="supervised_user.mojom.SupervisedUserCommands"/>
-  <int value="-4973921" label="blink.mojom.ConversionHost"/>
+  <int value="-4973921" label="blink.mojom.AttributionHost"/>
   <int value="191605727" label="content.mojom.PepperHost"/>
   <int value="828689080" label="blink.mojom.BlobURLStore"/>
   <int value="1984681860"
@@ -86049,7 +86054,6 @@
   <int value="29" label="kLacrosMainProfile"/>
   <int value="30" label="kProfileCreationSamlFlow"/>
   <int value="31" label="kDriveFsNativeMessageHostLacros"/>
-  <int value="32" label="kProfileDeletionProcess"/>
 </enum>
 
 <enum name="ProfileMenuActionableItem">
@@ -91072,7 +91076,7 @@
   <int value="31" label="SENSITIVE_CONTENT_WARNING"/>
   <int value="32" label="SENSITIVE_CONTENT_BLOCK"/>
   <int value="33" label="DEEP_SCANNED_SAFE"/>
-  <int value="34" label="ADVANCED_PROTECTION_PROMPT"/>
+  <int value="34" label="DEEP_SCAN_PROMPT"/>
   <int value="35" label="BLOCKED_UNSUPPORTED_FILETYPE"/>
   <int value="36" label="ACCOUNT_COMPROMISE"/>
 </enum>
@@ -91574,6 +91578,14 @@
   <int value="3" label="Skipped: Unsupported scheme"/>
 </enum>
 
+<enum name="SBDeepScanEvent">
+  <int value="0" label="Prompt shown"/>
+  <int value="1" label="Prompt bypassed"/>
+  <int value="2" label="Prompt accepted"/>
+  <int value="3" label="Scan canceled"/>
+  <int value="4" label="Scan completed"/>
+</enum>
+
 <enum name="SBDeepScanTriggers">
   <int value="0" label="Unknown"/>
   <int value="1" label="Advanced Protection Prompt"/>
@@ -92172,6 +92184,14 @@
   <int value="8" label="Throttle prevented the prefetch"/>
 </enum>
 
+<enum name="SearchPrefetchResponseDataReaderStatus">
+  <int value="0" label="kCreated"/>
+  <int value="1" label="kServingError"/>
+  <int value="2" label="kNetworkError"/>
+  <int value="3" label="kCompleted"/>
+  <int value="4" label="kCanceledByLoader"/>
+</enum>
+
 <enum name="SearchPrefetchServingReason">
   <int value="0" label="Served a prefetch response"/>
   <int value="1" label="Search engine not set"/>
@@ -104702,6 +104722,7 @@
   <int value="131074" label="University user on enterprise device"/>
   <int value="131075" label="Nonprofit user on enterprise device"/>
   <int value="131076" label="Enterprise user on enterprise device"/>
+  <int value="196605" label="Demo Mode on an enterprise device"/>
   <int value="196606" label="Kiosk app on an enterprise device"/>
   <int value="196607" label="Managed guest session on an enterprise device"/>
 </enum>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml
index 1c3371d..d587bef 100644
--- a/tools/metrics/histograms/metadata/arc/histograms.xml
+++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -405,7 +405,7 @@
 
 <histogram
     name="Arc.App.LowMemoryKills{ArcAppKillDailyBackgroundVms}{ArcAppKillDailyType}"
-    units="Apps" expires_after="2023-04-24">
+    units="Apps" expires_after="2023-09-29">
   <owner>cwd@google.com</owner>
   <owner>cros-vm-technology@google.com</owner>
   <summary>
@@ -1521,8 +1521,8 @@
 </histogram>
 
 <histogram name="Arc.NearbyShare.ArcBridgeFailure"
-    enum="NearbyShareArcBridgeFailResult" expires_after="2023-03-24">
-  <owner>ttefera@google.com</owner>
+    enum="NearbyShareArcBridgeFailResult" expires_after="2023-09-27">
+  <owner>alanding@google.com</owner>
   <owner>arc-app-dev@google.com</owner>
   <summary>
     Records any ARC Bridge connection / communication failures using
@@ -1531,8 +1531,8 @@
 </histogram>
 
 <histogram name="Arc.NearbyShare.DataHandlingFailure"
-    enum="ArcNearbyShareDataHandlingResult" expires_after="2023-08-27">
-  <owner>ttefera@google.com</owner>
+    enum="ArcNearbyShareDataHandlingResult" expires_after="2023-09-27">
+  <owner>alanding@google.com</owner>
   <owner>arc-app-dev@google.com</owner>
   <summary>
     Records any data handling errors with sharing text or files using
@@ -1541,7 +1541,7 @@
 </histogram>
 
 <histogram name="Arc.NearbyShare.FileStreamComplete.TimeDelta" units="ms"
-    expires_after="2023-08-08">
+    expires_after="2023-09-27">
   <owner>alanding@google.com</owner>
   <owner>arc-app-dev@google.com</owner>
   <summary>
@@ -1552,8 +1552,8 @@
 </histogram>
 
 <histogram name="Arc.NearbyShare.FileStreamFailure" enum="PlatformFileError"
-    expires_after="2023-08-27">
-  <owner>ttefera@google.com</owner>
+    expires_after="2023-09-27">
+  <owner>alanding@google.com</owner>
   <owner>arc-app-dev@google.com</owner>
   <summary>
     Records the reason for failing to stream a file using NearbyShare. ARC
@@ -1563,15 +1563,15 @@
 </histogram>
 
 <histogram name="Arc.NearbyShare.IOFailure" enum="ArcNearbyShareIOErrorResult"
-    expires_after="2023-08-27">
-  <owner>ttefera@google.com</owner>
+    expires_after="2023-09-27">
+  <owner>alanding@google.com</owner>
   <owner>arc-app-dev@google.com</owner>
   <summary>Records any IO errors while using NearbyShare.</summary>
 </histogram>
 
 <histogram name="Arc.NearbyShare.WindowFound" units="units"
-    expires_after="2023-03-24">
-  <owner>ttefera@google.com</owner>
+    expires_after="2023-09-27">
+  <owner>alanding@google.com</owner>
   <owner>arc-app-dev@google.com</owner>
   <summary>
     Records the success or failure of attempts to find NearbyShare window. ARC
diff --git a/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml b/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml
index 8a3c498..fa393bb 100644
--- a/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml
@@ -309,6 +309,17 @@
   </summary>
 </histogram>
 
+<histogram name="Ash.ClipboardHistory.PasteSource"
+    enum="ClipboardHistoryTriggerType" expires_after="2023-08-27">
+  <owner>ckincaid@chromium.org</owner>
+  <owner>multipaste@google.com</owner>
+  <summary>
+    The way a user made the clipboard history menu show before selecting an item
+    from that menu to paste. Recorded when an item is pasted from clipboard
+    history.
+  </summary>
+</histogram>
+
 <histogram name="Ash.ClipboardHistory.PasteType"
     enum="ClipboardHistoryPasteType" expires_after="2023-08-27">
   <owner>ckincaid@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/auto/histograms.xml b/tools/metrics/histograms/metadata/auto/histograms.xml
index 22d6219..bbea620 100644
--- a/tools/metrics/histograms/metadata/auto/histograms.xml
+++ b/tools/metrics/histograms/metadata/auto/histograms.xml
@@ -29,10 +29,9 @@
 
 <histogram
     name="AutoScreenBrightness.AdapterDecisionAtUserChange.BrightnessChange.Cause"
-    enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When user changes brightness manually, we will ask the model whether it also
     thinks brightness should be changed. This enum states the reason why the
@@ -42,12 +41,11 @@
 
 <histogram base="true"
     name="AutoScreenBrightness.AdapterDecisionAtUserChange.ModelIteration"
-    units="count" expires_after="2023-04-30">
+    units="count" expires_after="2023-10-31">
 <!-- Name completed by histogram_suffixes name="AdapterDecision" -->
 
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When user changes brightness manually, we will ask the model whether it also
     thinks brightness should be changed. We also log the number of model
@@ -58,10 +56,9 @@
 <histogram
     name="AutoScreenBrightness.AdapterDecisionAtUserChange.NoBrightnessChange.Cause"
     enum="AutoScreenBrightnessNoBrightnessChangeCause"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When user changes brightness manually, we will ask the model whether it also
     thinks brightness should be changed. This enum states the reason why the
@@ -71,12 +68,11 @@
 
 <histogram
     name="AutoScreenBrightness.AdapterDecisionAtUserChange.Unknown.AlsStd"
-    units="count" expires_after="2023-04-30">
+    units="count" expires_after="2023-10-31">
 <!-- Name completed by histogram_suffixes name="AdapterDecision" -->
 
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When user changes brightness manually, we will ask the model whether it also
     thinks brightness should be changed. We also log the als-stddev in its
@@ -87,10 +83,9 @@
 
 <histogram
     name="AutoScreenBrightness.AdapterDecisionAtUserChange.{AlsBrightnessDirection}AlsDelta"
-    units="count" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="count" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When user changes brightness manually, we will ask the model whether it also
     thinks brightness should be changed. We also log the als-delta from the
@@ -105,10 +100,9 @@
 
 <histogram
     name="AutoScreenBrightness.AdapterDecisionAtUserChange.{AlsBrightnessDirection}AlsStd"
-    units="count" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="count" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When user changes brightness manually, we will ask the model whether it also
     thinks brightness should be changed. We also log the als-stddev in its
@@ -121,38 +115,34 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.AlsReaderStatus"
-    enum="AutoScreenBrightnessAlsReaderStatus" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="AutoScreenBrightnessAlsReaderStatus" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Whether the ALS is enabled or the error otherwise. Chrome OS only.
   </summary>
 </histogram>
 
 <histogram name="AutoScreenBrightness.BrightnessChange.Cause"
-    enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>Reason for the model to change brightness. Chrome OS only.</summary>
 </histogram>
 
 <histogram name="AutoScreenBrightness.BrightnessChange.ElapsedTime" units="ms"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     The time between two consecutive auto brightness changes. Chrome OS only.
   </summary>
 </histogram>
 
 <histogram name="AutoScreenBrightness.BrightnessChange.ModelIteration"
-    units="count" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="count" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Number of model iterations when brightness is changed by a personal curve.
     Chrome OS only.
@@ -161,10 +151,9 @@
 
 <histogram name="AutoScreenBrightness.BrightnessMonitorStatus"
     enum="AutoScreenBrightnessBrightnessMonitorStatus"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Whether the brightness monitor is enabled or the error otherwise. Chrome OS
     only.
@@ -172,10 +161,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.DailyUserAdjustment.Atlas" units="count"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Number of times that a user has made brightness adjustments on an Atlas
     device with an ambient sensor that is supported by the auto screen
@@ -189,10 +177,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.DailyUserAdjustment.Eve" units="count"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Number of times that a user has made brightness adjustments on an Eve device
     with an ambient sensor that is supported by the auto screen brightness
@@ -205,10 +192,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.DailyUserAdjustment.Kohaku" units="count"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Number of times that a user has made brightness adjustments on a Kohaku
     device with an ambient sensor that is supported by the auto screen
@@ -222,10 +208,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.DailyUserAdjustment.NoAls" units="count"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Number of times that a user has made brightness adjustments on a device
     without an ambient sensor. Reported daily. The count is accumulated through
@@ -238,10 +223,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.DailyUserAdjustment.Nocturne"
-    units="count" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="count" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Number of times that a user has made brightness adjustments on a Nocturne
     device with an ambient sensor that is supported by the auto screen
@@ -255,10 +239,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.DailyUserAdjustment.SupportedAls"
-    units="count" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="count" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Number of times that a user has made brightness adjustments on a device with
     an ambient sensor that is supported by the auto screen brightness model.
@@ -271,10 +254,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.DailyUserAdjustment.UnsupportedAls"
-    units="count" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="count" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Number of times that a user has made brightness adjustments on a device with
     an ambient sensor that is not supported by the auto screen brightness model.
@@ -287,10 +269,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.DataError"
-    enum="AutoScreenBrightnessDataError" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="AutoScreenBrightnessDataError" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Type of error seen when handling data related to automatic screen brightness
     adjustments. Only reported on Chrome OS.
@@ -299,10 +280,9 @@
 
 <histogram
     name="AutoScreenBrightness.ElapsedTimeBetweenModelAndUserAdjustments"
-    units="ms" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="ms" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     The elapsed time from a model brightness adjustment to the next user manual
     brightness change. Chrome OS only.
@@ -310,18 +290,16 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.GlobalCurveResetOnInitialization"
-    enum="Boolean" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="Boolean" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>Whether the global curve is reset at initialization.</summary>
 </histogram>
 
 <histogram name="AutoScreenBrightness.InvalidCurveReason"
-    enum="AutoScreenBrightnessInvalidCurveReason" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="AutoScreenBrightnessInvalidCurveReason" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     A monotone cubic spline curve may be invalid from input that used to
     generate it. This metric records why it's invalid. Chrome OS only.
@@ -330,9 +308,8 @@
 
 <histogram name="AutoScreenBrightness.MissingAlsWhenBrightnessChanged"
     enum="BooleanError" expires_after="2023-09-03">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Whether there was no recorded ALS reading when brightness was changed.
   </summary>
@@ -340,9 +317,8 @@
 
 <histogram name="AutoScreenBrightness.MissingPriorUserBrightnessRequest"
     enum="BooleanError" expires_after="2023-09-03">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Under the current implementation of brightness monitor, user brightness
     request should be received before brightness change signal. Adapter operates
@@ -353,31 +329,28 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.ModelIterationCountAtInitialization"
-    units="count" expires_after="2023-04-30">
-  <owner>napper@chromium.org</owner>
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="count" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>napper@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Personal model iteration count when modeller is initialized. Chrome OS only.
   </summary>
 </histogram>
 
 <histogram name="AutoScreenBrightness.ModelLoadingStatus"
-    enum="AutoScreenBrightnessModelLoadingStatus" expires_after="2023-04-30">
-  <owner>napper@chromium.org</owner>
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="AutoScreenBrightnessModelLoadingStatus" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>napper@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>Status of the model loading from disk. Chrome OS only.</summary>
 </histogram>
 
 <histogram name="AutoScreenBrightness.ModelTraining.BrightnessChange"
     enum="AutoScreenBrightnessBoundedBrightnessChange"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Whether a new brightness exceeds the preset bound that defines reasonble
     range of change. Chrome OS only.
@@ -385,10 +358,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.ModelTraining.BrightnessOutlier"
-    enum="Boolean" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="Boolean" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Whether a training data is an outlier and should be discarded by the model
     during training. Chrome OS only.
@@ -396,11 +368,10 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.ModelTraining.Inaccuracy.NoUpdate"
-    units="%" expires_after="2023-04-30">
-  <owner>napper@chromium.org</owner>
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="%" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>napper@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When training data comes in, the model may or may not be updated. We measure
     the error of the model as compared with the target value from training data.
@@ -409,11 +380,10 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.ModelTraining.Inaccuracy.Update"
-    units="%" expires_after="2023-04-30">
-  <owner>napper@chromium.org</owner>
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="%" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>napper@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When training data comes in, the model may or may not be updated. We measure
     the error of the model as compared with the target value from training data.
@@ -422,10 +392,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.ModelTraining.ModelUserConsistent"
-    enum="Boolean" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="Boolean" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Whether user brightness change is consistent with the model so that model is
     not updated.
@@ -433,10 +402,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.NewCurveSaved.Duration" units="ms"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     The time elapsed between training start and a new curve saved to disk. Only
     reported if a new curve was created and saved successfully to disk. Chrome
@@ -445,10 +413,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.NewCurveSaved.Success"
-    enum="BooleanSuccess" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="BooleanSuccess" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Whether a new curve was successfully saved to disk. Only reported if a new
     curve was created during the training process. Chrome OS only.
@@ -456,10 +423,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.Opposite.UserModelBrightnessAdjustments"
-    units="count" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="count" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When user changes brightness manually, if the previous change was caused by
     the model, then we log bucketized absolute brightness changes of the two
@@ -469,10 +435,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.ParameterError"
-    enum="AutoScreenBrightnessParameterError" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="AutoScreenBrightnessParameterError" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When there is an error in the automatic screen brightness parameters, this
     records which kind of parameter is invalid. Chrome OS only.
@@ -480,20 +445,18 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.PersonalCurveValid" enum="BooleanValid"
-    expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     Whether the user's personal brightness curve is valid. Chrome OS only.
   </summary>
 </histogram>
 
 <histogram name="AutoScreenBrightness.Same.UserModelBrightnessAdjustments"
-    units="count" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="count" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     When user changes brightness manually, if the previous change was caused by
     the model, then we log bucketized absolute brightness changes of the two
@@ -503,10 +466,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.TrainingCompleteDuration.NewCurve"
-    units="ms" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="ms" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     The time elapsed to complete training after which a new curve was generated.
     Chrome OS only.
@@ -514,10 +476,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.TrainingCompleteDuration.NoNewCurve"
-    units="ms" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    units="ms" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     The time elapsed to complete training after which no new curve was
     generated. Chrome OS only.
@@ -525,10 +486,9 @@
 </histogram>
 
 <histogram name="AutoScreenBrightness.UserAdjustmentEffect"
-    enum="AutoScreenBrightnessUserAdjustmentEffect" expires_after="2023-04-30">
-  <owner>wrong@chromium.org</owner>
-  <owner>tby@chromium.org</owner>
+    enum="AutoScreenBrightnessUserAdjustmentEffect" expires_after="2023-10-31">
   <owner>thanhdng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
   <summary>
     How user manual screen brightness adjustment changes the model. Chrome OS
     only.
diff --git a/tools/metrics/histograms/metadata/chrome/histograms.xml b/tools/metrics/histograms/metadata/chrome/histograms.xml
index f61d6b7..f7481d34 100644
--- a/tools/metrics/histograms/metadata/chrome/histograms.xml
+++ b/tools/metrics/histograms/metadata/chrome/histograms.xml
@@ -91,7 +91,7 @@
 </histogram>
 
 <histogram name="Chrome.KAnonymityService.TrustTokenGetter.Action"
-    enum="KAnonymityTrustTokenGetterAction" expires_after="M113">
+    enum="KAnonymityTrustTokenGetterAction" expires_after="M115">
   <owner>behamilton@google.com</owner>
   <owner>pauljensen@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/event/histograms.xml b/tools/metrics/histograms/metadata/event/histograms.xml
index 41b1363..0693db4 100644
--- a/tools/metrics/histograms/metadata/event/histograms.xml
+++ b/tools/metrics/histograms/metadata/event/histograms.xml
@@ -70,16 +70,6 @@
   </summary>
 </histogram>
 
-<histogram name="Event.AsyncTargeting.ResponseTime" units="ms"
-    expires_after="2023-02-12">
-  <owner>jonross@chromium.org</owner>
-  <owner>event-targeting@chromium.org</owner>
-  <summary>
-    Tracks how long it takes for a client to respond to an asynchronous request
-    to find a target for an input event.
-  </summary>
-</histogram>
-
 <histogram name="Event.BrowserVerifiedUserActivation" enum="BooleanSuccess"
     expires_after="2021-10-17">
   <owner>liviutinta@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index 40c79f93..f1d598f 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -720,7 +720,7 @@
 </histogram>
 
 <histogram name="IOS.FinishedNavigationHasContext" enum="Boolean"
-    expires_after="2023-05-01">
+    expires_after="2024-05-01">
   <owner>gambard@chromium.org</owner>
   <owner>bling-team@google.com</owner>
   <summary>
@@ -734,7 +734,7 @@
 </histogram>
 
 <histogram name="IOS.FinishedNavigationHasItem" enum="Boolean"
-    expires_after="2023-05-01">
+    expires_after="2024-05-01">
   <owner>gambard@chromium.org</owner>
   <owner>bling-team@google.com</owner>
   <summary>
@@ -1683,7 +1683,7 @@
 </histogram>
 
 <histogram name="IOS.PostRestoreSignin.Choice"
-    enum="IOSPostRestoreSigninChoice" expires_after="2023-04-15">
+    enum="IOSPostRestoreSigninChoice" expires_after="2023-06-15">
   <owner>scottyoder@google.com</owner>
   <owner>bling-get-set-up@google.com</owner>
   <summary>
@@ -1692,7 +1692,7 @@
 </histogram>
 
 <histogram name="IOS.PostRestoreSignin.Displayed" enum="Boolean"
-    expires_after="2023-04-15">
+    expires_after="2023-06-15">
   <owner>scottyoder@google.com</owner>
   <owner>bling-get-set-up@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index 8989421..19be207 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -1553,7 +1553,7 @@
 
 <histogram
     name="Prerender.CanceledForInactivePageRestriction.DisallowActivationReason{PrerenderTriggerType}"
-    enum="InactiveFrameDisallowActivationReason" expires_after="2023-03-01">
+    enum="InactiveFrameDisallowActivationReason" expires_after="2023-09-03">
   <owner>lingqi@chromium.org</owner>
   <owner>chrome-prerendering@chromium.org</owner>
   <summary>
@@ -1569,13 +1569,16 @@
 
     Note: This histogram does not track prerender activation behavior, but to
     analyze PrerenderHostFinalStatus::kInactivePageRestriction.
+
+    Warning: this histogram was expired from 2023-03-01 to 2023-03-29; data may
+    be missing.
   </summary>
   <token key="PrerenderTriggerType" variants="PrerenderTriggerType"/>
 </histogram>
 
 <histogram
     name="Prerender.Experimental.ActivationHeadersMismatch{PrerenderTriggerType}"
-    enum="PrerenderActivationHeaderMismatchType" expires_after="2023-01-31">
+    enum="PrerenderActivationHeaderMismatchType" expires_after="2023-09-03">
   <owner>lingqi@chromium.org</owner>
   <owner>chrome-prerendering@google.com</owner>
   <summary>
@@ -1593,13 +1596,16 @@
     records the hashed number of a mismatching header, together with the
     mismatching reason: Missing in prerendering navigation, missing in
     activation navigation, or the values mismatch.
+
+    Warning: this histogram was expired from 2023-01-31 to 2023-03-29; data may
+    be missing.
   </summary>
   <token key="PrerenderTriggerType" variants="PrerenderTriggerType"/>
 </histogram>
 
 <histogram
     name="Prerender.Experimental.ActivationNavigationParamsMatch{PrerenderTriggerType}"
-    enum="PrerenderActivationNavigationParamsMatch" expires_after="2023-06-05">
+    enum="PrerenderActivationNavigationParamsMatch" expires_after="2023-09-03">
   <owner>nhiroki@chromium.org</owner>
   <owner>chrome-prerendering@google.com</owner>
   <summary>
@@ -1637,7 +1643,7 @@
 <histogram
     name="Prerender.Experimental.CrossOriginRedirectionProtocolChange{PrerenderTriggerType}"
     enum="PrerenderCrossOriginRedirectionProtocolChange"
-    expires_after="2023-04-30">
+    expires_after="2023-09-03">
   <owner>lingqi@chromium.org</owner>
   <owner>nhiroki@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
@@ -1732,7 +1738,7 @@
 
 <histogram
     name="Prerender.Experimental.PrerenderCrossOriginRedirectionMismatch{PrerenderTriggerType}"
-    enum="PrerenderCrossOriginRedirectionMismatch" expires_after="2023-04-30">
+    enum="PrerenderCrossOriginRedirectionMismatch" expires_after="2023-09-03">
   <owner>lingqi@chromium.org</owner>
   <owner>nhiroki@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml
index ac7eee9..9d31722e 100644
--- a/tools/metrics/histograms/metadata/omnibox/histograms.xml
+++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -1538,6 +1538,18 @@
   </token>
 </histogram>
 
+<histogram name="Omnibox.SearchPreload.ResponseDataReaderFinalStatus.Prerender"
+    enum="SearchPrefetchResponseDataReaderStatus" expires_after="2023-08-02">
+  <owner>lingqi@chromium.org</owner>
+  <owner>ryansturm@chromium.org</owner>
+  <owner>chrome-prerendering@google.com</owner>
+  <summary>
+    Tracks whether the StreamingSearchPrefetchURLLoader::ResponseReader can
+    successfully serving to prerender clients. Recorded when a
+    `StreamingSearchPrefetchURLLoader::ResponseReader` is destroyed.
+  </summary>
+</histogram>
+
 <histogram name="Omnibox.SearchProviderMatches" units="units"
     expires_after="2022-09-11">
   <obsolete>
@@ -1944,7 +1956,7 @@
 <histogram
     name="Omnibox.SuggestionUsed.Search.NavigationToLargestContentfulPaint2"
     units="ms" expires_after="2023-09-03">
-  <owner>asamidoi@chromium.org</owner>
+  <owner>lingqi@chromium.org</owner>
   <owner>chrome-prerendering@google.com</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
@@ -2037,8 +2049,8 @@
 
 <histogram
     name="Omnibox.SuggestionUsed.URL.NavigationToLargestContentfulPaint2"
-    units="ms" expires_after="2023-04-27">
-  <owner>asamidoi@chromium.org</owner>
+    units="ms" expires_after="2023-09-03">
+  <owner>robertlin@chromium.org</owner>
   <owner>chrome-prerendering@google.com</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index 612bb33..6b24319 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -3777,7 +3777,7 @@
   </summary>
 </histogram>
 
-<histogram name="Conversions.NavigationDataHostStatus2"
+<histogram name="Conversions.NavigationDataHostStatus3"
     enum="ConversionNavigationDataHostStatus" expires_after="M117">
   <owner>linnan@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
@@ -4164,6 +4164,22 @@
   </summary>
 </histogram>
 
+<histogram name="Conversions.{ReportType}.NetworkConnectionTypeOnFailure"
+    enum="NetworkConnectionType" expires_after="M117">
+  <owner>linnan@chromium.org</owner>
+  <owner>johnidel@chromium.org</owner>
+  <owner>measurement-api-dev+metrics@google.com</owner>
+  <summary>
+    Records the network connection type in the event that the report failed to
+    be sent due to network issues. Recorded for each report sending attempt that
+    failed.
+  </summary>
+  <token key="ReportType">
+    <variant name="AggregatableReport"/>
+    <variant name="EventLevelReport"/>
+  </token>
+</histogram>
+
 <histogram name="CopylessPaste.CacheHit" enum="CopylessCacheHit"
     expires_after="2020-03-01">
   <owner>wychen@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 3772d7c..d8389df 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -944,9 +944,8 @@
 
 <histogram
     name="PageLoad.Clients.Prerender.InteractiveTiming.FirstInputDelay4{PrerenderTriggerType}"
-    units="ms" expires_after="2023-04-27">
+    units="ms" expires_after="2023-09-03">
   <owner>ksakamoto@chromium.org</owner>
-  <owner>asamidoi@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
     PageLoad.InteractiveTiming.FirstInputDelay4, but for page loads that were
@@ -962,9 +961,8 @@
 
 <histogram
     name="PageLoad.Clients.Prerender.LayoutInstability.CumulativeShiftScore.MainFrame{PrerenderTriggerType}"
-    units="ms" expires_after="2023-04-27">
+    units="ms" expires_after="2023-09-03">
   <owner>ksakamoto@chromium.org</owner>
-  <owner>asamidoi@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
     PageLoad.LayoutInstability.CumulativeShiftScore.MainFrame, but for page
@@ -981,9 +979,8 @@
 
 <histogram
     name="PageLoad.Clients.Prerender.LayoutInstability.CumulativeShiftScore{PrerenderTriggerType}"
-    units="ms" expires_after="2023-04-27">
+    units="ms" expires_after="2023-09-03">
   <owner>ksakamoto@chromium.org</owner>
-  <owner>asamidoi@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
     PageLoad.LayoutInstability.CumulativeShiftScore, but for page loads that
@@ -999,8 +996,8 @@
 
 <histogram
     name="PageLoad.Clients.Prerender.LayoutInstability.MaxCumulativeShiftScore.SessionWindow.Gap1000ms.Max5000ms2{PrerenderTriggerType}"
-    units="ms" expires_after="2023-04-27">
-  <owner>asamidoi@chromium.org</owner>
+    units="ms" expires_after="2023-09-03">
+  <owner>kenoss@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
     PageLoad.LayoutInstability.MaxCumulativeShiftScore.SessionWindow.Gap1000ms.Max5000ms2,
@@ -1017,9 +1014,8 @@
 
 <histogram
     name="PageLoad.Clients.Prerender.NavigationToActivation{PrerenderTriggerType}"
-    units="ms" expires_after="2023-04-27">
+    units="ms" expires_after="2023-09-03">
   <owner>ksakamoto@chromium.org</owner>
-  <owner>asamidoi@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
     Measures the time from the start of initial prerendering navigation to the
@@ -1051,9 +1047,8 @@
 
 <histogram
     name="PageLoad.Clients.Prerender.PaintTiming.ActivationToFirstContentfulPaint{PrerenderTriggerType}"
-    units="ms" expires_after="2023-04-27">
+    units="ms" expires_after="2023-09-03">
   <owner>ksakamoto@chromium.org</owner>
-  <owner>asamidoi@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
     PageLoad.PaintTiming.NavigationToFirstContentfulPaint, but for page loads
@@ -1071,9 +1066,8 @@
 
 <histogram
     name="PageLoad.Clients.Prerender.PaintTiming.ActivationToFirstPaint{PrerenderTriggerType}"
-    units="ms" expires_after="2023-04-27">
+    units="ms" expires_after="2023-09-03">
   <owner>ksakamoto@chromium.org</owner>
-  <owner>asamidoi@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
     PageLoad.PaintTiming.NavigationToFirstPaint, but for page loads that were
@@ -1090,9 +1084,8 @@
 
 <histogram
     name="PageLoad.Clients.Prerender.PaintTiming.ActivationToLargestContentfulPaint2{PrerenderTriggerType}"
-    units="ms" expires_after="2023-04-27">
+    units="ms" expires_after="2023-09-03">
   <owner>ksakamoto@chromium.org</owner>
-  <owner>asamidoi@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
     PageLoad.PaintTiming.NavigationToLargestContentfulPaint2, but for page loads
@@ -1386,7 +1379,7 @@
 
 <histogram
     name="PageLoad.Clients.UseCounter.Experimental.MetricsReplayAtActivationDuration"
-    units="ms" expires_after="2023-03-16">
+    units="ms" expires_after="2023-09-03">
   <owner>kenoss@chromium.org</owner>
   <owner>toyoshim@chromium.org</owner>
   <summary>
@@ -1398,6 +1391,9 @@
     memory. When a page is activated then, buffered metrics are flushed and
     recorded. This metric records the duration of this flush, in case of this
     cause a performance degradation.
+
+    Warning: this histogram was expired from 2023-03-16 to 2023-03-29; data may
+    be missing.
   </summary>
 </histogram>
 
@@ -2524,7 +2520,7 @@
 
 <histogram name="PageLoad.Internal.Prerender2.Event"
     enum="PageLoadPrerenderEvent" expires_after="2023-09-17">
-  <owner>asamidoi@chromium.org</owner>
+  <owner>kenoss@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
     Counts page load events related to Prerender2, like navigation in
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml
index 633f390d..2c93e00147 100644
--- a/tools/metrics/histograms/metadata/platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -504,6 +504,19 @@
   </summary>
 </histogram>
 
+<histogram name="Platform.ExternalMetrics.SamplesRead" units="count"
+    expires_after="2023-09-27">
+  <owner>iby@google.com</owner>
+  <owner>mutexlox@google.com</owner>
+  <owner>cros-telemetry@google.com</owner>
+  <summary>
+    On ChromeOS, number of external metrics samples read in from the platform.
+    Emitted once every 30 seconds. If this is too large (over 100,000), we will
+    silently lose metrics. Additionally, 100,000 is the largest number we'll
+    ever record here: we stop counting when we hit 100,000.
+  </summary>
+</histogram>
+
 <histogram name="Platform.FileSystem.ErrorCount" units="errors"
     expires_after="2023-09-01">
   <owner>gwendal@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index ae689e2..ca53b79b 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -1978,6 +1978,17 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.TailoredSecurity.IsRecoveryTriggered"
+    enum="Boolean" expires_after="2024-03-24">
+  <owner>awado@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <summary>
+    Records whether the observer-based retry mechanism for the
+    ChromeTailoredSecurityService has been triggered or not which is logged on
+    every update to the synced account ESB timestamp.
+  </summary>
+</histogram>
+
 <histogram
     name="SafeBrowsing.TailoredSecurity.SyncPromptEnabledNotificationResult"
     enum="SafeBrowsingTailoredSecurityNotificationResult"
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml
index 165fcfa..07be9996 100644
--- a/tools/metrics/histograms/metadata/sb_client/histograms.xml
+++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -62,6 +62,19 @@
   </summary>
 </histogram>
 
+<histogram name="SBClientDownload.DeepScanEvent" enum="SBDeepScanEvent"
+    expires_after="2024-03-28">
+  <owner>drubery@chromium.org</owner>
+  <owner>chrome-counter-abuse-alerts@google.com</owner>
+  <summary>
+    Records events related to user interaction with deep scanning prompts. This
+    is recorded a few times during the process of each prompt for deep scanning:
+    - Once when the prompt is shown. - Once when the prompt is
+    accepted/bypassed. - Once when the scan is completed, either through
+    cancelation or completion.
+  </summary>
+</histogram>
+
 <histogram name="SBClientDownload.DeepScanTrigger" enum="SBDeepScanTriggers"
     expires_after="2023-08-08">
   <owner>drubery@chromium.org</owner>
@@ -371,8 +384,9 @@
     be missing.
   </summary>
   <token key="trigger">
-    <variant name="AdvancedProtectionPrompt"
-        summary="Advanced Protection user selected 'Scan'"/>
+    <variant name="ConsumerPrompt"
+        summary="Advanced Protection or Enhanced Protection user selected
+                 'Scan'"/>
     <variant name="Policy" summary="Triggered by enterprise policy"/>
     <variant name="Unknown" summary="Unknown trigger"/>
   </token>
diff --git a/tools/metrics/histograms/metadata/sharing/histograms.xml b/tools/metrics/histograms/metadata/sharing/histograms.xml
index 5684ba3..a98ab65 100644
--- a/tools/metrics/histograms/metadata/sharing/histograms.xml
+++ b/tools/metrics/histograms/metadata/sharing/histograms.xml
@@ -592,7 +592,7 @@
 </histogram>
 
 <histogram name="Sharing.SmsFetcherAvailableDeviceCount" units="devices"
-    expires_after="2023-07-02">
+    expires_after="2023-11-01">
   <owner>yigu@chromium.org</owner>
   <owner>src/content/browser/sms/OWNERS</owner>
   <summary>
@@ -603,7 +603,7 @@
 </histogram>
 
 <histogram name="Sharing.SmsFetcherClientNameIsEmpty" enum="BooleanEmpty"
-    expires_after="2023-04-30">
+    expires_after="2023-11-01">
   <owner>yigu@chromium.org</owner>
   <owner>src/content/browser/sms/OWNERS</owner>
   <summary>
@@ -614,7 +614,7 @@
 </histogram>
 
 <histogram name="Sharing.SmsFetcherScreenOnAndUnlocked" enum="Boolean"
-    expires_after="2023-06-11">
+    expires_after="2023-11-01">
   <owner>yigu@chromium.org</owner>
   <owner>src/content/browser/sms/OWNERS</owner>
   <summary>
@@ -625,7 +625,7 @@
 </histogram>
 
 <histogram name="Sharing.SmsFetcherTapWithChromeDestroyed" enum="Boolean"
-    expires_after="2023-05-07">
+    expires_after="2023-11-01">
   <owner>yigu@chromium.org</owner>
   <owner>src/content/browser/sms/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml
index e159ead..44bd718 100644
--- a/tools/metrics/histograms/metadata/storage/histograms.xml
+++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -531,7 +531,7 @@
 </histogram>
 
 <histogram name="Storage.InterestGroup.DBMaintenanceTime" units="microseconds"
-    expires_after="2023-04-30">
+    expires_after="M115">
   <owner>behamilton@google.com</owner>
   <owner>pauljensen@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml
index 1651f0d..e2d6d82 100644
--- a/tools/metrics/histograms/metadata/sync/histograms.xml
+++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -376,7 +376,7 @@
 </histogram>
 
 <histogram name="Sync.Crypto.NigoriKeyDerivationDuration.{Method}" units="ms"
-    expires_after="2023-05-01">
+    expires_after="2023-11-01">
   <owner>mmoskvitin@google.com</owner>
   <owner>treib@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -646,7 +646,7 @@
 </histogram>
 
 <histogram name="Sync.KeystoreDecryptionFailed"
-    enum="SyncKeystoreDecryptionFailure" expires_after="2023-05-06">
+    enum="SyncKeystoreDecryptionFailure" expires_after="2023-11-06">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1204,7 +1204,7 @@
 </histogram>
 
 <histogram name="Sync.RecordedUserEventType" enum="SyncUserEventType"
-    expires_after="2023-05-07">
+    expires_after="2023-11-07">
   <owner>mmoskvitin@google.com</owner>
   <owner>treib@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1723,7 +1723,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultURLFetchResponse{Reason}"
-    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2023-05-01">
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2023-11-01">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py
index 7622b85..ab86b21 100644
--- a/tools/perf/benchmarks/system_health_smoke_test.py
+++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -76,6 +76,9 @@
     'system_health.memory_desktop/load:social:instagram:2018',
     'system_health.memory_desktop/load:social:pinterest:2019',
 
+    # crbug.com/1428625
+    'system_health.memory_mobile/browse:news:cnn:2021',
+
     # The following tests are disabled because they are disabled on the perf
     # waterfall (using tools/perf/expectations.config) on one platform or
     # another. They may run fine on the CQ, but it isn't worth the bot time to
diff --git a/tools/rust/update_rust.py b/tools/rust/update_rust.py
index fa88428f..9253291 100755
--- a/tools/rust/update_rust.py
+++ b/tools/rust/update_rust.py
@@ -23,12 +23,13 @@
 
 # Add Clang scripts to path so we can import them later (if running within a
 # Chromium checkout.)
+# Note: Imports cannot be done until after the --print-rust-revision flag
+# has been processed, since that needs to work when running this script
+# in isolation.
 sys.path.append(
     os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'clang',
                  'scripts'))
 
-from update import (CHROMIUM_DIR)
-
 # These fields are written by //tools/clang/scripts/upload_revision.py, and
 # should not be changed manually.
 RUST_REVISION = 'ac4379fea9e83465d814bb05005689f49bd2141e'
@@ -72,6 +73,7 @@
 STAGE0_JSON_SHA256 = 'b45d1f388bfe54887d5776937e05a135ec819b6d2190b8794bb87bd7072e5553'
 
 THIS_DIR = os.path.abspath(os.path.dirname(__file__))
+CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..'))
 THIRD_PARTY_DIR = os.path.join(CHROMIUM_DIR, 'third_party')
 RUST_TOOLCHAIN_OUT_DIR = os.path.join(THIRD_PARTY_DIR, 'rust-toolchain')
 VERSION_STAMP_PATH = os.path.join(RUST_TOOLCHAIN_OUT_DIR, 'VERSION')
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index b9ce4489..ee51937f 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -226,7 +226,7 @@
  <item id="services_http_server_error_response" added_in_milestone="68" content_hash_code="079dad59" os_list="linux,windows,chromeos,android" file_path="services/network/public/cpp/server/http_server.cc" />
  <item id="shared_storage_worklet_module_script_downloader" added_in_milestone="95" content_hash_code="072bbf71" os_list="linux,windows,chromeos,android" file_path="third_party/blink/common/shared_storage/module_script_downloader.cc" />
  <item id="sigined_exchange_cert_fetcher" added_in_milestone="66" content_hash_code="007c2dac" os_list="linux,windows,chromeos,android" file_path="content/browser/web_package/signed_exchange_cert_fetcher.cc" />
- <item id="signed_in_profile_avatar" added_in_milestone="62" content_hash_code="00619a19" os_list="linux,windows,chromeos,android" file_path="chrome/browser/profiles/profile_downloader.cc" />
+ <item id="signed_in_profile_avatar" added_in_milestone="62" content_hash_code="04934c15" os_list="linux,windows,chromeos,android" file_path="chrome/browser/profiles/profile_downloader.cc" />
  <item id="socket_bio_adapter" added_in_milestone="66" content_hash_code="014a4058" os_list="linux,windows,chromeos,android" file_path="net/socket/socket_bio_adapter.cc" />
  <item id="spdy_push_stream" added_in_milestone="67" content_hash_code="042048b5" os_list="linux,windows,chromeos,android" file_path="net/spdy/spdy_session.cc" />
  <item id="spdy_session_control" added_in_milestone="66" content_hash_code="01c6f3f0" os_list="linux,windows,chromeos,android" file_path="net/spdy/spdy_session.cc" />
diff --git a/ui/accessibility/ax_computed_node_data.cc b/ui/accessibility/ax_computed_node_data.cc
index f2b7571..1629f084 100644
--- a/ui/accessibility/ax_computed_node_data.cc
+++ b/ui/accessibility/ax_computed_node_data.cc
@@ -489,6 +489,7 @@
       // The accessible name is not displayed directly inside the node but is
       // visible via e.g. a tooltip.
       case ax::mojom::NameFrom::kTitle:
+      case ax::mojom::NameFrom::kPopoverAttribute:
         return std::string();
 
       case ax::mojom::NameFrom::kContents:
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc
index f6e87799..0a533379 100644
--- a/ui/accessibility/ax_enum_util.cc
+++ b/ui/accessibility/ax_enum_util.cc
@@ -2316,6 +2316,8 @@
       return "relatedElement";
     case ax::mojom::NameFrom::kTitle:
       return "title";
+    case ax::mojom::NameFrom::kPopoverAttribute:
+      return "popoverAttribute";
     case ax::mojom::NameFrom::kValue:
       return "value";
   }
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom
index 8811e81..fb82326d 100644
--- a/ui/accessibility/ax_enums.mojom
+++ b/ui/accessibility/ax_enums.mojom
@@ -1252,6 +1252,10 @@
 
   // The name comes from the value attribute, such as in a button element.
   kValue,
+
+  // The name comes from a tooltip-style popover (aka hint popover), where the
+  // contents could be distilled to a plain text string.
+  kPopoverAttribute,
 };
 
 // The source of the accessible description. Used by some screen readers
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc
index 7e4d2261..5aa7a6c 100644
--- a/ui/accessibility/ax_role_properties.cc
+++ b/ui/accessibility/ax_role_properties.cc
@@ -1130,4 +1130,23 @@
   }
 }
 
+bool IsPlainContentElement(ax::mojom::Role role) {
+  switch (role) {
+    case ax::mojom::Role::kInlineTextBox:
+    case ax::mojom::Role::kLineBreak:
+    case ax::mojom::Role::kStaticText:
+    case ax::mojom::Role::kCanvas:
+    case ax::mojom::Role::kDocCover:
+    case ax::mojom::Role::kGraphicsSymbol:
+    case ax::mojom::Role::kImage:
+    case ax::mojom::Role::kSvgRoot:
+    case ax::mojom::Role::kGenericContainer:
+    case ax::mojom::Role::kNone:
+    case ax::mojom::Role::kGroup:
+      return true;
+    default:
+      return false;
+  }
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/ax_role_properties.h b/ui/accessibility/ax_role_properties.h
index 51e39d5..73961cc 100644
--- a/ui/accessibility/ax_role_properties.h
+++ b/ui/accessibility/ax_role_properties.h
@@ -264,6 +264,10 @@
 // Returns true if the provided role supports toggle.
 AX_BASE_EXPORT bool SupportsToggle(const ax::mojom::Role role);
 
+// Returns true if the provided role is one of the roles considered plain
+// elements. Check AXObject::IsPlainContent()
+AX_BASE_EXPORT bool IsPlainContentElement(const ax::mojom::Role role);
+
 }  // namespace ui
 
 #endif  // UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
index 0220b49..5b1d469 100644
--- a/ui/accessibility/ax_tree.cc
+++ b/ui/accessibility/ax_tree.cc
@@ -1882,6 +1882,14 @@
   }
 }
 
+void AXTree::NotifyChildTreeConnectionChanged(AXNode* node,
+                                              AXTree* child_tree) {
+  DCHECK(node->tree() == this);
+  for (AXTreeObserver& observer : observers_) {
+    observer.OnChildTreeConnectionChanged(node);
+  }
+}
+
 void AXTree::NotifyNodeAttributesWillChange(
     AXNode* node,
     AXTreeUpdateState& update_state,
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h
index 085bf7e1..bc7d081 100644
--- a/ui/accessibility/ax_tree.h
+++ b/ui/accessibility/ax_tree.h
@@ -257,6 +257,8 @@
   // same tree.
   void NotifyTreeManagerWillBeRemoved(AXTreeID previous_tree_id);
 
+  void NotifyChildTreeConnectionChanged(AXNode* node, AXTree* child_tree);
+
  private:
   friend class ScopedTreeUpdateInProgressStateSetter;
   friend class AXTableInfoTest;
diff --git a/ui/accessibility/ax_tree_manager.cc b/ui/accessibility/ax_tree_manager.cc
index 0eac978..9e0b403 100644
--- a/ui/accessibility/ax_tree_manager.cc
+++ b/ui/accessibility/ax_tree_manager.cc
@@ -367,6 +367,7 @@
   }
   connected_to_parent_tree_node_ = true;
 
+  parent->tree()->NotifyChildTreeConnectionChanged(parent, ax_tree_.get());
   UpdateAttributesOnParent(parent);
   AXTreeManager* parent_manager = parent->GetManager();
   parent = parent_manager->RetargetForEvents(
diff --git a/ui/accessibility/ax_tree_observer.h b/ui/accessibility/ax_tree_observer.h
index 79610d4..e050197 100644
--- a/ui/accessibility/ax_tree_observer.h
+++ b/ui/accessibility/ax_tree_observer.h
@@ -137,6 +137,10 @@
   // updating.
   virtual void OnNodeChanged(AXTree* tree, AXNode* node) {}
 
+  // Called when a child tree hosted by `host_node` is connected or
+  // disconnected.
+  virtual void OnChildTreeConnectionChanged(AXNode* host_node) {}
+
   // Called just before a tree manager is removed from the AXTreeManagerMap.
   //
   // Why is this needed?
diff --git a/ui/events/event_processor_unittest.cc b/ui/events/event_processor_unittest.cc
index 0dad1d1..36866eb 100644
--- a/ui/events/event_processor_unittest.cc
+++ b/ui/events/event_processor_unittest.cc
@@ -503,7 +503,7 @@
 
  private:
   DestroyTarget destroy_target_;
-  TestEventTarget* root_;
+  raw_ptr<TestEventTarget> root_;
   std::unique_ptr<TestEventProcessor> processor_;
 };
 
diff --git a/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
index f401423..a5b7a61 100644
--- a/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
@@ -357,33 +357,27 @@
 // Test fixture.
 class TabletEventConverterEvdevTest : public testing::Test {
  public:
-  TabletEventConverterEvdevTest() = default;
+  TabletEventConverterEvdevTest()
+      : cursor_(std::make_unique<ui::MockTabletCursorEvdev>()),
+        device_manager_(ui::CreateDeviceManagerForTest()),
+        keyboard_layout_engine_(
+            std::make_unique<ui::StubKeyboardLayoutEngine>()),
+        event_factory_(ui::CreateEventFactoryEvdevForTest(
+            cursor_.get(),
+            device_manager_.get(),
+            keyboard_layout_engine_.get(),
+            base::BindRepeating(
+                &TabletEventConverterEvdevTest::DispatchEventForTest,
+                base::Unretained(this)))),
+        dispatcher_(
+            ui::CreateDeviceEventDispatcherEvdevForTest(event_factory_.get())),
+        test_clock_(std::make_unique<ui::test::ScopedEventTestTickClock>()) {}
 
   TabletEventConverterEvdevTest(const TabletEventConverterEvdevTest&) = delete;
   TabletEventConverterEvdevTest& operator=(
       const TabletEventConverterEvdevTest&) = delete;
 
-  // Overridden from testing::Test:
-  void SetUp() override {
-    cursor_ = std::make_unique<ui::MockTabletCursorEvdev>();
-    device_manager_ = ui::CreateDeviceManagerForTest();
-    keyboard_layout_engine_ = std::make_unique<ui::StubKeyboardLayoutEngine>();
-    event_factory_ = ui::CreateEventFactoryEvdevForTest(
-        cursor_.get(), device_manager_.get(), keyboard_layout_engine_.get(),
-        base::BindRepeating(
-            &TabletEventConverterEvdevTest::DispatchEventForTest,
-            base::Unretained(this)));
-    dispatcher_ =
-        ui::CreateDeviceEventDispatcherEvdevForTest(event_factory_.get());
-
-    test_clock_ = std::make_unique<ui::test::ScopedEventTestTickClock>();
-  }
-
-  void TearDown() override {
-    cursor_.reset();
-  }
-
-  ui::MockTabletEventConverterEvdev* CreateDevice(
+  std::unique_ptr<ui::MockTabletEventConverterEvdev> CreateDevice(
       const ui::DeviceCapabilities& caps) {
     // Set up pipe to satisfy message pump (unused).
     int evdev_io[2];
@@ -394,7 +388,7 @@
 
     ui::EventDeviceInfo devinfo;
     CapabilitiesToDeviceInfo(caps, &devinfo);
-    return new ui::MockTabletEventConverterEvdev(
+    return std::make_unique<ui::MockTabletEventConverterEvdev>(
         std::move(events_in), base::FilePath(kTestDevicePath), cursor_.get(),
         devinfo, dispatcher_.get());
   }
@@ -430,12 +424,12 @@
   }
 
  private:
-  std::unique_ptr<ui::MockTabletCursorEvdev> cursor_;
-  std::unique_ptr<ui::DeviceManager> device_manager_;
-  std::unique_ptr<ui::KeyboardLayoutEngine> keyboard_layout_engine_;
-  std::unique_ptr<ui::EventFactoryEvdev> event_factory_;
-  std::unique_ptr<ui::DeviceEventDispatcherEvdev> dispatcher_;
-  std::unique_ptr<ui::test::ScopedEventTestTickClock> test_clock_;
+  const std::unique_ptr<ui::MockTabletCursorEvdev> cursor_;
+  const std::unique_ptr<ui::DeviceManager> device_manager_;
+  const std::unique_ptr<ui::KeyboardLayoutEngine> keyboard_layout_engine_;
+  const std::unique_ptr<ui::EventFactoryEvdev> event_factory_;
+  const std::unique_ptr<ui::DeviceEventDispatcherEvdev> dispatcher_;
+  const std::unique_ptr<ui::test::ScopedEventTestTickClock> test_clock_;
 
   std::vector<std::unique_ptr<ui::Event>> dispatched_events_;
 
@@ -447,7 +441,7 @@
 // Uses real data captured from Wacom Intuos 5 Pen
 TEST_F(TabletEventConverterEvdevTest, MoveTopLeft) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
+      CreateDevice(kWacomIntuos5SPen);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
@@ -479,7 +473,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, MoveTopRight) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
+      CreateDevice(kWacomIntuos5SPen);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
@@ -514,7 +508,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, MoveBottomLeft) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
+      CreateDevice(kWacomIntuos5SPen);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
@@ -549,7 +543,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, MoveBottomRight) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
+      CreateDevice(kWacomIntuos5SPen);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
@@ -587,7 +581,7 @@
 TEST_F(TabletEventConverterEvdevTest,
        ShouldDisableMouseWarpingToOtherDisplays) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
+      CreateDevice(kWacomIntuos5SPen);
 
   // Move to bottom right, even though the end position doesn't matter for this
   // test, as long as it is a move.
@@ -623,7 +617,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Tap) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
+      CreateDevice(kWacomIntuos5SPen);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 15456},
@@ -682,7 +676,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, StylusButtonPress) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
+      CreateDevice(kWacomIntuos5SPen);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
@@ -735,7 +729,7 @@
 // Should only get an event if BTN_TOOL received
 TEST_F(TabletEventConverterEvdevTest, CheckStylusFiltering) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(kWacomIntuos5SPen));
+      CreateDevice(kWacomIntuos5SPen);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 0},
@@ -750,7 +744,7 @@
 // for digitizer pen with only one side button
 TEST_F(TabletEventConverterEvdevTest, DigitizerPenOneSideButtonPress) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(EpsonBrightLink1430));
+      CreateDevice(EpsonBrightLink1430);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_DISTANCE, 63},
@@ -807,7 +801,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, NoButtonPressedKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomOnePenTabletMediumCTC6110WL));
+      CreateDevice(WacomOnePenTabletMediumCTC6110WL);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
@@ -848,7 +842,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, SideEraserAlwaysPressedKernel5) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomOnePenTabletMediumCTC6110WL));
+      CreateDevice(WacomOnePenTabletMediumCTC6110WL);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_RUBBER, 1},
@@ -891,7 +885,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, SideEraserAlwaysPressedKernel6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomOnePenTabletMediumCTC6110WL));
+      CreateDevice(WacomOnePenTabletMediumCTC6110WL);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_RUBBER, 1},
@@ -930,7 +924,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, SideEraserReleasedWhileTouchingKernel5) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomOnePenTabletMediumCTC6110WL));
+      CreateDevice(WacomOnePenTabletMediumCTC6110WL);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_RUBBER, 1},
@@ -982,7 +976,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, SideEraserReleasedWhileTouchingKernel6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomOnePenTabletMediumCTC6110WL));
+      CreateDevice(WacomOnePenTabletMediumCTC6110WL);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_RUBBER, 1},
@@ -1030,7 +1024,7 @@
 TEST_F(TabletEventConverterEvdevTest,
        SideEraserPressedWhileTouchingKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomOnePenTabletMediumCTC6110WL));
+      CreateDevice(WacomOnePenTabletMediumCTC6110WL);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
@@ -1085,7 +1079,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, TailEraserKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomIntuousProMPenPTH660));
+      CreateDevice(WacomIntuousProMPenPTH660);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 21040},
@@ -1133,7 +1127,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Button1AlwaysPressedKernel5) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(XPPenStarG640));
+      CreateDevice(XPPenStarG640);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_MSC, MSC_SCAN, 0xd0044},
@@ -1180,7 +1174,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Button1AlwaysPressedKernel6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(XPPenStarG640));
+      CreateDevice(XPPenStarG640);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
@@ -1229,7 +1223,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Button1ReleasedWhileTouchingKernel5) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(XPPenStarG640));
+      CreateDevice(XPPenStarG640);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_STYLUS, 1},  // Event 0
@@ -1294,7 +1288,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Button1ReleasedWhileTouchingKernel6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(XPPenStarG640));
+      CreateDevice(XPPenStarG640);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
@@ -1363,7 +1357,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Button1PressedWhileTouchingKernel5) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(XPPenStarG640));
+      CreateDevice(XPPenStarG640);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
@@ -1416,7 +1410,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Button1PressedWhileTouchingKernel6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(XPPenStarG640));
+      CreateDevice(XPPenStarG640);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1},
@@ -1485,7 +1479,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Button2AlwaysPressedKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomOneByWacomSPenCTC472));
+      CreateDevice(WacomOneByWacomSPenCTC472);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 8430},
@@ -1542,7 +1536,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Button2ReleasedWhileTouchingKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomOneByWacomSPenCTC472));
+      CreateDevice(WacomOneByWacomSPenCTC472);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 9826},
@@ -1600,7 +1594,7 @@
 
 TEST_F(TabletEventConverterEvdevTest, Button2PressedWhileTouchingKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomOneByWacomSPenCTC472));
+      CreateDevice(WacomOneByWacomSPenCTC472);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 9886},
@@ -1654,7 +1648,7 @@
 TEST_F(TabletEventConverterEvdevTest,
        Button1AlwaysPressedWithTailEraserKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomIntuousProMPenPTH660));
+      CreateDevice(WacomIntuousProMPenPTH660);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 38777},
@@ -1717,7 +1711,7 @@
 TEST_F(TabletEventConverterEvdevTest,
        Button1ReleasedWhileTouchingWithTailEraserKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomIntuousProMPenPTH660));
+      CreateDevice(WacomIntuousProMPenPTH660);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 34762},
@@ -1782,7 +1776,7 @@
 TEST_F(TabletEventConverterEvdevTest,
        Button1PressedWhileTouchingWithTailEraserKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomIntuousProMPenPTH660));
+      CreateDevice(WacomIntuousProMPenPTH660);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 35858},
@@ -1843,7 +1837,7 @@
 TEST_F(TabletEventConverterEvdevTest,
        Button2AlwaysPressedWithTailEraserKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomIntuousProMPenPTH660));
+      CreateDevice(WacomIntuousProMPenPTH660);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 37215},
@@ -1908,7 +1902,7 @@
 TEST_F(TabletEventConverterEvdevTest,
        Button2ReleasedWhileTouchingWithTailEraserKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomIntuousProMPenPTH660));
+      CreateDevice(WacomIntuousProMPenPTH660);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 37450},
@@ -1974,7 +1968,7 @@
 TEST_F(TabletEventConverterEvdevTest,
        Button2PressedWhileTouchingWithTailEraserKernel5And6) {
   std::unique_ptr<ui::MockTabletEventConverterEvdev> dev =
-      base::WrapUnique(CreateDevice(WacomIntuousProMPenPTH660));
+      CreateDevice(WacomIntuousProMPenPTH660);
 
   struct input_event mock_kernel_queue[] = {
       {{0, 0}, EV_ABS, ABS_X, 38408},
diff --git a/ui/gfx/color_conversion_sk_filter_cache.cc b/ui/gfx/color_conversion_sk_filter_cache.cc
index a3811852..aa504ce 100644
--- a/ui/gfx/color_conversion_sk_filter_cache.cc
+++ b/ui/gfx/color_conversion_sk_filter_cache.cc
@@ -15,10 +15,46 @@
 #include "third_party/skia/include/core/SkSurface.h"
 #include "third_party/skia/include/gpu/GpuTypes.h"
 #include "third_party/skia/include/gpu/GrDirectContext.h"
+#include "third_party/skia/include/private/SkGainmapInfo.h"
+#include "third_party/skia/include/private/SkGainmapShader.h"
 #include "ui/gfx/color_transform.h"
 
 namespace gfx {
 
+namespace {
+
+// Allocate an SkSurface to be used to create the tonemapped result.
+static sk_sp<SkSurface> MakeSurfaceForResult(SkImageInfo image_info,
+                                             GrDirectContext* context) {
+  sk_sp<SkSurface> surface;
+  if (context) {
+    // TODO(https://crbug.com/1286088): Consider adding mipmap support here.
+    surface =
+        SkSurface::MakeRenderTarget(context, skgpu::Budgeted::kNo, image_info,
+                                    /*sampleCount=*/0, kTopLeft_GrSurfaceOrigin,
+                                    /*surfaceProps=*/nullptr,
+                                    /*shouldCreateWithMips=*/false);
+    // It is not guaranteed that kRGBA_F16_SkColorType is renderable. If we fail
+    // to create an SkSurface with that color type, fall back to
+    // kN32_SkColorType.
+    if (!surface) {
+      DLOG(ERROR) << "Falling back to tone mapped 8-bit surface.";
+      image_info = image_info.makeColorType(kN32_SkColorType);
+      surface = SkSurface::MakeRenderTarget(
+          context, skgpu::Budgeted::kNo, image_info,
+          /*sampleCount=*/0, kTopLeft_GrSurfaceOrigin,
+          /*surfaceProps=*/nullptr,
+          /*shouldCreateWithMips=*/false);
+    }
+  } else {
+    surface = SkSurface::MakeRaster(image_info, image_info.minRowBytes(),
+                                    /*surfaceProps=*/nullptr);
+  }
+  return surface;
+}
+
+}  // namespace
+
 ColorConversionSkFilterCache::ColorConversionSkFilterCache() = default;
 ColorConversionSkFilterCache::~ColorConversionSkFilterCache() = default;
 
@@ -93,6 +129,68 @@
       src, dst, resource_offset, resource_multiplier, options));
 }
 
+sk_sp<SkImage> ColorConversionSkFilterCache::ApplyGainmap(
+    sk_sp<SkImage> base_image,
+    sk_sp<SkImage> gainmap_image,
+    const SkGainmapInfo& gainmap_info,
+    float dst_max_luminance_relative,
+    GrDirectContext* context) {
+  DCHECK_EQ(base_image->isTextureBacked(), gainmap_image->isTextureBacked());
+  DCHECK_EQ(!!context, base_image->isTextureBacked());
+
+  // If `gainmap_image` will not be applied, then return `base_image` directly.
+  switch (gainmap_info.fBaseImageType) {
+    case SkGainmapInfo::BaseImageType::kSDR:
+      if (dst_max_luminance_relative <= gainmap_info.fDisplayRatioSdr) {
+        return base_image;
+      }
+      break;
+    case SkGainmapInfo::BaseImageType::kHDR:
+      if (dst_max_luminance_relative >= gainmap_info.fDisplayRatioHdr) {
+        return base_image;
+      }
+      break;
+  }
+
+  // The output surface will be in a linearized version of the input
+  // base_image's color space.
+  sk_sp<SkColorSpace> surface_color_space = base_image->refColorSpace();
+  if (surface_color_space) {
+    surface_color_space = surface_color_space->makeLinearGamma();
+  } else {
+    surface_color_space = SkColorSpace::MakeSRGBLinear();
+  }
+  SkImageInfo surface_info =
+      SkImageInfo::Make(base_image->dimensions(),
+                        SkColorInfo(kRGBA_F16_SkColorType, kPremul_SkAlphaType,
+                                    surface_color_space));
+
+  // Create the surface to render the gainmap shader to.
+  sk_sp<SkSurface> surface = MakeSurfaceForResult(surface_info, context);
+  if (!surface) {
+    LOG(ERROR) << "Failed to create SkSurface for applying gainmap.";
+    return base_image;
+  }
+
+  // Render the gainmap shader to the surface
+  SkRect image_rect = SkRect::MakeSize(SkSize::Make(base_image->dimensions()));
+  SkRect gainmap_rect =
+      SkRect::MakeSize(SkSize::Make(gainmap_image->dimensions()));
+  SkRect surface_rect =
+      SkRect::MakeSize(SkSize::Make(surface_info.dimensions()));
+  sk_sp<SkShader> shader = SkGainmapShader::Make(
+      base_image, image_rect, SkSamplingOptions(), gainmap_image, gainmap_rect,
+      SkSamplingOptions(), gainmap_info, surface_rect,
+      dst_max_luminance_relative, surface_color_space);
+  DCHECK(shader);
+  SkPaint paint;
+  paint.setShader(shader);
+  surface->getCanvas()->drawRect(surface_rect, paint);
+
+  // Return the surface's contents as an SkImage.
+  return surface->makeImageSnapshot();
+}
+
 sk_sp<SkImage> ColorConversionSkFilterCache::ConvertImage(
     sk_sp<SkImage> image,
     sk_sp<SkColorSpace> target_color_space,
@@ -123,30 +221,7 @@
       SkImageInfo::Make(image->dimensions(),
                         SkColorInfo(kRGBA_F16_SkColorType, kPremul_SkAlphaType,
                                     image_sk_color_space));
-  sk_sp<SkSurface> surface;
-  if (context) {
-    // TODO(https://crbug.com/1286088): Consider adding mipmap support here.
-    surface =
-        SkSurface::MakeRenderTarget(context, skgpu::Budgeted::kNo, image_info,
-                                    /*sampleCount=*/0, kTopLeft_GrSurfaceOrigin,
-                                    /*surfaceProps=*/nullptr,
-                                    /*shouldCreateWithMips=*/false);
-    // It is not guaranteed that kRGBA_F16_SkColorType is renderable. If we fail
-    // to create an SkSurface with that color type, fall back to
-    // kN32_SkColorType.
-    if (!surface) {
-      DLOG(ERROR) << "Falling back to tone mapped 8-bit surface.";
-      image_info = image_info.makeColorType(kN32_SkColorType);
-      surface = SkSurface::MakeRenderTarget(
-          context, skgpu::Budgeted::kNo, image_info,
-          /*sampleCount=*/0, kTopLeft_GrSurfaceOrigin,
-          /*surfaceProps=*/nullptr,
-          /*shouldCreateWithMips=*/false);
-    }
-  } else {
-    surface = SkSurface::MakeRaster(image_info, image_info.minRowBytes(),
-                                    /*surfaceProps=*/nullptr);
-  }
+  sk_sp<SkSurface> surface = MakeSurfaceForResult(image_info, context);
   if (!surface) {
     DLOG(ERROR) << "Failed to create SkSurface color conversion.";
     return nullptr;
@@ -163,8 +238,7 @@
   SkSamplingOptions sampling_options(SkFilterMode::kNearest);
   surface->getCanvas()->drawImage(image,
                                   /*x=*/0, /*y=*/0, sampling_options, &paint);
-  return surface->makeImageSnapshot()->reinterpretColorSpace(
-      target_color_space);
+  return surface->makeImageSnapshot();
 }
 
 }  // namespace gfx
diff --git a/ui/gfx/color_conversion_sk_filter_cache.h b/ui/gfx/color_conversion_sk_filter_cache.h
index 2c9d8834..9f5184d 100644
--- a/ui/gfx/color_conversion_sk_filter_cache.h
+++ b/ui/gfx/color_conversion_sk_filter_cache.h
@@ -17,6 +17,7 @@
 class SkImage;
 class SkColorFilter;
 class SkRuntimeEffect;
+struct SkGainmapInfo;
 
 namespace gfx {
 
@@ -59,6 +60,20 @@
                               bool enable_tone_mapping,
                               GrDirectContext* context);
 
+  // Apply the gainmap in `gainmap_image` to `base_image`, using the parameters
+  // in `gainmap_info` and `dst_max_luminance_relative`, and return the
+  // resulting image.
+  // * If `context` is non-nullptr, then `base_image` and `gainmap_image` must
+  //   be texture-backed and on `context`, and the result will be texture backed
+  //   and on `context`.
+  // * If `context` is nullptr, then the arguments should be bitmaps, and the
+  //   result will be a bitmap.
+  sk_sp<SkImage> ApplyGainmap(sk_sp<SkImage> base_image,
+                              sk_sp<SkImage> gainmap_image,
+                              const SkGainmapInfo& gainmap_info,
+                              float dst_max_luminance_relative,
+                              GrDirectContext* context);
+
  public:
   struct Key {
     Key(const gfx::ColorSpace& src,
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 8a1142f0..44ab549 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -1177,6 +1177,7 @@
     "bubble/bubble_dialog_model_host_unittest.cc",
     "bubble/bubble_frame_view_unittest.cc",
     "bubble/info_bubble_unittest.cc",
+    "bubble/tooltip_icon_unittest.cc",
     "controls/base_control_test_widget.cc",
     "controls/base_control_test_widget.h",
     "controls/button/button_unittest.cc",
diff --git a/ui/views/background.cc b/ui/views/background.cc
index 01daf6a..4854ff1 100644
--- a/ui/views/background.cc
+++ b/ui/views/background.cc
@@ -44,9 +44,17 @@
   BaseRoundedRectBackground(float top_radius,
                             float bottom_radius,
                             int for_border_thickness)
-      : top_radius_(top_radius),
-        bottom_radius_(bottom_radius),
-        half_thickness_(for_border_thickness / 2.0f) {}
+      : BaseRoundedRectBackground(
+            Radii{
+                .top_left = top_radius,
+                .top_right = top_radius,
+                .bottom_right = bottom_radius,
+                .bottom_left = bottom_radius,
+            },
+            for_border_thickness) {}
+
+  BaseRoundedRectBackground(const Radii& radii, int for_border_thickness)
+      : radii_(radii), half_thickness_(for_border_thickness / 2.0f) {}
 
   BaseRoundedRectBackground(const BaseRoundedRectBackground&) = delete;
   BaseRoundedRectBackground& operator=(const BaseRoundedRectBackground&) =
@@ -56,9 +64,10 @@
     gfx::Rect rect(view->GetLocalBounds());
     rect.Inset(half_thickness_);
     SkPath path;
-    SkScalar radii[8] = {top_radius_,    top_radius_,    top_radius_,
-                         top_radius_,    bottom_radius_, bottom_radius_,
-                         bottom_radius_, bottom_radius_};
+    SkScalar radii[8] = {radii_.top_left,     radii_.top_left,
+                         radii_.top_right,    radii_.top_right,
+                         radii_.bottom_right, radii_.bottom_right,
+                         radii_.bottom_left,  radii_.bottom_left};
     path.addRoundRect(gfx::RectToSkRect(rect), radii);
 
     cc::PaintFlags flags;
@@ -69,8 +78,7 @@
   }
 
  private:
-  const float top_radius_;
-  const float bottom_radius_;
+  const Radii radii_;
   const float half_thickness_;
 };
 
@@ -147,9 +155,17 @@
                               float top_radius,
                               float bottom_radius,
                               int for_border_thickness)
-      : BaseRoundedRectBackground(top_radius,
-                                  bottom_radius,
-                                  for_border_thickness),
+      : ThemedRoundedRectBackground(color_id,
+                                    Radii{.top_left = top_radius,
+                                          .top_right = top_radius,
+                                          .bottom_right = bottom_radius,
+                                          .bottom_left = bottom_radius},
+                                    for_border_thickness) {}
+
+  ThemedRoundedRectBackground(ui::ColorId color_id,
+                              const Radii& radii,
+                              int for_border_thickness)
+      : BaseRoundedRectBackground(radii, for_border_thickness),
         color_id_(color_id) {}
 
   ThemedRoundedRectBackground(const ThemedRoundedRectBackground&) = delete;
@@ -226,6 +242,14 @@
       color_id, top_radius, bottom_radius, for_border_thickness);
 }
 
+std::unique_ptr<Background> CreateThemedRoundedRectBackground(
+    ui::ColorId color_id,
+    const Radii& radii,
+    int for_border_thickness) {
+  return std::make_unique<ThemedRoundedRectBackground>(color_id, radii,
+                                                       for_border_thickness);
+}
+
 std::unique_ptr<Background> CreateThemedVectorIconBackground(
     const ui::ThemedVectorIcon& icon) {
   return std::make_unique<ThemedVectorIconBackground>(icon);
diff --git a/ui/views/background.h b/ui/views/background.h
index 4af2924..611f8b45 100644
--- a/ui/views/background.h
+++ b/ui/views/background.h
@@ -71,6 +71,13 @@
   SkColor color_ = gfx::kPlaceholderColor;
 };
 
+struct VIEWS_EXPORT Radii {
+  float top_left;
+  float top_right;
+  float bottom_right;
+  float bottom_left;
+};
+
 // Creates a background that fills the canvas in the specified color.
 VIEWS_EXPORT std::unique_ptr<Background> CreateSolidBackground(SkColor color);
 
@@ -98,6 +105,12 @@
     float bottom_radius,
     int for_border_thickness);
 
+// Same as above except each corner radius can be different and customized.
+VIEWS_EXPORT std::unique_ptr<Background> CreateThemedRoundedRectBackground(
+    ui::ColorId color_id,
+    const Radii& radii,
+    int for_border_thickness);
+
 // Creates a background that fills the canvas in the color specified by the
 // view's ColorProvider and the given color identifier.
 VIEWS_EXPORT std::unique_ptr<Background> CreateThemedSolidBackground(
diff --git a/ui/views/bubble/tooltip_icon.cc b/ui/views/bubble/tooltip_icon.cc
index 93b365cf..b2de59b 100644
--- a/ui/views/bubble/tooltip_icon.cc
+++ b/ui/views/bubble/tooltip_icon.cc
@@ -9,7 +9,6 @@
 #include "build/build_config.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/accessibility/ax_enums.mojom.h"
-#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_provider.h"
@@ -35,6 +34,14 @@
   SetBorder(CreateEmptyBorder(
       LayoutProvider::Get()->GetInsetsMetric(INSETS_VECTOR_IMAGE_BUTTON)));
   InstallCircleHighlightPathGenerator(this);
+
+  // The tooltip icon, despite visually being an icon with no text, actually
+  // opens a bubble whenever the user mouses over it or focuses it, so it's
+  // essentially a text control that hides itself when not in view without
+  // altering the bubble's layout when shown. As such, have it behave like
+  // static text for screenreader users, since that's the role it serves here
+  // anyway.
+  SetAccessibilityProperties(ax::mojom::Role::kStaticText, tooltip_);
 }
 
 TooltipIcon::~TooltipIcon() {
@@ -77,17 +84,6 @@
   }
 }
 
-void TooltipIcon::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  // The tooltip icon, despite visually being an icon with no text, actually
-  // opens a bubble whenever the user mouses over it or focuses it, so it's
-  // essentially a text control that hides itself when not in view without
-  // altering the bubble's layout when shown. As such, have it behave like
-  // static text for screenreader users, since that's the role it serves here
-  // anyway.
-  node_data->role = ax::mojom::Role::kStaticText;
-  node_data->SetNameChecked(tooltip_);
-}
-
 void TooltipIcon::OnThemeChanged() {
   ImageView::OnThemeChanged();
   SetDrawAsHovered(false);
diff --git a/ui/views/bubble/tooltip_icon.h b/ui/views/bubble/tooltip_icon.h
index 82dfb70a..49f9f7d3 100644
--- a/ui/views/bubble/tooltip_icon.h
+++ b/ui/views/bubble/tooltip_icon.h
@@ -53,7 +53,6 @@
   void OnFocus() override;
   void OnBlur() override;
   void OnGestureEvent(ui::GestureEvent* event) override;
-  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void OnThemeChanged() override;
 
   // MouseWatcherListener:
diff --git a/ui/views/bubble/tooltip_icon_unittest.cc b/ui/views/bubble/tooltip_icon_unittest.cc
new file mode 100644
index 0000000..2b9e2a5
--- /dev/null
+++ b/ui/views/bubble/tooltip_icon_unittest.cc
@@ -0,0 +1,29 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/bubble/tooltip_icon.h"
+
+#include <memory>
+
+#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace views {
+
+using TooltipIconTest = views::ViewsTestBase;
+
+TEST_F(TooltipIconTest, AccessibleRoleAndName) {
+  std::u16string tooltip_text = u"Tooltip text";
+  std::unique_ptr<views::TooltipIcon> tooltip =
+      std::make_unique<views::TooltipIcon>(tooltip_text, 12);
+  ui::AXNodeData data;
+  tooltip->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.role, ax::mojom::Role::kStaticText);
+  EXPECT_EQ(data.GetString16Attribute(ax::mojom::StringAttribute::kName),
+            tooltip_text);
+  EXPECT_EQ(tooltip->GetAccessibleName(), tooltip_text);
+}
+
+}  // namespace views
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index 84321f9..f08d859 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -180,6 +180,11 @@
     views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(),
                                                   GetCornerRadius());
   }
+
+  // `ax::mojom::Role::kComboBox` is for UI elements with a dropdown and
+  // an editable text field, which `views::Combobox` does not have. Use
+  // `ax::mojom::Role::kPopUpButton` to match an HTML <select> element.
+  SetAccessibilityProperties(ax::mojom::Role::kPopUpButton);
 }
 
 Combobox::~Combobox() {
@@ -482,17 +487,13 @@
 }
 
 void Combobox::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  // ax::mojom::Role::kComboBox is for UI elements with a dropdown and
-  // an editable text field, which views::Combobox does not have. Use
-  // ax::mojom::Role::kPopUpButton to match an HTML <select> element.
-  node_data->role = ax::mojom::Role::kPopUpButton;
+  View::GetAccessibleNodeData(node_data);
   if (menu_runner_) {
     node_data->AddState(ax::mojom::State::kExpanded);
   } else {
     node_data->AddState(ax::mojom::State::kCollapsed);
   }
 
-  node_data->SetName(GetAccessibleName());
   node_data->SetValue(model_->GetItemAt(selected_index_.value()));
   if (GetEnabled()) {
     node_data->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kOpen);
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc
index e1f82da..dd11a329 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.cc
+++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -89,6 +89,7 @@
         ButtonController::NotifyAction::kOnPress);
 
     ConfigureComboboxButtonInkDrop(this);
+    SetAccessibilityProperties(ax::mojom::Role::kButton);
   }
   Arrow(const Arrow&) = delete;
   Arrow& operator=(const Arrow&) = delete;
@@ -113,8 +114,7 @@
   }
 
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
-    node_data->role = ax::mojom::Role::kButton;
-    node_data->SetName(GetAccessibleName());
+    Button::GetAccessibleNodeData(node_data);
     node_data->SetHasPopup(ax::mojom::HasPopup::kMenu);
     if (GetEnabled()) {
       node_data->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kOpen);
@@ -390,6 +390,7 @@
   }
 
   SetLayoutManager(std::make_unique<FillLayout>());
+  SetAccessibilityProperties(ax::mojom::Role::kComboBoxGrouping);
 }
 
 EditableCombobox::~EditableCombobox() {
@@ -455,9 +456,7 @@
 }
 
 void EditableCombobox::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  node_data->role = ax::mojom::Role::kComboBoxGrouping;
-
-  node_data->SetName(textfield_->GetAccessibleName());
+  View::GetAccessibleNodeData(node_data);
   node_data->SetValue(GetText());
 }
 
diff --git a/ui/views/controls/editable_combobox/editable_combobox.h b/ui/views/controls/editable_combobox/editable_combobox.h
index c2dc4e2..054ef76 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.h
+++ b/ui/views/controls/editable_combobox/editable_combobox.h
@@ -134,6 +134,8 @@
   friend class EditableComboboxTest;
   friend class EditablePasswordComboboxTest;
   friend class test::InteractionTestUtilSimulatorViews;
+  FRIEND_TEST_ALL_PREFIXES(EditableComboboxTest, AccessibleNameAndRole);
+
   class EditableComboboxMenuModel;
   class EditableComboboxPreTargetHandler;
 
diff --git a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
index 8fe5823..987b4298 100644
--- a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
+++ b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
@@ -887,6 +887,24 @@
   EXPECT_FALSE(IsMenuOpen());
 }
 
+TEST_F(EditableComboboxTest, AccessibleNameAndRole) {
+  InitEditableCombobox();
+
+  ui::AXNodeData data;
+  combobox_->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.role, ax::mojom::Role::kComboBoxGrouping);
+  EXPECT_EQ(data.GetString16Attribute(ax::mojom::StringAttribute::kName),
+            u"abc");
+  EXPECT_EQ(combobox_->GetAccessibleName(), u"abc");
+
+  data = ui::AXNodeData();
+  combobox_->SetAccessibleName(u"New name");
+  combobox_->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.GetString16Attribute(ax::mojom::StringAttribute::kName),
+            u"New name");
+  EXPECT_EQ(combobox_->GetAccessibleName(), u"New name");
+}
+
 using EditableComboboxDefaultTest = ViewsTestBase;
 
 class ConfigurableComboboxModel final : public ui::ComboboxModel {
diff --git a/ui/views/controls/focus_ring.cc b/ui/views/controls/focus_ring.cc
index 72b1907..7db4052 100644
--- a/ui/views/controls/focus_ring.cc
+++ b/ui/views/controls/focus_ring.cc
@@ -12,8 +12,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/notreached.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "ui/accessibility/ax_enums.mojom.h"
-#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/theme_provider.h"
 #include "ui/base/ui_base_features.h"
@@ -25,6 +23,7 @@
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/rect_f.h"
 #include "ui/gfx/geometry/skia_conversions.h"
+#include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/cascading_property.h"
 #include "ui/views/controls/focusable_border.h"
 #include "ui/views/controls/highlight_path_generator.h"
@@ -286,17 +285,6 @@
   return RingRectFromPathRect(rbounds);
 }
 
-void FocusRing::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  // Mark the focus ring in the accessibility tree as ignored.
-  // Marking it as invisible keeps it in the accessibility tree with a "hidden"
-  // attribute where assistive technologies can still find it. Marking it as
-  // ignored causes it to be removed from the accessibility tree. This also
-  // ensures that when a non-used control, such as the minimize button in a
-  // JavaScript alert, is marked as ignored, that control's parent will not
-  // have any "invisible" FocusRing children.
-  node_data->AddState(ax::mojom::State::kIgnored);
-}
-
 void FocusRing::OnThemeChanged() {
   View::OnThemeChanged();
   if (invalid_ || color_id_.has_value())
@@ -314,6 +302,9 @@
 FocusRing::FocusRing() {
   // Don't allow the view to process events.
   SetCanProcessEventsWithinSubtree(false);
+
+  // This should never be included in the accessibility tree.
+  GetViewAccessibility().OverrideIsIgnored(true);
 }
 
 SkPath FocusRing::GetPath() const {
diff --git a/ui/views/controls/focus_ring.h b/ui/views/controls/focus_ring.h
index d00a5c0..01230de 100644
--- a/ui/views/controls/focus_ring.h
+++ b/ui/views/controls/focus_ring.h
@@ -100,7 +100,6 @@
   void ViewHierarchyChanged(
       const ViewHierarchyChangedDetails& details) override;
   void OnPaint(gfx::Canvas* canvas) override;
-  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void OnThemeChanged() override;
 
   // ViewObserver:
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc
index c619e78c..6f46fb1 100644
--- a/ui/views/controls/label.cc
+++ b/ui/views/controls/label.cc
@@ -107,12 +107,14 @@
   if (new_text == GetText())
     return;
 
-  if (GetAccessibleName().empty() || GetAccessibleName() == GetText()) {
+  std::u16string current_text = GetText();
+  full_text_->SetText(new_text);
+  ClearDisplayText();
+
+  if (GetAccessibleName().empty() || GetAccessibleName() == current_text) {
     SetAccessibleName(new_text);
   }
 
-  full_text_->SetText(new_text);
-  ClearDisplayText();
   OnPropertyChanged(&full_text_ + kLabelText,
                     kPropertyEffectsPreferredSizeChanged);
   stored_selection_range_ = gfx::Range::InvalidRange();
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc
index 36a5ce0..73681817 100644
--- a/ui/views/controls/label_unittest.cc
+++ b/ui/views/controls/label_unittest.cc
@@ -721,6 +721,13 @@
   label()->GetAccessibleNodeData(&node_data);
   EXPECT_EQ(label()->GetText(),
             node_data.GetString16Attribute(ax::mojom::StringAttribute::kName));
+
+  // If the displayed text is the source of the accessible name, and that text
+  // is cleared, the accessible name should also be cleared.
+  label()->SetText(u"");
+  label()->GetAccessibleNodeData(&node_data);
+  EXPECT_EQ(label()->GetText(),
+            node_data.GetString16Attribute(ax::mojom::StringAttribute::kName));
 }
 
 TEST_F(LabelTest, SetTextNotifiesAccessibilityEvent) {
diff --git a/ui/views/controls/link.cc b/ui/views/controls/link.cc
index 3f7e4ce..192ebab1 100644
--- a/ui/views/controls/link.cc
+++ b/ui/views/controls/link.cc
@@ -9,7 +9,6 @@
 #include "base/check.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_enums.mojom.h"
-#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_id.h"
@@ -19,6 +18,7 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/font_list.h"
+#include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/controls/focus_ring.h"
 #include "ui/views/style/platform_style.h"
 
@@ -31,6 +31,10 @@
   enabled_changed_subscription_ = AddEnabledChangedCallback(
       base::BindRepeating(&Link::RecalculateFont, base::Unretained(this)));
 
+  SetAccessibilityProperties(ax::mojom::Role::kLink, title);
+  // Prevent invisible links from being announced by screen reader.
+  GetViewAccessibility().OverrideIsIgnored(title.empty());
+
   // Label() indirectly calls SetText(), but at that point our virtual override
   // will not be reached.  Call it explicitly here to configure focus.
   SetText(GetText());
@@ -151,13 +155,6 @@
           PlatformStyle::kReturnClicksFocusedControl);
 }
 
-void Link::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  Label::GetAccessibleNodeData(node_data);
-  // Prevent invisible links from being announced by screen reader.
-  node_data->role =
-      GetText().empty() ? ax::mojom::Role::kNone : ax::mojom::Role::kLink;
-}
-
 void Link::OnFocus() {
   Label::OnFocus();
   RecalculateFont();
@@ -179,6 +176,8 @@
 
 void Link::SetText(const std::u16string& text) {
   Label::SetText(text);
+  // Prevent invisible links from being announced by screen reader.
+  GetViewAccessibility().OverrideIsIgnored(text.empty());
   ConfigureFocus();
 }
 
diff --git a/ui/views/controls/link.h b/ui/views/controls/link.h
index 35909a1..63101f3 100644
--- a/ui/views/controls/link.h
+++ b/ui/views/controls/link.h
@@ -75,7 +75,6 @@
   bool OnKeyPressed(const ui::KeyEvent& event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
   bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override;
-  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void OnFocus() override;
   void OnBlur() override;
   void SetFontList(const gfx::FontList& font_list) override;
diff --git a/ui/views/controls/link_unittest.cc b/ui/views/controls/link_unittest.cc
index 368df46..f0e8d19 100644
--- a/ui/views/controls/link_unittest.cc
+++ b/ui/views/controls/link_unittest.cc
@@ -16,6 +16,7 @@
 #include "ui/events/base_event_utils.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/strings/grit/ui_strings.h"
+#include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/base_control_test_widget.h"
 #include "ui/views/controls/focus_ring.h"
@@ -135,4 +136,48 @@
   EXPECT_TRUE(views::FocusRing::Get(link())->ShouldPaintForTesting());
 }
 
+TEST_F(LinkTest, AccessibleProperties) {
+  ui::AXNodeData data;
+  link()->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.GetString16Attribute(ax::mojom::StringAttribute::kName),
+            u"TestLink");
+  EXPECT_EQ(link()->GetAccessibleName(), u"TestLink");
+  EXPECT_EQ(data.role, ax::mojom::Role::kLink);
+  EXPECT_FALSE(link()->GetViewAccessibility().IsIgnored());
+
+  // Setting the accessible name to a non-empty string should replace the name
+  // from the link text.
+  data = ui::AXNodeData();
+  std::u16string accessible_name = u"Accessible Name";
+  link()->SetAccessibleName(accessible_name);
+  link()->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.GetString16Attribute(ax::mojom::StringAttribute::kName),
+            accessible_name);
+  EXPECT_EQ(link()->GetAccessibleName(), accessible_name);
+  EXPECT_EQ(data.role, ax::mojom::Role::kLink);
+  EXPECT_FALSE(link()->GetViewAccessibility().IsIgnored());
+
+  // Setting the accessible name to an empty string should cause the link text
+  // to be used as the name.
+  data = ui::AXNodeData();
+  link()->SetAccessibleName(std::u16string());
+  link()->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.GetString16Attribute(ax::mojom::StringAttribute::kName),
+            u"TestLink");
+  EXPECT_EQ(link()->GetAccessibleName(), u"TestLink");
+  EXPECT_EQ(data.role, ax::mojom::Role::kLink);
+  EXPECT_FALSE(link()->GetViewAccessibility().IsIgnored());
+
+  // Setting the link to an empty string without setting a new accessible
+  // name should cause the view to become "ignored" again.
+  data = ui::AXNodeData();
+  link()->SetText(std::u16string());
+  link()->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.GetString16Attribute(ax::mojom::StringAttribute::kName),
+            std::u16string());
+  EXPECT_EQ(link()->GetAccessibleName(), std::u16string());
+  EXPECT_EQ(data.role, ax::mojom::Role::kLink);
+  EXPECT_TRUE(link()->GetViewAccessibility().IsIgnored());
+}
+
 }  // namespace views
diff --git a/ui/views/controls/menu/menu_separator.cc b/ui/views/controls/menu/menu_separator.cc
index be7ca40..8d73681 100644
--- a/ui/views/controls/menu/menu_separator.cc
+++ b/ui/views/controls/menu/menu_separator.cc
@@ -7,7 +7,6 @@
 #include "build/build_config.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/accessibility/ax_enums.mojom.h"
-#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/canvas.h"
 #include "ui/native_theme/native_theme.h"
@@ -19,6 +18,10 @@
 
 namespace views {
 
+MenuSeparator::MenuSeparator(ui::MenuSeparatorType type) : type_(type) {
+  SetAccessibilityProperties(ax::mojom::Role::kSplitter);
+}
+
 void MenuSeparator::OnPaint(gfx::Canvas* canvas) {
   if (type_ == ui::SPACING_SEPARATOR)
     return;
@@ -104,10 +107,6 @@
   OnPropertyChanged(&type_, kPropertyEffectsPreferredSizeChanged);
 }
 
-void MenuSeparator::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  node_data->role = ax::mojom::Role::kSplitter;
-}
-
 BEGIN_METADATA(MenuSeparator, View)
 ADD_PROPERTY_METADATA(ui::MenuSeparatorType, Type)
 END_METADATA
diff --git a/ui/views/controls/menu/menu_separator.h b/ui/views/controls/menu/menu_separator.h
index 81b00eb..fe881ce 100644
--- a/ui/views/controls/menu/menu_separator.h
+++ b/ui/views/controls/menu/menu_separator.h
@@ -17,9 +17,7 @@
   METADATA_HEADER(MenuSeparator);
 
   explicit MenuSeparator(
-      ui::MenuSeparatorType type = ui::MenuSeparatorType::NORMAL_SEPARATOR)
-      : type_(type) {}
-
+      ui::MenuSeparatorType type = ui::MenuSeparatorType::NORMAL_SEPARATOR);
   MenuSeparator(const MenuSeparator&) = delete;
   MenuSeparator& operator=(const MenuSeparator&) = delete;
 
@@ -30,8 +28,6 @@
   ui::MenuSeparatorType GetType() const;
   void SetType(ui::MenuSeparatorType type);
 
-  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
-
  private:
   // The type of the separator.
   ui::MenuSeparatorType type_;
diff --git a/ui/views/controls/menu/menu_separator_unittest.cc b/ui/views/controls/menu/menu_separator_unittest.cc
index 2d497d2..659740bf 100644
--- a/ui/views/controls/menu/menu_separator_unittest.cc
+++ b/ui/views/controls/menu/menu_separator_unittest.cc
@@ -7,6 +7,8 @@
 #include <memory>
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/models/menu_separator_types.h"
 #include "ui/views/controls/menu/menu_config.h"
 #include "ui/views/test/view_metadata_test_utils.h"
@@ -32,4 +34,12 @@
   EXPECT_EQ(config.double_separator_height, separator->height());
 }
 
+TEST_F(MenuSeparatorTest, AccessibleRole) {
+  auto separator = std::make_unique<MenuSeparator>();
+  ui::AXNodeData data;
+  separator->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.role, ax::mojom::Role::kSplitter);
+  EXPECT_EQ(separator->GetAccessibleRole(), ax::mojom::Role::kSplitter);
+}
+
 }  // namespace views
diff --git a/ui/views/controls/progress_bar.cc b/ui/views/controls/progress_bar.cc
index 3e9e2a7..aa40037d 100644
--- a/ui/views/controls/progress_bar.cc
+++ b/ui/views/controls/progress_bar.cc
@@ -62,12 +62,13 @@
     : preferred_height_(preferred_height),
       allow_round_corner_(allow_round_corner) {
   SetFlipCanvasOnPaintForRTLUI(true);
+  SetAccessibilityProperties(ax::mojom::Role::kProgressIndicator);
 }
 
 ProgressBar::~ProgressBar() = default;
 
 void ProgressBar::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  node_data->role = ax::mojom::Role::kProgressIndicator;
+  View::GetAccessibleNodeData(node_data);
   if (IsIndeterminate())
     node_data->RemoveStringAttribute(ax::mojom::StringAttribute::kValue);
   else
diff --git a/ui/views/controls/resize_area.cc b/ui/views/controls/resize_area.cc
index 4614839..e696e902 100644
--- a/ui/views/controls/resize_area.cc
+++ b/ui/views/controls/resize_area.cc
@@ -6,14 +6,15 @@
 
 #include "base/i18n/rtl.h"
 #include "ui/accessibility/ax_enums.mojom.h"
-#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/views/controls/resize_area_delegate.h"
 
 namespace views {
 
-ResizeArea::ResizeArea(ResizeAreaDelegate* delegate) : delegate_(delegate) {}
+ResizeArea::ResizeArea(ResizeAreaDelegate* delegate) : delegate_(delegate) {
+  SetAccessibilityProperties(ax::mojom::Role::kSplitter);
+}
 
 ResizeArea::~ResizeArea() = default;
 
@@ -60,10 +61,6 @@
   ReportResizeAmount(initial_position_, true);
 }
 
-void ResizeArea::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  node_data->role = ax::mojom::Role::kSplitter;
-}
-
 void ResizeArea::ReportResizeAmount(int resize_amount, bool last_update) {
   gfx::Point point(resize_amount, 0);
   View::ConvertPointToScreen(this, &point);
diff --git a/ui/views/controls/resize_area.h b/ui/views/controls/resize_area.h
index 1721c5c..ab26c6f 100644
--- a/ui/views/controls/resize_area.h
+++ b/ui/views/controls/resize_area.h
@@ -31,7 +31,6 @@
   bool OnMouseDragged(const ui::MouseEvent& event) override;
   void OnMouseReleased(const ui::MouseEvent& event) override;
   void OnMouseCaptureLost() override;
-  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
  private:
   // Report the amount the user resized by to the delegate, accounting for
diff --git a/ui/views/controls/resize_area_unittest.cc b/ui/views/controls/resize_area_unittest.cc
index 1dec877d..70194a0a 100644
--- a/ui/views/controls/resize_area_unittest.cc
+++ b/ui/views/controls/resize_area_unittest.cc
@@ -206,6 +206,21 @@
 
   EXPECT_EQ(0, resize_amount());
 }
+
+TEST_F(ResizeAreaTest, AccessibleRole) {
+  auto* resize_area = widget()->GetContentsView();
+  ui::AXNodeData data;
+  resize_area->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.role, ax::mojom::Role::kSplitter);
+  EXPECT_EQ(resize_area->GetAccessibleRole(), ax::mojom::Role::kSplitter);
+
+  data = ui::AXNodeData();
+  resize_area->SetAccessibleRole(ax::mojom::Role::kButton);
+  resize_area->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.role, ax::mojom::Role::kButton);
+  EXPECT_EQ(resize_area->GetAccessibleRole(), ax::mojom::Role::kButton);
+}
+
 #endif  // !BUILDFLAG(IS_MAC)
 
 }  // namespace views
diff --git a/ui/views/controls/scrollbar/scroll_bar.cc b/ui/views/controls/scrollbar/scroll_bar.cc
index 2cf0214..1cef4e4 100644
--- a/ui/views/controls/scrollbar/scroll_bar.cc
+++ b/ui/views/controls/scrollbar/scroll_bar.cc
@@ -19,7 +19,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "ui/accessibility/ax_enums.mojom.h"
-#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/events/event.h"
@@ -90,10 +89,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // ScrollBar, View implementation:
 
-void ScrollBar::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  node_data->role = ax::mojom::Role::kScrollBar;
-}
-
 bool ScrollBar::OnMousePressed(const ui::MouseEvent& event) {
   if (event.IsOnlyLeftMouseButton())
     ProcessPressEvent(event);
@@ -401,6 +396,7 @@
       repeater_(base::BindRepeating(&ScrollBar::TrackClicked,
                                     base::Unretained(this))) {
   set_context_menu_controller(this);
+  SetAccessibilityProperties(ax::mojom::Role::kScrollBar);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/controls/scrollbar/scroll_bar.h b/ui/views/controls/scrollbar/scroll_bar.h
index 46e752ce..777699c 100644
--- a/ui/views/controls/scrollbar/scroll_bar.h
+++ b/ui/views/controls/scrollbar/scroll_bar.h
@@ -128,7 +128,6 @@
   int GetPosition() const;
 
   // View:
-  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   void OnMouseReleased(const ui::MouseEvent& event) override;
   void OnMouseCaptureLost() override;
diff --git a/ui/views/controls/scrollbar/scrollbar_unittest.cc b/ui/views/controls/scrollbar/scrollbar_unittest.cc
index 1f80d99..d7e9be5 100644
--- a/ui/views/controls/scrollbar/scrollbar_unittest.cc
+++ b/ui/views/controls/scrollbar/scrollbar_unittest.cc
@@ -211,6 +211,19 @@
   EXPECT_EQ(0, scrollbar_->GetPosition());
 }
 
+TEST_F(ScrollBarViewsTest, AccessibleRole) {
+  ui::AXNodeData data;
+  scrollbar_->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.role, ax::mojom::Role::kScrollBar);
+  EXPECT_EQ(scrollbar_->GetAccessibleRole(), ax::mojom::Role::kScrollBar);
+
+  data = ui::AXNodeData();
+  scrollbar_->SetAccessibleRole(ax::mojom::Role::kButton);
+  scrollbar_->GetAccessibleNodeData(&data);
+  EXPECT_EQ(data.role, ax::mojom::Role::kButton);
+  EXPECT_EQ(scrollbar_->GetAccessibleRole(), ax::mojom::Role::kButton);
+}
+
 #if !BUILDFLAG(IS_MAC)
 TEST_F(ScrollBarViewsTest, RightClickOpensMenu) {
   EXPECT_EQ(nullptr, scrollbar_->menu_model_);
diff --git a/ui/webui/resources/cr_components/help_bubble/help_bubble.html b/ui/webui/resources/cr_components/help_bubble/help_bubble.html
index 7b5ebc2..d2f8297 100644
--- a/ui/webui/resources/cr_components/help_bubble/help_bubble.html
+++ b/ui/webui/resources/cr_components/help_bubble/help_bubble.html
@@ -233,7 +233,8 @@
 </style>
 
 <div class="help-bubble" role="alertdialog" aria-modal="true"
-    aria-labelledby="title" aria-describedby="body" aria-live="assertive">
+    aria-labelledby="title" aria-describedby="body" aria-live="assertive"
+    on-keydown="onKeyDown_" on-click="blockPropagation_">
   <div id="topContainer">
     <div id="bodyIcon" hidden$="[[!shouldShowBodyIcon_(bodyIconName)]]"
         aria-label$="[[bodyIconAltText]]">
diff --git a/ui/webui/resources/cr_components/help_bubble/help_bubble.ts b/ui/webui/resources/cr_components/help_bubble/help_bubble.ts
index b52ce74..ea547b9b 100644
--- a/ui/webui/resources/cr_components/help_bubble/help_bubble.ts
+++ b/ui/webui/resources/cr_components/help_bubble/help_bubble.ts
@@ -260,6 +260,25 @@
     }));
   }
 
+  /**
+   * Handles ESC keypress (dismiss bubble) and prevents it from propagating up
+   * to parent elements.
+   */
+  private onKeyDown_(e: KeyboardEvent) {
+    if (e.key === 'Escape') {
+      e.stopPropagation();
+      this.dismiss_();
+    }
+  }
+
+  /**
+   * Prevent event propagation. Attach to any event that should not bubble up
+   * out of the help bubble.
+   */
+  private blockPropagation_(e: Event) {
+    e.stopPropagation();
+  }
+
   private getProgressClass_(index: number): string {
     return index < this.progress!.current ? 'current-progress' :
                                             'total-progress';
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn
index de43cb40..1b8c167 100644
--- a/ui/webui/resources/cr_elements/BUILD.gn
+++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -110,7 +110,6 @@
   }
 
   html_to_wrapper_template = "detect"
-  html_to_wrapper_scheme = "relative"
 
   ts_out_dir = "$root_gen_dir/ui/webui/resources/tsc/cr_elements"
   ts_composite = true
diff --git a/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.html b/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.html
index 8a054b7..fe0c5645 100644
--- a/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.html
+++ b/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.html
@@ -382,7 +382,8 @@
       style$="background-image: [[getFavicon_(url)]];">
   </div>
   <div class="image-container"
-      hidden$="[[!shouldShowUrlImage_(url, size, imageUrls)]]">
+      hidden$="[[!shouldShowUrlImage_(
+          url, size, imageUrls, firstImageLoaded_)]]">
     <img class="url-image" is="cr-auto-img" auto-src="[[imageUrls.0]]">
   </div>
   <div class="folder-and-count"
@@ -390,7 +391,7 @@
     <template is="dom-if" if="[[shouldShowFolderImages_(size)]]" restamp>
       <template is="dom-repeat" items="[[imageUrls]]"
           filter="shouldShowImageUrl_">
-        <div class="image-container">
+        <div class="image-container" hidden$="[[!firstImageLoaded_]]">
           <img class="folder-image" is="cr-auto-img" auto-src="[[item]]">
         </div>
       </template>
diff --git a/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.ts b/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.ts
index 0968b4d9..7aad66f 100644
--- a/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.ts
+++ b/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.ts
@@ -46,33 +46,44 @@
       buttonAriaDescription: String,
       count: Number,
       description: String,
+      title: String,
+      url: String,
+
       hasBadges_: {
         type: Boolean,
         reflectToAttribute: true,
       },
+
       hasDescriptions_: {
         type: Boolean,
         computed: 'computeHasDescriptions_(hasBadges_, description)',
         reflectToAttribute: true,
       },
+
       isFolder_: {
         computed: 'computeIsFolder_(count)',
         type: Boolean,
         value: false,
         reflectToAttribute: true,
       },
+
       size: {
         observer: 'onSizeChanged_',
         reflectToAttribute: true,
         type: String,
         value: CrUrlListItemSize.MEDIUM,
       },
-      title: String,
-      url: String,
+
       imageUrls: {
+        observer: 'resetFirstImageLoaded_',
         type: Array,
         value: () => [],
       },
+
+      firstImageLoaded_: {
+        type: Boolean,
+        value: false,
+      },
     };
   }
 
@@ -87,6 +98,7 @@
   override title: string;
   url?: string;
   imageUrls: string[];
+  private firstImageLoaded_: boolean;
 
   override ready() {
     super.ready();
@@ -96,6 +108,28 @@
     this.addEventListener('pointerleave', () => this.setActiveState_(false));
   }
 
+  override connectedCallback() {
+    super.connectedCallback();
+    this.resetFirstImageLoaded_();
+  }
+
+  private resetFirstImageLoaded_() {
+    this.firstImageLoaded_ = false;
+    const image = this.shadowRoot!.querySelector('img');
+    if (!image) {
+      return;
+    }
+
+    if (image.complete) {
+      this.firstImageLoaded_ = true;
+      return;
+    }
+
+    image.addEventListener('load', () => {
+      this.firstImageLoaded_ = true;
+    }, {once: true});
+  }
+
   private computeHasDescriptions_(): boolean {
     return !!this.description || this.hasBadges_;
   }
@@ -151,7 +185,8 @@
   private shouldShowUrlImage_(): boolean {
     return this.url !== undefined &&
         !(this.size === CrUrlListItemSize.COMPACT ||
-          this.imageUrls.length === 0);
+          this.imageUrls.length === 0) &&
+        this.firstImageLoaded_;
   }
 
   private shouldShowFolderImages_(): boolean {
diff --git a/ui/webui/resources/tools/build_webui.gni b/ui/webui/resources/tools/build_webui.gni
index edf9b29..42ac45f 100644
--- a/ui/webui/resources/tools/build_webui.gni
+++ b/ui/webui/resources/tools/build_webui.gni
@@ -225,6 +225,7 @@
       in_files = html_files
       minify = optimize
 
+      scheme = "relative"
       if (defined(invoker.html_to_wrapper_scheme)) {
         scheme = invoker.html_to_wrapper_scheme
       }
diff --git a/weblayer/browser/android/javatests/BUILD.gn b/weblayer/browser/android/javatests/BUILD.gn
index f681a95..8297d72b 100644
--- a/weblayer/browser/android/javatests/BUILD.gn
+++ b/weblayer/browser/android/javatests/BUILD.gn
@@ -11,7 +11,7 @@
   sources = [
     "src/org/chromium/webengine/test/CookieManagerTest.java",
     "src/org/chromium/webengine/test/ExecuteScriptTest.java",
-    "src/org/chromium/webengine/test/FaviconTest.java",
+    "src/org/chromium/webengine/test/ExternalIntentsTest.java",
     "src/org/chromium/webengine/test/FullscreenCallbackTest.java",
     "src/org/chromium/webengine/test/PostMessageTest.java",
     "src/org/chromium/webengine/test/StatePersistenceTest.java",
@@ -77,6 +77,20 @@
   ]
 }
 
+android_library("external_intents_apk_java") {
+  sources = [ "external_intents/src/org/chromium/webengine/test/external/intents/ExternalIntentsTestActivity.java" ]
+}
+
+android_apk("external_intents_apk") {
+  apk_name = "external_intents_apk"
+  android_manifest = "external_intents/AndroidManifest.xml"
+
+  deps = [
+    ":external_intents_apk_java",
+    "//weblayer/public/java:webengine_java",
+  ]
+}
+
 template("webengine_instrumentation") {
   instrumentation_test_apk(target_name) {
     forward_variables_from(invoker, "*")
@@ -102,7 +116,10 @@
 webengine_instrumentation("webengine_support_instrumentation_test_apk") {
   apk_name = "WebEngineSupportInstrumentationTest"
   apk_under_test = "//weblayer/shell/android:webengine_shell_local_apk"
-  additional_apks = [ "//weblayer/shell/android:weblayer_support_apk" ]
+  additional_apks = [
+    "//weblayer/shell/android:weblayer_support_apk",
+    ":external_intents_apk",
+  ]
 
   deps = [ ":webengine_java_tests" ]
 }
diff --git a/weblayer/browser/android/javatests/external_intents/AndroidManifest.xml b/weblayer/browser/android/javatests/external_intents/AndroidManifest.xml
new file mode 100644
index 0000000..c2be45d
--- /dev/null
+++ b/weblayer/browser/android/javatests/external_intents/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright 2023 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!-- External intents need to target a separate application otherwise
+chromium the external intents component will not launch an intent. So we need to
+test this with a different activity. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="org.chromium.webengine.test.external.intents">
+
+    <application android:label="ExternalIntents test app">
+        <activity
+            android:name="ExternalIntentsTestActivity"
+            android:launchMode="singleTask"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="webenginetest" android:host="state.app" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/weblayer/browser/android/javatests/external_intents/src/org/chromium/webengine/test/external/intents/ExternalIntentsTestActivity.java b/weblayer/browser/android/javatests/external_intents/src/org/chromium/webengine/test/external/intents/ExternalIntentsTestActivity.java
new file mode 100644
index 0000000..9811678d
--- /dev/null
+++ b/weblayer/browser/android/javatests/external_intents/src/org/chromium/webengine/test/external/intents/ExternalIntentsTestActivity.java
@@ -0,0 +1,48 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.webengine.test.external.intents;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Used by the external intents test. The problem is that the external intents
+ * only be launched for packages outside of the package the tests are being
+ * run from so this needs to be in a separate application.
+ *
+ * This exists to start the activity that called it.
+ *
+ * This activity will kill itself to clean up after it has been backgrounded.
+ */
+public class ExternalIntentsTestActivity extends Activity {
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        String returnTo = getIntent().getData().getQueryParameter("return_to");
+
+        if (returnTo != null) {
+            ComponentName componentCaller = ComponentName.unflattenFromString(returnTo);
+
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.addCategory(Intent.CATEGORY_LAUNCHER);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setComponent(componentCaller);
+            intent.putExtra("LAUNCHED_EXTERNAL", true);
+
+            // We are just returning back because the instrumentation activity is
+            // set to single task.
+            startActivity(intent);
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        // We want to clean up, but only when we're leaving to ensure that it
+        // starts the previous activity with its intent.
+        finish();
+    }
+}
diff --git a/weblayer/browser/android/javatests/src/org/chromium/webengine/test/ExternalIntentsTest.java b/weblayer/browser/android/javatests/src/org/chromium/webengine/test/ExternalIntentsTest.java
new file mode 100644
index 0000000..e18a012
--- /dev/null
+++ b/weblayer/browser/android/javatests/src/org/chromium/webengine/test/ExternalIntentsTest.java
@@ -0,0 +1,155 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.webengine.test;
+
+import static org.chromium.content_public.browser.test.util.TestThreadUtils.runOnUiThreadBlocking;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+
+import androidx.test.filters.MediumTest;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.DoNotBatch;
+import org.chromium.content_public.browser.test.util.ClickUtils;
+import org.chromium.net.test.EmbeddedTestServer;
+import org.chromium.net.test.EmbeddedTestServerRule;
+import org.chromium.webengine.Tab;
+import org.chromium.webengine.WebEngine;
+import org.chromium.webengine.WebEngineParams;
+import org.chromium.webengine.WebSandbox;
+import org.chromium.webengine.shell.InstrumentationActivity;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Tests for launching external intents from deep links.
+ */
+@DoNotBatch(reason = "Tests are testing behaviour between activities that are single task")
+@RunWith(WebEngineJUnit4ClassRunner.class)
+public class ExternalIntentsTest {
+    @Rule
+    public EmbeddedTestServerRule mTestServerRule = new EmbeddedTestServerRule();
+
+    @Rule
+    public InstrumentationActivityTestRule mActivityTestRule =
+            new InstrumentationActivityTestRule();
+
+    // We need plenty time to load up a page, launch a new activity, and return.
+    // We need to be confident that those events also did not happen in the disabled
+    // case if this times out.
+    private static final int TEST_TIMEOUT_MS = 5_000;
+
+    private EmbeddedTestServer mServer;
+    private WebSandbox mSandbox;
+    private Instrumentation mInstrumentation;
+    private String mUrl;
+
+    @Before
+    public void setUp() throws Exception {
+        mActivityTestRule.launchShell();
+
+        mServer = mTestServerRule.getServer();
+        mUrl = getTestDataURL("external_intents.html#"
+                + mActivityTestRule.getShellComponentName().flattenToString());
+
+        mSandbox = mActivityTestRule.getWebSandbox();
+    }
+
+    @After
+    public void shutdown() {
+        runOnUiThreadBlocking(() -> mSandbox.shutdown());
+        mActivityTestRule.finish();
+    }
+
+    @Test
+    @MediumTest
+    public void testOpensExternalIntents_shouldLaunch() throws Exception {
+        // Awful hack heads up:
+        // The problem is that the application is a separate application from the
+        // activity running the tests so we can't use an ActivityMonitor.
+        // Chromium thinks that if you are opening a deeplink to the same package,
+        // it should act as a "tab" navigation and not send an external intent.
+        // We can't override apis like startActivity for the instrumentation activity
+        // because the component is starting the activity from the web engine context.
+        final SettableFuture<Boolean> launchedExternal = SettableFuture.create();
+        mActivityTestRule.getActivity().setLifeCycleListener(
+                new InstrumentationActivity.LifeCycleListener() {
+                    @Override
+                    public void onNewIntent(Intent intent) {
+                        launchedExternal.set(intent.hasExtra("LAUNCHED_EXTERNAL"));
+                    }
+                });
+        Tab currentTab = createWebEngineAndLoadPage(/* isExternalIntentsEnabled= */ true);
+
+        ClickUtils.mouseSingleClickView(InstrumentationRegistry.getInstrumentation(),
+                mActivityTestRule.getFragmentContainerView(), 1, 1);
+
+        try {
+            Assert.assertTrue(launchedExternal.get(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        } catch (TimeoutException e) {
+            Assert.fail("Shouldn't have timed out");
+        }
+    }
+
+    @Test
+    @MediumTest
+    public void testDisableExternalIntents_shouldNotLaunch() throws Exception {
+        final SettableFuture<Boolean> launchedExternal = SettableFuture.create();
+        mActivityTestRule.getActivity().setLifeCycleListener(
+                new InstrumentationActivity.LifeCycleListener() {
+                    @Override
+                    public void onNewIntent(Intent intent) {
+                        launchedExternal.set(intent.hasExtra("LAUNCHED_EXTERNAL"));
+                    }
+                });
+        Tab currentTab = createWebEngineAndLoadPage(/* isExternalIntentsEnabled= */ false);
+
+        ClickUtils.mouseSingleClickView(InstrumentationRegistry.getInstrumentation(),
+                mActivityTestRule.getFragmentContainerView(), 1, 1);
+
+        try {
+            Assert.assertFalse(launchedExternal.get(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+            // If we get here it means the test resumed from the other activity
+            Assert.fail("The activity shouldn't have been resumed");
+        } catch (TimeoutException e) {
+            // Yay it was meant to timeout
+        }
+    }
+
+    /**
+     * Creates a new web engine and loads the test page.
+     *
+     * Will configure if we can launch external intents or not.
+     */
+    private Tab createWebEngineAndLoadPage(boolean isExternalIntentsEnabled) throws Exception {
+        WebEngineParams params = new WebEngineParams.Builder()
+                                         .setProfileName("Default")
+                                         .setIsExternalIntentsEnabled(isExternalIntentsEnabled)
+                                         .build();
+
+        WebEngine webEngine = runOnUiThreadBlocking(() -> mSandbox.createWebEngine(params)).get();
+        runOnUiThreadBlocking(() -> mActivityTestRule.attachFragment(webEngine.getFragment()));
+
+        Tab activeTab = webEngine.getTabManager().getActiveTab();
+        mActivityTestRule.navigateAndWait(activeTab, mUrl);
+
+        return activeTab;
+    }
+
+    private String getTestDataURL(String path) {
+        return mServer.getURL("/weblayer/test/data/" + path);
+    }
+}
diff --git a/weblayer/browser/android/javatests/src/org/chromium/webengine/test/FaviconTest.java b/weblayer/browser/android/javatests/src/org/chromium/webengine/test/FaviconTest.java
deleted file mode 100644
index 3c0c31e..0000000
--- a/weblayer/browser/android/javatests/src/org/chromium/webengine/test/FaviconTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.webengine.test;
-
-import static org.chromium.content_public.browser.test.util.TestThreadUtils.runOnUiThreadBlocking;
-
-import android.graphics.Bitmap;
-import android.graphics.Color;
-
-import androidx.test.filters.MediumTest;
-import androidx.test.filters.SmallTest;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.DoNotBatch;
-import org.chromium.net.test.EmbeddedTestServer;
-import org.chromium.net.test.EmbeddedTestServerRule;
-import org.chromium.webengine.Tab;
-import org.chromium.webengine.TabObserver;
-import org.chromium.webengine.WebEngine;
-import org.chromium.webengine.WebSandbox;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Tests that a tab's favicon is returned.
- */
-@DoNotBatch(reason = "Tests need separate Activities and WebFragments")
-@RunWith(WebEngineJUnit4ClassRunner.class)
-public class FaviconTest {
-    @Rule
-    public EmbeddedTestServerRule mTestServerRule = new EmbeddedTestServerRule();
-
-    @Rule
-    public InstrumentationActivityTestRule mActivityTestRule =
-            new InstrumentationActivityTestRule();
-
-    private EmbeddedTestServer mServer;
-    private Tab mTab;
-
-    private String getTestDataURL(String path) {
-        return mServer.getURL("/weblayer/test/data/" + path);
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        mActivityTestRule.launchShell();
-        mServer = mTestServerRule.getServer();
-        WebSandbox sandbox = mActivityTestRule.getWebSandbox();
-        WebEngine webEngine = runOnUiThreadBlocking(() -> sandbox.createWebEngine()).get();
-
-        mTab = webEngine.getTabManager().getActiveTab();
-    }
-
-    @After
-    public void tearDown() {
-        mActivityTestRule.finish();
-    }
-
-    private static final class ResultHolder {
-        public Bitmap mResult;
-    }
-
-    private Bitmap waitForFaviconChange() throws Exception {
-        final ResultHolder holder = new ResultHolder();
-        CountDownLatch faviconLatch = new CountDownLatch(1);
-        TabObserver observer = new TabObserver() {
-            @Override
-            public void onFaviconChanged(Tab tab, Bitmap favicon) {
-                holder.mResult = favicon;
-                faviconLatch.countDown();
-            }
-        };
-        runOnUiThreadBlocking(() -> mTab.registerTabObserver(observer));
-
-        faviconLatch.await(10, TimeUnit.SECONDS);
-
-        runOnUiThreadBlocking(() -> mTab.unregisterTabObserver(observer));
-        return holder.mResult;
-    }
-
-    private void verifyFavicon(Bitmap favicon) {
-        Assert.assertNotNull(favicon);
-        Assert.assertEquals(favicon.getHeight(), 16);
-        Assert.assertEquals(favicon.getWidth(), 16);
-        Assert.assertEquals(favicon.getPixel(0, 0), Color.rgb(0, 72, 255));
-    }
-
-    @Test
-    @SmallTest
-    public void checkFaviconIsExposed() throws Exception {
-        runOnUiThreadBlocking(() -> mTab.getNavigationController().navigate(
-                                              getTestDataURL("simple_page_with_favicon.html")));
-        Bitmap favicon = waitForFaviconChange();
-        verifyFavicon(favicon);
-    }
-
-    @Test
-    @SmallTest
-    public void checkDelayedFaviconsAreDelivered() throws Exception {
-        runOnUiThreadBlocking(() -> mTab.getNavigationController().navigate(getTestDataURL(
-                                              "simple_page_with_delayed_favicon.html")));
-
-        Bitmap favicon = waitForFaviconChange();
-        Assert.assertNull(favicon);
-
-        // The page dynamically creates a favicon after receiving a post message.
-        runOnUiThreadBlocking(() -> mTab.postMessage("message", "*"));
-        favicon = waitForFaviconChange();
-        verifyFavicon(favicon);
-    }
-
-    @Test
-    @MediumTest
-    public void checkFaviconsCanBeDeleted() throws Exception {
-        runOnUiThreadBlocking(() -> mTab.getNavigationController().navigate(getTestDataURL(
-                                              "simple_page_with_deleted_favicon.html")));
-
-        Bitmap favicon = waitForFaviconChange();
-        verifyFavicon(favicon);
-
-        // Favicon eventually gets deleted.
-        favicon = waitForFaviconChange();
-        Assert.assertNull(favicon);
-    }
-
-    @Test
-    @SmallTest
-    public void pageWithNoFaviconDeliversEvent() throws Exception {
-        runOnUiThreadBlocking(
-                () -> mTab.getNavigationController().navigate(getTestDataURL("simple_page.html")));
-
-        Bitmap favicon = waitForFaviconChange();
-        Assert.assertNull(favicon);
-    }
-
-    @Test
-    @SmallTest
-    public void multipleNavigationsDelieverEvents() throws Exception {
-        runOnUiThreadBlocking(() -> mTab.getNavigationController().navigate(
-                                              getTestDataURL("simple_page_with_favicon.html")));
-
-        Bitmap favicon = waitForFaviconChange();
-        verifyFavicon(favicon);
-
-        runOnUiThreadBlocking(
-                () -> mTab.getNavigationController().navigate(getTestDataURL("simple_page.html")));
-        favicon = waitForFaviconChange();
-        Assert.assertNull(favicon);
-    }
-}
\ No newline at end of file
diff --git a/weblayer/browser/android/javatests/src/org/chromium/webengine/test/InstrumentationActivityTestRule.java b/weblayer/browser/android/javatests/src/org/chromium/webengine/test/InstrumentationActivityTestRule.java
index fe2ccd7..c907803 100644
--- a/weblayer/browser/android/javatests/src/org/chromium/webengine/test/InstrumentationActivityTestRule.java
+++ b/weblayer/browser/android/javatests/src/org/chromium/webengine/test/InstrumentationActivityTestRule.java
@@ -49,12 +49,15 @@
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(Intent.CATEGORY_LAUNCHER);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.setComponent(
-                new ComponentName(InstrumentationRegistry.getInstrumentation().getTargetContext(),
-                        InstrumentationActivity.class));
+        intent.setComponent(getShellComponentName());
         launchActivity(intent);
     }
 
+    public ComponentName getShellComponentName() {
+        return new ComponentName(InstrumentationRegistry.getInstrumentation().getTargetContext(),
+                InstrumentationActivity.class);
+    }
+
     public void finish() {
         Assert.assertNotNull(getActivity());
         getActivity().finish();
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
index d29c32d7..3c3deb95 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
@@ -46,6 +46,7 @@
 
     private long mNativeBrowser;
     private final ProfileImpl mProfile;
+    private final boolean mIsExternalIntentsEnabled;
     private Context mServiceContext;
 
     private IBrowserClient mClient;
@@ -97,6 +98,9 @@
 
         mProfile.checkNotDestroyed(); // TODO(swestphal): or mProfile != null
 
+        mIsExternalIntentsEnabled =
+                fragmentArgs.getBoolean(BrowserFragmentArgs.IS_EXTERNAL_INTENTS_ENABLED);
+
         if (!isIncognito && !TextUtils.isEmpty(persistenceId)) {
             mFullPersistenceInfo = new FullPersistenceInfo();
             mFullPersistenceInfo.mPersistenceId = persistenceId;
@@ -291,6 +295,10 @@
         BrowserImplJni.get().onFragmentPause(mNativeBrowser);
     }
 
+    boolean isExternalIntentsEnabled() {
+        return mIsExternalIntentsEnabled;
+    }
+
     public boolean isWindowOnSmallDevice() {
         WindowAndroid windowAndroid = mBrowserFragmentImpl.getWindowAndroid();
         assert windowAndroid != null;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
index ee593e9f..72e7ae3 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
@@ -49,7 +49,7 @@
 
     @Override
     public boolean shouldDisableExternalIntentRequestsForUrl(GURL url) {
-        return false;
+        return !mTab.getBrowser().isExternalIntentsEnabled();
     }
 
     @Override
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/BrowserFragmentArgs.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/BrowserFragmentArgs.java
index 6e6cdc7..78907b0 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/BrowserFragmentArgs.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/BrowserFragmentArgs.java
@@ -12,5 +12,6 @@
      * A boolean value indicating whether the profile is incognito.
      */
     String IS_INCOGNITO = "is_incognito";
+    String IS_EXTERNAL_INTENTS_ENABLED = "is_external_intents_enabled";
     String USE_VIEW_MODEL = "use_view_model";
 }
diff --git a/weblayer/public/java/org/chromium/webengine/TabObserver.java b/weblayer/public/java/org/chromium/webengine/TabObserver.java
index 9d4aaaa2..430d4cf0 100644
--- a/weblayer/public/java/org/chromium/webengine/TabObserver.java
+++ b/weblayer/public/java/org/chromium/webengine/TabObserver.java
@@ -4,10 +4,7 @@
 
 package org.chromium.webengine;
 
-import android.graphics.Bitmap;
-
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
 /**
  * An interface for observing changes to a Tab.
@@ -31,13 +28,6 @@
     public default void onTitleUpdated(Tab tab, @NonNull String title) {}
 
     /**
-     *
-     * @param tab the tab associated with this event.
-     * @param favicon The favicon associated with the Tab. null if there is no favicon.
-     */
-    public default void onFaviconChanged(Tab tab, @Nullable Bitmap favicon) {}
-
-    /**
      * Triggered when the render process dies, either due to crash or killed by the system to
      * reclaim memory.
      *
diff --git a/weblayer/public/java/org/chromium/webengine/TabObserverDelegate.java b/weblayer/public/java/org/chromium/webengine/TabObserverDelegate.java
index 9430ffa7..97081bc 100644
--- a/weblayer/public/java/org/chromium/webengine/TabObserverDelegate.java
+++ b/weblayer/public/java/org/chromium/webengine/TabObserverDelegate.java
@@ -4,7 +4,6 @@
 
 package org.chromium.webengine;
 
-import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
@@ -76,13 +75,4 @@
             }
         });
     }
-
-    @Override
-    public void notifyFaviconChanged(Bitmap favicon) {
-        mHandler.post(() -> {
-            for (TabObserver observer : mTabObservers) {
-                observer.onFaviconChanged(mTab, favicon);
-            }
-        });
-    }
 }
\ No newline at end of file
diff --git a/weblayer/public/java/org/chromium/webengine/WebEngineParams.java b/weblayer/public/java/org/chromium/webengine/WebEngineParams.java
index fa0825e..1c664e67 100644
--- a/weblayer/public/java/org/chromium/webengine/WebEngineParams.java
+++ b/weblayer/public/java/org/chromium/webengine/WebEngineParams.java
@@ -21,11 +21,14 @@
 
     private boolean mIsIncognito;
 
+    private boolean mIsExternalIntentsEnabled = true;
+
     IWebEngineParams getParcelable() {
         IWebEngineParams params = new IWebEngineParams();
         params.profileName = mProfileName;
         params.persistenceId = mPersistenceId;
         params.isIncognito = mIsIncognito;
+        params.isExternalIntentsEnabled = mIsExternalIntentsEnabled;
         return params;
     }
 
@@ -44,7 +47,7 @@
          * profile. If {@code profile} must only contain alphanumeric and underscore characters
          * since it will be used as a directory name in the file system.
          *
-         * @param name The name of the profile.
+         * @param profileName The name of the profile.
          */
         @NonNull
         public Builder setProfileName(@Nullable String profileName) {
@@ -68,12 +71,23 @@
 
         /**
          * Sets whether the profile is incognito.
-         * @param incognito Whether the profile should be incognito.
+         * @param isIncognito Whether the profile should be incognito.
          */
         @NonNull
         public Builder setIsIncognito(boolean isIncognito) {
             mParams.mIsIncognito = isIncognito;
             return this;
         }
+
+        /**
+         * Sets whether pages will be able to open native intents.
+         * @param isExternalIntentsEnabled Whether all pages will have the ability to open intent
+         *         urls.
+         */
+        @NonNull
+        public Builder setIsExternalIntentsEnabled(boolean isExternalIntentsEnabled) {
+            mParams.mIsExternalIntentsEnabled = isExternalIntentsEnabled;
+            return this;
+        }
     }
 }
diff --git a/weblayer/public/java/org/chromium/webengine/interfaces/ITabObserverDelegate.aidl b/weblayer/public/java/org/chromium/webengine/interfaces/ITabObserverDelegate.aidl
index 2aeeebf..1a32804b 100644
--- a/weblayer/public/java/org/chromium/webengine/interfaces/ITabObserverDelegate.aidl
+++ b/weblayer/public/java/org/chromium/webengine/interfaces/ITabObserverDelegate.aidl
@@ -4,13 +4,10 @@
 
 package org.chromium.webengine.interfaces;
 
-import android.graphics.Bitmap;
-
 import org.chromium.webengine.interfaces.ITabParams;
 
 oneway interface ITabObserverDelegate {
-    void notifyTitleUpdated(in String title) = 1;
-    void notifyVisibleUriChanged(in String uri) = 2;
+    void notifyTitleUpdated(String title) = 1;
+    void notifyVisibleUriChanged(String uri) = 2;
     void notifyRenderProcessGone() = 3;
-    void notifyFaviconChanged(in Bitmap favicon) = 4;
 }
\ No newline at end of file
diff --git a/weblayer/public/java/org/chromium/webengine/interfaces/IWebEngineParams.aidl b/weblayer/public/java/org/chromium/webengine/interfaces/IWebEngineParams.aidl
index 3f0b82c..0804ec8 100644
--- a/weblayer/public/java/org/chromium/webengine/interfaces/IWebEngineParams.aidl
+++ b/weblayer/public/java/org/chromium/webengine/interfaces/IWebEngineParams.aidl
@@ -8,4 +8,5 @@
     String profileName;
     String persistenceId;
     boolean isIncognito;
+    boolean isExternalIntentsEnabled;
 }
diff --git a/weblayer/public/java/org/chromium/weblayer/TabProxy.java b/weblayer/public/java/org/chromium/weblayer/TabProxy.java
index 4a337d2c4..99188754 100644
--- a/weblayer/public/java/org/chromium/weblayer/TabProxy.java
+++ b/weblayer/public/java/org/chromium/weblayer/TabProxy.java
@@ -4,7 +4,6 @@
 
 package org.chromium.weblayer;
 
-import android.graphics.Bitmap;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -35,7 +34,6 @@
             new WebFragmentNavigationDelegate();
     private FullscreenCallbackDelegate mFullscreenCallbackDelegate =
             new FullscreenCallbackDelegate();
-    private FaviconFetcher mFaviconFetcher;
 
     // Only use one callback for all the message event listeners. This is to avoid sending the same
     // message over multiple times. The message can then be proxied to all valid listeners.
@@ -50,12 +48,6 @@
 
         tab.registerTabCallback(mTabObserverDelegate);
         tab.setFullscreenCallback(mFullscreenCallbackDelegate);
-        mFaviconFetcher = tab.createFaviconFetcher(new FaviconCallback() {
-            @Override
-            public void onFaviconChanged(Bitmap favicon) {
-                mTabObserverDelegate.notifyFaviconChanged(favicon);
-            }
-        });
     }
 
     void invalidate() {
@@ -64,8 +56,6 @@
 
         mTabObserverDelegate = null;
         mNavigationObserverDelegate = null;
-        mFaviconFetcher.destroy();
-        mFaviconFetcher = null;
     }
 
     boolean isValid() {
diff --git a/weblayer/public/java/org/chromium/weblayer/WebEngineDelegate.java b/weblayer/public/java/org/chromium/weblayer/WebEngineDelegate.java
index 540ec21..ec622e0 100644
--- a/weblayer/public/java/org/chromium/weblayer/WebEngineDelegate.java
+++ b/weblayer/public/java/org/chromium/weblayer/WebEngineDelegate.java
@@ -63,6 +63,7 @@
     private static Bundle bundleParams(IWebEngineParams params) {
         String profileName = Profile.sanitizeProfileName(params.profileName);
         boolean isIncognito = params.isIncognito || "".equals(profileName);
+        boolean isExternalIntentsEnabled = params.isExternalIntentsEnabled;
         // Support for named incognito profiles was added in 87. Checking is done in
         // WebFragment, as this code should not trigger loading WebLayer.
         Bundle args = new Bundle();
@@ -71,6 +72,7 @@
             args.putString(BrowserFragmentArgs.PERSISTENCE_ID, params.persistenceId);
         }
         args.putBoolean(BrowserFragmentArgs.IS_INCOGNITO, isIncognito);
+        args.putBoolean(BrowserFragmentArgs.IS_EXTERNAL_INTENTS_ENABLED, isExternalIntentsEnabled);
         args.putBoolean(BrowserFragmentArgs.USE_VIEW_MODEL, false);
 
         return args;
diff --git a/weblayer/public/java/org/chromium/weblayer/WebFragmentTabDelegate.java b/weblayer/public/java/org/chromium/weblayer/WebFragmentTabDelegate.java
index 9e69cdd..944e14616 100644
--- a/weblayer/public/java/org/chromium/weblayer/WebFragmentTabDelegate.java
+++ b/weblayer/public/java/org/chromium/weblayer/WebFragmentTabDelegate.java
@@ -4,12 +4,10 @@
 
 package org.chromium.weblayer;
 
-import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.RemoteException;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
 import org.chromium.webengine.interfaces.ITabObserverDelegate;
 
@@ -39,10 +37,6 @@
         maybeRunOnTabObserver(observer -> { observer.notifyTitleUpdated(title); });
     }
 
-    void notifyFaviconChanged(@Nullable Bitmap favicon) {
-        maybeRunOnTabObserver(observer -> { observer.notifyFaviconChanged(favicon); });
-    }
-
     private interface OnTabObserverCallback {
         void run(ITabObserverDelegate tabObserver) throws RemoteException;
     }
diff --git a/weblayer/shell/android/webengine_shell_apk/src/org/chromium/webengine/shell/DefaultObservers.java b/weblayer/shell/android/webengine_shell_apk/src/org/chromium/webengine/shell/DefaultObservers.java
index 10c1d97..c9683728 100644
--- a/weblayer/shell/android/webengine_shell_apk/src/org/chromium/webengine/shell/DefaultObservers.java
+++ b/weblayer/shell/android/webengine_shell_apk/src/org/chromium/webengine/shell/DefaultObservers.java
@@ -4,8 +4,6 @@
 
 package org.chromium.webengine.shell;
 
-import android.graphics.Bitmap;
-
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
@@ -40,13 +38,6 @@
         Log.i(TAG, this + "received Tab Event: 'onRenderProcessGone()'");
     }
 
-    @Override
-    public void onFaviconChanged(@NonNull Tab tab, @Nullable Bitmap favicon) {
-        Log.i(TAG,
-                this + "received Tab Event: 'onFaviconChanged("
-                        + (favicon == null ? "null" : favicon.toString()) + ")'");
-    }
-
     // NavigationObserver implementation.
 
     @Override
diff --git a/weblayer/shell/android/webengine_shell_apk/src/org/chromium/webengine/shell/InstrumentationActivity.java b/weblayer/shell/android/webengine_shell_apk/src/org/chromium/webengine/shell/InstrumentationActivity.java
index 3f21ff0..6b355730 100644
--- a/weblayer/shell/android/webengine_shell_apk/src/org/chromium/webengine/shell/InstrumentationActivity.java
+++ b/weblayer/shell/android/webengine_shell_apk/src/org/chromium/webengine/shell/InstrumentationActivity.java
@@ -4,6 +4,7 @@
 
 package org.chromium.webengine.shell;
 
+import android.content.Intent;
 import android.os.Bundle;
 import android.view.View;
 
@@ -24,6 +25,18 @@
 public class InstrumentationActivity extends AppCompatActivity {
     private ListenableFuture<WebSandbox> mWebSandboxFuture;
     private ListenableFuture<String> mWebSandboxVersionFuture;
+    private LifeCycleListener mLifeCycleListener;
+
+    /**
+     * Use this to listen for life cycle events in tests.
+     */
+    public interface LifeCycleListener {
+        void onNewIntent(Intent intent);
+    }
+
+    public void setLifeCycleListener(LifeCycleListener lifeCycleListener) {
+        mLifeCycleListener = lifeCycleListener;
+    }
 
     @Override
     protected void onCreate(final Bundle savedInstanceState) {
@@ -64,4 +77,12 @@
 
         return (WebFragment) fragments.get(0);
     }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        if (mLifeCycleListener != null) {
+            mLifeCycleListener.onNewIntent(intent);
+        }
+        super.onNewIntent(intent);
+    }
 }
diff --git a/weblayer/test/data/external_intents.html b/weblayer/test/data/external_intents.html
new file mode 100644
index 0000000..192e4106
--- /dev/null
+++ b/weblayer/test/data/external_intents.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+    <body>
+        <a id="button">
+            launch state activity
+        </a>
+        <script type="text/javascript">
+            document.getElementById('button').href = 'intent://state.app?return_to=' + window.location.href.split('#')[1]  + '#Intent;scheme=webenginetest;action=android.intent.action.VIEW;package=org.chromium.webengine.test.external.intents;end;';
+        </script>
+    </body>
+</html>
diff --git a/weblayer/test/data/simple_page_with_delayed_favicon.html b/weblayer/test/data/simple_page_with_delayed_favicon.html
deleted file mode 100644
index ef04aae..0000000
--- a/weblayer/test/data/simple_page_with_delayed_favicon.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<html>
-  <head>
-    <title>OK</title>
-  </head>
-<body>
-Basic html test.
-</body>
-<script>
-function createFavicon() {
-    const link = document.createElement('link');
-    link.rel = 'icon';
-    link.href = 'favicon.png';
-    document.head.appendChild(link);
-}
-window.addEventListener('message', () => {
-    createFavicon();
-});
-</script>
-</html>
diff --git a/weblayer/test/data/simple_page_with_deleted_favicon.html b/weblayer/test/data/simple_page_with_deleted_favicon.html
deleted file mode 100644
index 542daacd..0000000
--- a/weblayer/test/data/simple_page_with_deleted_favicon.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<html>
-  <head>
-    <title>OK</title>
-    <link rel="icon" id="fi" type="image/png" href="favicon.png"/>
-  </head>
-<body>
-Basic html test.
-</body>
-<script>
-setTimeout(() => {
-  const link = document.getElementById('fi');
-  document.head.removeChild(link);
-}, 5000);
-</script>
-</html>