diff --git a/DEPS b/DEPS
index 37635dc9..bfc665b 100644
--- a/DEPS
+++ b/DEPS
@@ -299,11 +299,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '0c636b805b9e70c73af46060e9faa9464f836e43',
+  'skia_revision': '59dcffca90618578a6f9522dbad7c500a98884a1',
   # 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': 'd7513544531095ae60036f53b965b34c0fa56011',
+  'v8_revision': '6ee8246e79f1e7a69669e3599fb1f94a517b10bd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
@@ -326,7 +326,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:11.20230128.1.1',
+  'fuchsia_version': 'version:11.20230129.1.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -418,7 +418,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.
-  'quiche_revision': '566b33c9fa5b1723db04be3d40dcaf102344c323',
+  'quiche_revision': '18631e198ebd9f3c4984b76dcd52258b5ddf4a93',
   # 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.
@@ -752,7 +752,7 @@
 
   'src/clank': {
     'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' +
-    'ab56a45a7048fb5fd81daac1c81342cf5be97ac5',
+    'a2c86438eb101876f70bacba5adec8b2c3716b19',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -851,7 +851,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/linux-amd64',
-          'version': 'W8aiOxFUYLi5EWDrI_ydzRLG7Ay_loaXncJobBLiKY0C',
+          'version': 'dp8woh8rfQWUquwDYBEKTHvkmwo9LWSsqRAnQkhPq1sC',
         },
       ],
       'dep_type': 'cipd',
@@ -862,7 +862,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': 'oHaXkZacLvhJb_pjG1J1DFqlzEzTyBOmcILiOmI_5ggC',
+          'version': 'IeTyIWeiXhN4OK8wlSGP6Mnu0QJSxvyKF5nTCJq7PPkC',
         },
       ],
       'dep_type': 'cipd',
@@ -873,7 +873,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/windows-amd64',
-          'version': '9NCMWj0O-RhFZ19u0Q8fFgz7oAre0LPEcQTZmnoCvogC',
+          'version': 'TwbxOQEmLvrdGnf7uQW2ZWI9CoHOIM9ZiYuWlEb6ESMC',
         },
       ],
       'dep_type': 'cipd',
@@ -941,7 +941,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'NQPYbXN8Ab7VRK5nH3Bv_AtkolGTMUH1Bmke4myDgtAC',
+          'version': 'Aw6kA-NpPjzWNknKBiY0EyY5bNO-dUuS9QdZHdjLzX8C',
       },
     ],
     'condition': 'checkout_android',
@@ -1176,7 +1176,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'aea2f085e3a5147f6bd2b88251b82eeb73495b87',
+      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'e424b890c2a36af44151d328f73cb725e152efa8',
       'condition': 'checkout_linux',
   },
 
@@ -1186,13 +1186,13 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b7d8efd8bee494f4cfacacc19cf50fc4d4be3900',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9d77ca716ffdd46eb4be7d5638939da5e8ffb5ef',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'c462663cd0079148df5c0f85fd2ab1f3fe142f00',
+      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '368981bc3b4c041d8cd0229dd102ecf460b81d31',
     'condition': 'checkout_src_internal',
   },
 
@@ -1650,7 +1650,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '07e128e9a2a37507a7db1de743b7b1b3e27cc930',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '45275bed1173d8a0cd0995560ca2882eb7d45e19',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1690,7 +1690,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': 'T0UK7p_L0p6Mj1ZDZo1V5htccPl41gV_E67mU9jHXokC',
+              'version': 'l0C1ThOaE6rumuAbPi3UJ4mbRYtfEz2MYsw8oNHsehYC',
           },
       ],
       'condition': 'checkout_android',
@@ -1905,7 +1905,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1d60f778a9acc011fb59dd3b8da648664b75cc2d',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@d19a58e3d0df3ee6b2e2889b7779ba4cf44c2e83',
     'condition': 'checkout_src_internal',
   },
 
@@ -1935,7 +1935,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': '3Z7gv4J_WlUkA8U8Gn2ensbIoROjvJW403Ux91z-OF8C',
+        'version': '-MSX5O2Dir7maBa2lB-y9Dy9sU4UziV_-ieQmfcFP4kC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1957,7 +1957,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'clObjcfOHFWyPY6Qhd99roF37abFuLgCOU9uBY15hsIC',
+        'version': 'aBpoCHEPfMKLdl7Tez28r4Vk4n52JH2cSQVC-VJ4Mc0C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/strings/ash_strings_fa.xtb b/ash/strings/ash_strings_fa.xtb
index 481f15d..9c56070 100644
--- a/ash/strings/ash_strings_fa.xtb
+++ b/ash/strings/ash_strings_fa.xtb
@@ -732,6 +732,7 @@
 <translation id="492453977506755176">کلید حالت ضبط</translation>
 <translation id="4925542575807923399">سرپرست این حساب لازم می‌داند که این حساب اولین حسابی باشد که در جلسه چندگانه ورود به سیستم وارد سیستم شده باشد.</translation>
 <translation id="4929163402621253029">آیا درحال صحبت هستید؟ صدای شما قطع است. بیشتر بدانید</translation>
+<translation id="4936329710968938986">همه، خاموش</translation>
 <translation id="4938176435186993759">پنهان کردن همه پیشنهادها</translation>
 <translation id="4945196315133970626">غیرفعال کردن اعلان‌ها</translation>
 <translation id="4946376291507881335">ضبط</translation>
@@ -1386,6 +1387,7 @@
 <translation id="8477270416194247200">‏برای لغو کردن Alt+Search یا Shift را فشار دهید.</translation>
 <translation id="8492573885090281069"><ph name="DISPLAY_NAME" /> از <ph name="SPECIFIED_RESOLUTION" /> پشتیبانی نمی‌کند. وضوح به <ph name="FALLBACK_RESOLUTION" /> تغییر کرد. برای حفظ تغییرات، روی تأیید کلیک کنید. تنظیمات قبلی <ph name="TIMEOUT_SECONDS" /> دیگر بازیابی خواهد شد.</translation>
 <translation id="8496402167048257517">نمایش تنظیمات «هم‌رسانی با اطراف»</translation>
+<translation id="8507563469658346379">همه، <ph name="REMAINING_TIME" /></translation>
 <translation id="85123341071060231">‏بلوتوث Chromebook خاموش است. برای باز کردن قفل Chromebook، گذرواژه را وارد کنید.</translation>
 <translation id="8513108775083588393">چرخش خودکار</translation>
 <translation id="851458219935658693">نمایش پنجره‌ها از میزکار فعلی، دکمه رادیو انتخاب شد</translation>
diff --git a/ash/strings/ash_strings_mn.xtb b/ash/strings/ash_strings_mn.xtb
index defe9b9..f638844 100644
--- a/ash/strings/ash_strings_mn.xtb
+++ b/ash/strings/ash_strings_mn.xtb
@@ -734,6 +734,7 @@
 <translation id="492453977506755176">Зураг авах горимын товч</translation>
 <translation id="4925542575807923399">Энэ хаягийг хариуцсан ажилтан нь олон хаягаар зэрэг нэвтрэх тохиолдолд зөвхөн энэ хаягаар түрүүлж нэвтэрсний дараагаар бусад хаягт нэвтрэх боломжтой байхаар тохируулсан байна.</translation>
 <translation id="4929163402621253029">Та ярьж байна уу? Таны дуу хаагдсан байна. Нэмэлт мэдээлэл авах</translation>
+<translation id="4936329710968938986">Бүгд, унтраалттай</translation>
 <translation id="4938176435186993759">Бүх зөвлөмжийг нуух</translation>
 <translation id="4945196315133970626">Мэдэгдлийг унтраах</translation>
 <translation id="4946376291507881335">Зураг авах</translation>
@@ -1389,6 +1390,7 @@
 <translation id="8477270416194247200">Цуцлахын тулд Alt+Search эсвэл Shift товчлуурыг дарна уу.</translation>
 <translation id="8492573885090281069"><ph name="DISPLAY_NAME" /> <ph name="SPECIFIED_RESOLUTION" />-г дэмждэггүй. Нягтралыг <ph name="FALLBACK_RESOLUTION" /> болгож өөрчилсөн. Өөрчлөлтийг хадгалахын тулд баталгаажуулахыг товшино уу. Өмнөх тохиргоог <ph name="TIMEOUT_SECONDS" />-н дараа сэргээнэ.</translation>
 <translation id="8496402167048257517">Ойролцоо хуваалцах тохиргоог харуулна уу</translation>
+<translation id="8507563469658346379">Бүгд, <ph name="REMAINING_TIME" /></translation>
 <translation id="85123341071060231">Таны Chromebook-н Bluetooth унтраалттай байна. Chromebook-нхээ түгжээг тайлахын тулд нууц үг оруулна уу.</translation>
 <translation id="8513108775083588393">Автомат эргэх</translation>
 <translation id="851458219935658693">Одоогийн дэлгэцээс цонхыг харуулах, радио товчлуурыг сонгосон</translation>
diff --git a/ash/strings/ash_strings_sk.xtb b/ash/strings/ash_strings_sk.xtb
index 4645263..9631e375 100644
--- a/ash/strings/ash_strings_sk.xtb
+++ b/ash/strings/ash_strings_sk.xtb
@@ -733,6 +733,7 @@
 <translation id="492453977506755176">Kláves režimu snímania</translation>
 <translation id="4925542575807923399">Správca tohto účtu vyžaduje, aby sa tento účet v relácii viacnásobného prihlásenia prihlásil ako prvý.</translation>
 <translation id="4929163402621253029">Hovoríte? Máte vypnutý zvuk. Ďalšie informácie</translation>
+<translation id="4936329710968938986">Všetci, vypnuté</translation>
 <translation id="4938176435186993759">Skryť všetky návrhy</translation>
 <translation id="4945196315133970626">Vypnúť upozornenia</translation>
 <translation id="4946376291507881335">Nasnímať</translation>
@@ -1387,6 +1388,7 @@
 <translation id="8477270416194247200">Ak to chcete zrušiť, stlačte klávesy Alt+Hľadať alebo Shift.</translation>
 <translation id="8492573885090281069"><ph name="DISPLAY_NAME" /> nepodporuje rozlíšenie <ph name="SPECIFIED_RESOLUTION" />. Preto bolo zmenené na <ph name="FALLBACK_RESOLUTION" />. Zmeny ponecháte kliknutím na Potvrdiť. Predchádzajúce nastavenia budú obnovené o <ph name="TIMEOUT_SECONDS" />.</translation>
 <translation id="8496402167048257517">Zobraziť nastavenia Zdieľania nablízku</translation>
+<translation id="8507563469658346379">Všetci, <ph name="REMAINING_TIME" /></translation>
 <translation id="85123341071060231">V Chromebooku je vypnuté rozhranie Bluetooth. Ak chcete Chromebook odomknúť, zadajte heslo.</translation>
 <translation id="8513108775083588393">Aut. otáčanie</translation>
 <translation id="851458219935658693">Prepínač je prepnutý na možnosť zobrazenia okien z aktuálnej plochy</translation>
diff --git a/base/check.cc b/base/check.cc
index d263c76..0b1a2061 100644
--- a/base/check.cc
+++ b/base/check.cc
@@ -197,10 +197,6 @@
   return NotReachedError(log_message);
 }
 
-void NotReachedError::TriggerNotReached() {
-  NotReached("", -1);
-}
-
 NotReachedError::~NotReachedError() = default;
 
 void RawCheck(const char* message) {
diff --git a/base/check.h b/base/check.h
index 99db3eb..52bc2d4 100644
--- a/base/check.h
+++ b/base/check.h
@@ -101,10 +101,6 @@
  public:
   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.
-  NOMERGE NOINLINE NOT_TAIL_CALLED static void TriggerNotReached();
-
   // TODO(crbug.com/851128): Mark [[noreturn]] once this is CHECK-fatal on all
   // builds.
   NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedError();
diff --git a/base/check_unittest.cc b/base/check_unittest.cc
index 71560c2..280275c3 100644
--- a/base/check_unittest.cc
+++ b/base/check_unittest.cc
@@ -457,11 +457,6 @@
   // Expect LOG(ERROR) that looks like CHECK(false) with streamed params intact.
   EXPECT_LOG_ERROR(__LINE__, NOTREACHED() << "foo",
                    "Check failed: false. foo\n");
-#else
-  // Expect LOG(ERROR) that looks like CHECK(false) without file, line or
-  // streamed params.
-  EXPECT_LOG_ERROR_WITH_FILENAME("", -1, NOTREACHED() << "foo",
-                                 "Check failed: false. \n");
 #endif
 }
 
diff --git a/base/message_loop/message_pump_default.cc b/base/message_loop/message_pump_default.cc
index 789545c..96abf52 100644
--- a/base/message_loop/message_pump_default.cc
+++ b/base/message_loop/message_pump_default.cc
@@ -23,7 +23,7 @@
 namespace {
 
 #if BUILDFLAG(IS_APPLE)
-bool g_use_thread_qos = false;
+bool g_use_thread_qos = true;
 #endif
 
 }  // namespace
diff --git a/base/notreached.h b/base/notreached.h
index 8452758..ddbd80df 100644
--- a/base/notreached.h
+++ b/base/notreached.h
@@ -16,19 +16,21 @@
 // non-FATAL a crash report will be generated for the first NOTREACHED() that
 // hits per process.
 //
-// Outside DCHECK builds NOTREACHED() will LOG(ERROR) and also upload a crash
-// report without crashing in order to weed out prevalent NOTREACHED()s in the
-// wild before always turning NOTREACHED()s FATAL.
+// If `enable_log_error_not_reached` is enabled in the build then NOTREACHED()
+// builds will LOG(ERROR) and also upload a crash report without crashing in
+// order to weed out prevalent NOTREACHED()s in the wild before always turning
+// NOTREACHED()s FATAL.
 //
+// Without either of the above this currently does nothing. In the future (TODO
+// below) we should replace the #else branch here with base::ImmediateCrash() or
+// equivalent (and make ~NotReachedError()) FATAL and [[noreturn]].
 // TODO(crbug.com/851128): Turn NOTREACHED() FATAL and mark them [[noreturn]].
 #if CHECK_WILL_STREAM() || BUILDFLAG(ENABLE_LOG_ERROR_NOT_REACHED)
 #define NOTREACHED()   \
   CHECK_FUNCTION_IMPL( \
       ::logging::NotReachedError::NotReached(__FILE__, __LINE__), false)
 #else
-#define NOTREACHED()                                       \
-  (true) ? ::logging::NotReachedError::TriggerNotReached() \
-         : EAT_CHECK_STREAM_PARAMS()
+#define NOTREACHED() EAT_CHECK_STREAM_PARAMS()
 #endif
 
 // The NOTIMPLEMENTED() macro annotates codepaths which have not been
diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm
index 197d50e..1a332e33 100644
--- a/base/threading/platform_thread_mac.mm
+++ b/base/threading/platform_thread_mac.mm
@@ -92,7 +92,7 @@
 #endif
 );
 
-const Feature kUseThreadQoSMac{"UseThreadQoSMac", FEATURE_DISABLED_BY_DEFAULT};
+const Feature kUseThreadQoSMac{"UseThreadQoSMac", FEATURE_ENABLED_BY_DEFAULT};
 
 namespace {
 
@@ -328,6 +328,7 @@
       break;
     case ThreadType::kResourceEfficient:
       if (use_thread_qos) {
+        priority = ThreadPriorityForTest::kUtility;
         pthread_set_qos_class_self_np(QOS_CLASS_UTILITY, 0);
         break;
       }
diff --git a/base/threading/platform_thread_unittest.cc b/base/threading/platform_thread_unittest.cc
index 48b558f..a4e34ee 100644
--- a/base/threading/platform_thread_unittest.cc
+++ b/base/threading/platform_thread_unittest.cc
@@ -488,8 +488,13 @@
                                       ThreadPriorityForTest::kBackground);
   TestPriorityResultingFromThreadType(ThreadType::kUtility,
                                       ThreadPriorityForTest::kUtility);
+#if BUILDFLAG(IS_APPLE)
+  TestPriorityResultingFromThreadType(ThreadType::kResourceEfficient,
+                                      ThreadPriorityForTest::kUtility);
+#else
   TestPriorityResultingFromThreadType(ThreadType::kResourceEfficient,
                                       ThreadPriorityForTest::kNormal);
+#endif  // BUILDFLAG(IS_APPLE)
   TestPriorityResultingFromThreadType(ThreadType::kDefault,
                                       ThreadPriorityForTest::kNormal);
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 37272674..e974764 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-11.20230128.2.1
+11.20230129.3.1
diff --git a/chrome/VERSION b/chrome/VERSION
index 955ce67..691fce9 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=112
 MINOR=0
-BUILD=5567
+BUILD=5569
 PATCH=0
diff --git a/chrome/app/resources/generated_resources_cy.xtb b/chrome/app/resources/generated_resources_cy.xtb
index bd4dd40..c96b0b6 100644
--- a/chrome/app/resources/generated_resources_cy.xtb
+++ b/chrome/app/resources/generated_resources_cy.xtb
@@ -27,6 +27,7 @@
 <translation id="1017280919048282932">&amp;Ychwanegu at y geiriadur</translation>
 <translation id="1018656279737460067">Canslwyd</translation>
 <translation id="1022489261739821355">Wrthi'n dangos cyfrineiriau o'ch <ph name="BEGIN_LINK" />Cyfrif Google<ph name="END_LINK" /></translation>
+<translation id="1022669824195822609">Rheolir eich dyfais gan <ph name="DOMAIN" />. Gall gweinyddwyr gael mynediad at y data mewn unrhyw broffil ar y ddyfais hon.</translation>
 <translation id="1026655690966755180">Ychwanegu Porth</translation>
 <translation id="1026822031284433028">Llwytho llun</translation>
 <translation id="1028604629594230522">Mae Chrome yn rhaglwytho tudalennau rydych yn debygol o ymweld â nhw, fel eu bod yn llwytho yn gyflymach pan rydych yn ymweld â nhw.</translation>
@@ -1883,6 +1884,7 @@
 <translation id="2643064289437760082">Gallwch bob amser ddileu data mesur hysbyseb wrth ddileu eich data pori</translation>
 <translation id="2643698698624765890">Rheoli eich estyniadau drwy glicio Estyniadau yn y ddewislen Windows.</translation>
 <translation id="2645047101481282803">Rheolir eich dyfais gan <ph name="PROFILE_NAME" /></translation>
+<translation id="2645388244376970260">Wrthi'n castio'r tab hwn i <ph name="DEVICE_NAME" /></translation>
 <translation id="2645435784669275700">ChromeOS</translation>
 <translation id="2649045351178520408">Base64-encodiwyd ASCII, cadwyn tystysgrif</translation>
 <translation id="265156376773362237">Rhaglwytho safonol</translation>
@@ -2755,6 +2757,7 @@
 <translation id="3446274660183028131">Lansiwch Fwrdd Gwaith Parallels i osod Windows.</translation>
 <translation id="344630545793878684">Darllen eich data ar nifer o wefannau</translation>
 <translation id="3447644283769633681">Rhwystro pob cwci trydydd parti</translation>
+<translation id="3447797901512053632">Wrthi'n castio <ph name="TAB_NAME" /> i <ph name="DEVICE_NAME" /></translation>
 <translation id="3448492834076427715">Diweddaru'r cyfrif</translation>
 <translation id="3449393517661170867">ffenestr sydd mewn tab newydd</translation>
 <translation id="3449839693241009168">Pwyswch <ph name="SEARCH_KEY" /> i anfon gorchmynion at <ph name="EXTENSION_NAME" /></translation>
@@ -2909,6 +2912,7 @@
 <translation id="3590295622232282437">Wrthi'n dechrau sesiwn sydd wedi'i rheoli.</translation>
 <translation id="3591057288287063271">Cadw <ph name="FILE_NAME" /></translation>
 <translation id="3592260987370335752">&amp;Dysgu rhagor</translation>
+<translation id="3592344177526089979">Wrthi'n castio tab i <ph name="DEVICE_NAME" /></translation>
 <translation id="3593152357631900254">Galluogi'r modd Fuzzy-Pinyin</translation>
 <translation id="3593965109698325041">Cyfyngiadau Enw Tystysgrif</translation>
 <translation id="3596012367874587041">Gosodiadau ap</translation>
diff --git a/chrome/app/resources/generated_resources_fa.xtb b/chrome/app/resources/generated_resources_fa.xtb
index c5d2c3d15..ce64a21 100644
--- a/chrome/app/resources/generated_resources_fa.xtb
+++ b/chrome/app/resources/generated_resources_fa.xtb
@@ -27,6 +27,7 @@
 <translation id="1017280919048282932">&amp;افزودن به واژه‌نامه</translation>
 <translation id="1018656279737460067">لغو شده</translation>
 <translation id="1022489261739821355">‏درحال نمایش گذرواژه‌های ذخیره‌شده در <ph name="BEGIN_LINK" />حساب Google<ph name="END_LINK" /> شما</translation>
+<translation id="1022669824195822609">دستگاه شما تحت‌مدیریت <ph name="DOMAIN" /> قرار دارد. سرپرستان می‌توانند به داده‌های موجود در همه نمایه‌های این دستگاه دسترسی داشته باشند.</translation>
 <translation id="1026655690966755180">افزودن درگاه</translation>
 <translation id="1026822031284433028">بارگیری تصویر</translation>
 <translation id="1028604629594230522">‏Chrome صفحه‌هایی را که احتمالاً از آن‌ها بازدید خواهید کرد پیش‌بارگیری می‌کند، تا وقتی از آن‌ها بازدید می‌کنید سریع‌تر بار شوند.</translation>
@@ -1878,6 +1879,7 @@
 <translation id="2643064289437760082">هر زمان بخواهید می‌توانید با حذف کردن داده‌های مرورتان، داده‌های سنجش آگهی را حذف کنید</translation>
 <translation id="2643698698624765890">با کلیک کردن روی افزونه‌ها در منوی پنجره، برنامه‌های افزودنی نصب شده خود را مدیریت کنید.</translation>
 <translation id="2645047101481282803">دستگاهتان را <ph name="PROFILE_NAME" /> مدیریت می‌کند</translation>
+<translation id="2645388244376970260">درحال پخش محتوای این برگه به <ph name="DEVICE_NAME" /></translation>
 <translation id="2645435784669275700">ChromeOS</translation>
 <translation id="2649045351178520408">‏Base64-ASCII رمزگذاری‌شده، زنجیره گواهی</translation>
 <translation id="265156376773362237">پیش‌بارگذاری استاندارد</translation>
@@ -2750,6 +2752,7 @@
 <translation id="3446274660183028131">‏لطفاً برای نصب Windows، ‏Parallels Desktop را راه‌اندازی کنید.</translation>
 <translation id="344630545793878684">خواندن داده‌های شما در تعدادی از وب‌سایت‌ها</translation>
 <translation id="3447644283769633681">مسدود کردن همه کوکی‌های شخص ثالث</translation>
+<translation id="3447797901512053632">درحال پخش محتوای <ph name="TAB_NAME" /> به <ph name="DEVICE_NAME" /></translation>
 <translation id="3448492834076427715">به‌روزرسانی حساب</translation>
 <translation id="3449393517661170867">پنجره برگه‌دار جدید</translation>
 <translation id="3449839693241009168"><ph name="SEARCH_KEY" /> را فشار دهید تا فرمانها به <ph name="EXTENSION_NAME" /> ارسال شود</translation>
@@ -2904,6 +2907,7 @@
 <translation id="3590295622232282437">درحال ورود به جلسه مدیریت‌شده.</translation>
 <translation id="3591057288287063271">نگه داشتن <ph name="FILE_NAME" /></translation>
 <translation id="3592260987370335752">&amp;بیشتر بیاموزید</translation>
+<translation id="3592344177526089979">درحال پخش محتوای برگه به <ph name="DEVICE_NAME" /></translation>
 <translation id="3593152357631900254">‏فعال کردن حالت Fuzzy-Pinyin</translation>
 <translation id="3593965109698325041">محدودیتهای نام گواهی</translation>
 <translation id="3596012367874587041">تنظیمات برنامه</translation>
@@ -3179,6 +3183,7 @@
 <translation id="3823310065043511710">‏توصیه می‌شود حداقل <ph name="INSTALL_SIZE" />  فضا برای Linux داشته باشید.</translation>
 <translation id="3824621460022590830">کد ثبت‌نام دستگاه نامعتبر است. لطفاً با مالک یا سرپرست دستگاه تماس بگیرید. کد خطا: <ph name="ERROR_CODE" />.</translation>
 <translation id="3825041664272812989">{FILE_TYPE_COUNT,plural, =1{انتخاب من برای این نوع فایل به‌خاطر سپرده شود: <ph name="FILE_TYPES" />}one{انتخاب من برای این نوع فایل به‌خاطر سپرده شود: <ph name="FILE_TYPES" />}other{انتخاب من برای این نوع فایل‌ها به‌خاطر سپرده شود: <ph name="FILE_TYPES" />}}</translation>
+<translation id="3825635794653163640">نمایش نقطه روی نماد برنامه برای هشدارهای برنامه</translation>
 <translation id="3826071569074535339">اجازه دارد از حسگرهای حرکتی استفاده کند</translation>
 <translation id="3826440694796503677">‏سرپرستتان افزودن تعداد بیشتر «حساب Google» را غیرفعال کرده است</translation>
 <translation id="3827774300009121996">&amp;تمام صفحه</translation>
@@ -4499,6 +4504,7 @@
 <translation id="5063480226653192405">کاربر </translation>
 <translation id="5065775832226780415">Smart Lock</translation>
 <translation id="5066100345385738837">‏مدیریت ساناد امن در تنظیمات ChromeOS</translation>
+<translation id="5066160542186949327">انتقال به پوشه‌ای دیگر</translation>
 <translation id="5067399438976153555">همیشه روشن</translation>
 <translation id="5067867186035333991">اگر <ph name="HOST" /> می‌خواهد به میکروفن شما دسترسی داشته باشد از من سوال شود</translation>
 <translation id="5068553687099139861">نمایش گذرواژه‌ها</translation>
diff --git a/chrome/app/resources/generated_resources_mn.xtb b/chrome/app/resources/generated_resources_mn.xtb
index aa0a624..92f99a288 100644
--- a/chrome/app/resources/generated_resources_mn.xtb
+++ b/chrome/app/resources/generated_resources_mn.xtb
@@ -27,6 +27,7 @@
 <translation id="1017280919048282932">&amp;Толь бичигт нэмэх</translation>
 <translation id="1018656279737460067">Цуцлагдсан байна</translation>
 <translation id="1022489261739821355">Таны <ph name="BEGIN_LINK" />Google Бүртгэл<ph name="END_LINK" /> дээрх нууц үгнүүдийг харуулж байна</translation>
+<translation id="1022669824195822609">Таны төхөөрөмжийг <ph name="DOMAIN" />-с удирддаг. Администратор энэ төхөөрөмж дээрх дурын профайлын өгөгдөлд хандах боломжтой.</translation>
 <translation id="1026655690966755180">Порт нэмэх</translation>
 <translation id="1026822031284433028">Зураг ачаалах</translation>
 <translation id="1028604629594230522">Chrome таны зочлох магадлалтай хуудаснуудыг урьдчилан ачаалах бөгөөд ингэснээр тэдгээр нь таныг зочлох үед илүү хурдан ачаална.</translation>
@@ -1877,6 +1878,7 @@
 <translation id="2643064289437760082">Та интернэтээр үзсэн өгөгдлөө устгаснаар зарын хэмжилтийн өгөгдлийг мөн хэзээд устгах боломжтой</translation>
 <translation id="2643698698624765890">Window цэсэн дэх Өргөтгөлүүд хэсэг дээр дарж өөрийн өргөтгөлүүдээ удирд.</translation>
 <translation id="2645047101481282803">Таны төхөөрөмжийг <ph name="PROFILE_NAME" />-с удирддаг</translation>
+<translation id="2645388244376970260">Энэ табыг <ph name="DEVICE_NAME" />-д дамжуулж байна</translation>
 <translation id="2645435784669275700">ChromeOS</translation>
 <translation id="2649045351178520408">Base64-шифрлэгдсэн ASCII, гэрчилгээний хэлхээ</translation>
 <translation id="265156376773362237">Стандарт урьдчилан ачаалал</translation>
@@ -2749,6 +2751,7 @@
 <translation id="3446274660183028131">Windows-г суулгахын тулд Parallels Desktop-г эхлүүлнэ үү.</translation>
 <translation id="344630545793878684">Олон тооны веб хуудсууд дээр байгаа өөрийнхөө мэдээллийг уншина уу</translation>
 <translation id="3447644283769633681">Гуравдагч талын бүх күүкиг блоклох</translation>
+<translation id="3447797901512053632"><ph name="TAB_NAME" />-г <ph name="DEVICE_NAME" />-д дамжуулж байна</translation>
 <translation id="3448492834076427715">Бүртгэл шинэчлэх</translation>
 <translation id="3449393517661170867">Шинэ табтай цонх</translation>
 <translation id="3449839693241009168"><ph name="EXTENSION_NAME" /> руу коммандуудыг илгээхийн тулд <ph name="SEARCH_KEY" /> дээр дарна уу</translation>
@@ -2903,6 +2906,7 @@
 <translation id="3590295622232282437">Хяналттай харилцан үйлдлийг оруулж байна.</translation>
 <translation id="3591057288287063271"><ph name="FILE_NAME" />-г хадгалах</translation>
 <translation id="3592260987370335752">Дэлгэрэнгүй мэдээлэл</translation>
+<translation id="3592344177526089979">Табыг <ph name="DEVICE_NAME" />-д дамжуулж байна</translation>
 <translation id="3593152357631900254">Fuzzy-Pinyin горимыг идэвхжүүл</translation>
 <translation id="3593965109698325041">Сертификатын нэрийн хязгаарлалт</translation>
 <translation id="3596012367874587041">Aппын тохиргоо</translation>
@@ -3178,6 +3182,7 @@
 <translation id="3823310065043511710">Linux-д хамгийн багадаа <ph name="INSTALL_SIZE" />-н зайтай байхыг зөвлөж байна.</translation>
 <translation id="3824621460022590830">Төхөөрөмжийн бүртгэлийн тэмдэг буруу байна. Төхөөрөмж өмчлөгч эсвэл администратортайгаа холбогдоно уу. Алдааны код: <ph name="ERROR_CODE" />.</translation>
 <translation id="3825041664272812989">{FILE_TYPE_COUNT,plural, =1{Миний энэ файлын төрлийн сонголтыг санана уу: <ph name="FILE_TYPES" />}other{Миний эдгээр файлын төрлийн сонголтыг санана уу: <ph name="FILE_TYPES" />}}</translation>
+<translation id="3825635794653163640">Аппын сэрэмжлүүлгийн аппын дүрс тэмдэгт цэг харуулах</translation>
 <translation id="3826071569074535339">Хөдөлгөөн мэдрэгчийг ашиглахыг зөвшөөрсөн</translation>
 <translation id="3826440694796503677">Таны администратор илүү Google Бүртгэл нэмэхийг идэвхгүй болгосон</translation>
 <translation id="3827774300009121996">Бүтэн дэлгэцээр харуулах</translation>
@@ -4498,6 +4503,7 @@
 <translation id="5063480226653192405">Ашиглалт</translation>
 <translation id="5065775832226780415">Smart Lock</translation>
 <translation id="5066100345385738837">ChromeOS-н тохиргоо хэсэгт Аюулгүй DNS-г удирдана уу</translation>
+<translation id="5066160542186949327">Өөр фолдер луу зөөх</translation>
 <translation id="5067399438976153555">Үргэлж асаалттай</translation>
 <translation id="5067867186035333991"><ph name="HOST" /> таны микрофонд хандахыг хүсвэл асуу</translation>
 <translation id="5068553687099139861">нууц үг харуулах</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index 605473d..f764fd5 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -3173,6 +3173,7 @@
 <translation id="3823310065043511710">Na používanie systému Linux sa vyžaduje minimálne <ph name="INSTALL_SIZE" /> voľného priestoru.</translation>
 <translation id="3824621460022590830">Token registrácie zariadenia je neplatný. Kontaktujte vlastníka či správcu zariadenia. Kód chyby: <ph name="ERROR_CODE" />.</translation>
 <translation id="3825041664272812989">{FILE_TYPE_COUNT,plural, =1{Zapamätať môj výber pre tento typ súboru: <ph name="FILE_TYPES" />}few{Zapamätať môj výber pre tieto typy súborov: <ph name="FILE_TYPES" />}many{Remember my choice for these file types: <ph name="FILE_TYPES" />}other{Zapamätať môj výber pre tieto typy súborov: <ph name="FILE_TYPES" />}}</translation>
+<translation id="3825635794653163640">Zobrazujte si na ikone aplikácie bodku označujúcu upozornenia aplikácie</translation>
 <translation id="3826071569074535339">Môže používať senzory pohybu</translation>
 <translation id="3826440694796503677">Váš správca zakázal pridávanie ďalších účtov Google</translation>
 <translation id="3827774300009121996">&amp;Celá obrazovka</translation>
@@ -4492,6 +4493,7 @@
 <translation id="5063480226653192405">Použitie</translation>
 <translation id="5065775832226780415">Smart Lock</translation>
 <translation id="5066100345385738837">Správa zabezpečeného DNS v nastaveniach systému Chrome OS</translation>
+<translation id="5066160542186949327">Presunúť do iného priečinka</translation>
 <translation id="5067399438976153555">Vždy zapnuté</translation>
 <translation id="5067867186035333991">Opýtať sa, ak chcú stránky <ph name="HOST" /> pristupovať k mikrofónu</translation>
 <translation id="5068553687099139861">zobrazovať heslá</translation>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 776412ba..c779716e 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2613,18 +2613,6 @@
 };
 #endif  // BUILDFLAG(IS_ANDROID)
 
-const FeatureEntry::FeatureParam kCheckOfflineCapabilityWarnOnly[] = {
-    {"check_mode", "warn_only"}};
-const FeatureEntry::FeatureParam kCheckOfflineCapabilityEnforce[] = {
-    {"check_mode", "enforce"}};
-
-const FeatureEntry::FeatureVariation kCheckOfflineCapabilityVariations[] = {
-    {"Warn-only", kCheckOfflineCapabilityWarnOnly,
-     std::size(kCheckOfflineCapabilityWarnOnly), nullptr},
-    {"Enforce", kCheckOfflineCapabilityEnforce,
-     std::size(kCheckOfflineCapabilityEnforce), nullptr},
-};
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 const FeatureEntry::FeatureParam kProductivityLauncher_WithoutContinue[] = {
     {"enable_continue", "false"}};
@@ -7601,12 +7589,6 @@
      flag_descriptions::kBlockInsecureDownloadsDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kBlockInsecureDownloads)},
 
-    {"check-offline-capability", flag_descriptions::kCheckOfflineCapabilityName,
-     flag_descriptions::kCheckOfflineCapabilityDescription, kOsAll,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(blink::features::kCheckOfflineCapability,
-                                    kCheckOfflineCapabilityVariations,
-                                    "CheckOfflineCapability")},
-
     {"deferred-font-shaping", flag_descriptions::kDeferredFontShapingName,
      flag_descriptions::kDeferredFontShapingDescription, kOsAll,
      FEATURE_VALUE_TYPE(blink::features::kDeferredShaping)},
@@ -8396,13 +8378,6 @@
      FEATURE_VALUE_TYPE(ash::features::kDesksTemplates)},
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-    {"default-link-capturing-in-browser",
-     flag_descriptions::kDefaultLinkCapturingInBrowserName,
-     flag_descriptions::kDefaultLinkCapturingInBrowserDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(features::kDefaultLinkCapturingInBrowser)},
-#endif
-
     {"large-favicon-from-google",
      flag_descriptions::kLargeFaviconFromGoogleName,
      flag_descriptions::kLargeFaviconFromGoogleDescription, kOsAndroid,
@@ -8987,6 +8962,11 @@
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillParseVcnCardOnFileStandaloneCvcFields)},
 
+    {"background-resource-fetch",
+     flag_descriptions::kBackgroundResourceFetchName,
+     flag_descriptions::kBackgroundResourceFetchDescription, kOsAll,
+     FEATURE_VALUE_TYPE(blink::features::kBackgroundResourceFetch)},
+
 #if !BUILDFLAG(IS_ANDROID)
     {"desktop-partial-translate",
      flag_descriptions::kDesktopPartialTranslateName,
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_cache.cc b/chrome/browser/apps/app_deduplication_service/app_deduplication_cache.cc
index 0149496..1b46e09 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_cache.cc
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_cache.cc
@@ -6,42 +6,58 @@
 
 #include <string>
 
-#include "base/files/file.h"
+#include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
+#include "base/system/sys_info.h"
+
+namespace {
+// File name for the file where deduplication data is stored.
+constexpr char kAppDeduplicationDataFileName[] = "deduplication_data.pb";
+
+// Maximum size of App Deduplication Response is 1MB, current size of file
+// at initial launch (v1 of deduplication endpoint) is ~6KB.
+constexpr int kMaxRequiredDiskSpaceBytes = 1024 * 1024;
+}  // namespace
 
 namespace apps::deduplication {
 
-AppDeduplicationCache::AppDeduplicationCache(base::FilePath& path)
-    : folder_path_(path) {
-  if (!base::PathExists(folder_path_)) {
-    base::CreateDirectory(folder_path_);
+AppDeduplicationCache::AppDeduplicationCache(base::FilePath& path) {
+  file_path_ = path.AppendASCII(kAppDeduplicationDataFileName);
+  if (!base::PathExists(file_path_)) {
+    base::CreateDirectory(file_path_.DirName());
   }
 }
 
 AppDeduplicationCache::~AppDeduplicationCache() = default;
 
 bool AppDeduplicationCache::WriteDeduplicateDataToDisk(
-    const base::FilePath& deduplicate_data_path,
     proto::DeduplicateData& data) {
-  base::File file(deduplicate_data_path,
-                  (base::File::FLAG_CREATE | base::File::FLAG_WRITE));
-
-  if (!file.IsValid() || !file.created()) {
-    LOG(ERROR) << "Failed to create deduplicate data file at "
-               << deduplicate_data_path.MaybeAsASCII();
+  if (base::SysInfo::AmountOfFreeDiskSpace(file_path_.DirName()) <
+      kMaxRequiredDiskSpaceBytes) {
+    LOG(ERROR) << "Not enough disk space left.";
     return false;
   }
 
-  std::string deduplicate_data_string;
-  data.SerializeToString(&deduplicate_data_string);
+  // Create temporary file.
+  base::FilePath temp_file;
+  if (!base::CreateTemporaryFileInDir(file_path_.DirName(), &temp_file)) {
+    LOG(ERROR) << "Failed to create a temporary file.";
+    return false;
+  }
 
-  const int written = file.WriteAtCurrentPos(deduplicate_data_string.c_str(),
-                                             deduplicate_data_string.length());
+  // Write to temporary file.
+  std::string serialized_data = data.SerializeAsString();
+  if (!base::WriteFile(temp_file, serialized_data)) {
+    LOG(ERROR) << "Failed to write to temporary file.";
+    base::DeleteFile(temp_file);
+    return false;
+  }
 
-  if (written != static_cast<int>(deduplicate_data_string.length())) {
-    LOG(ERROR) << "Failed to write all data to deduplicate data file.";
-    base::DeleteFile(deduplicate_data_path);
+  // Replace the current file with the temporary file.
+  if (!base::ReplaceFile(temp_file, file_path_, /*error=*/nullptr)) {
+    LOG(ERROR) << "Failed to replace the temporary file.";
+    base::DeleteFile(temp_file);
     return false;
   }
 
@@ -49,17 +65,10 @@
 }
 
 absl::optional<proto::DeduplicateData>
-AppDeduplicationCache::ReadDeduplicateDataFromDisk(
-    const base::FilePath& deduplicate_data_path) {
+AppDeduplicationCache::ReadDeduplicateDataFromDisk() {
   std::string deduplicate_data_string;
 
-  if (!base::PathExists(deduplicate_data_path)) {
-    LOG(ERROR) << "Path to deduplicate data file does not exist.";
-    return absl::nullopt;
-  }
-
-  if (!base::ReadFileToString(deduplicate_data_path,
-                              &deduplicate_data_string)) {
+  if (!base::ReadFileToString(file_path_, &deduplicate_data_string)) {
     LOG(ERROR) << "Reading deduplicate data file from disk failed.";
     return absl::nullopt;
   }
@@ -69,6 +78,7 @@
     LOG(ERROR) << "Parsing proto to string failed.";
     return absl::nullopt;
   }
+
   return deduplicate_data;
 }
 
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_cache.h b/chrome/browser/apps/app_deduplication_service/app_deduplication_cache.h
index c85f2aa..818514d 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_cache.h
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_cache.h
@@ -11,10 +11,8 @@
 
 namespace apps::deduplication {
 
-// The AppDeduplicationCache is used to store deduplicate app data on disk and
-// read the stored data from disk. Two versions of the data will be stored to
-// the disk at a time in case reading data from the most recent version fails.
-// TODO(b/266005828): add functionality to store two versions of data.
+// The AppDeduplicationCache is used to store deduplicate app data on disk
+// and read the stored data from disk.
 class AppDeduplicationCache {
  public:
   // `path` refers to path of the folder on disk which will store the data.
@@ -23,17 +21,17 @@
   AppDeduplicationCache& operator=(const AppDeduplicationCache&) = delete;
   ~AppDeduplicationCache();
 
-  // Creates a file at given file path and stores duplicate data on disk.
-  // Returns true if all data is written successfully and false otherwise.
-  bool WriteDeduplicateDataToDisk(const base::FilePath& deduplicate_data_path,
-                                  proto::DeduplicateData& data);
+  // Writes data to deduplication file on disk. If the write operation
+  // fails, the existing data on disk will be unaffected. Returns true if
+  // data is written to disk successfully and false otherwise.
+  bool WriteDeduplicateDataToDisk(proto::DeduplicateData& data);
 
-  // Reads and returns deduplicate data from file at `deduplicate_data_path`.
-  absl::optional<proto::DeduplicateData> ReadDeduplicateDataFromDisk(
-      const base::FilePath& deduplicate_data_path);
+  // Reads and returns deduplicate data from file.
+  absl::optional<proto::DeduplicateData> ReadDeduplicateDataFromDisk();
 
  private:
-  base::FilePath folder_path_;
+  // Absolute path to the file where deduplication data is stored.
+  base::FilePath file_path_;
 };
 
 }  // namespace apps::deduplication
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_cache_unittest.cc b/chrome/browser/apps/app_deduplication_service/app_deduplication_cache_unittest.cc
index 2a88badd..aa00361 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_cache_unittest.cc
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_cache_unittest.cc
@@ -43,14 +43,13 @@
   app->set_app_id("com.skype.raidar");
   app->set_platform("phonehub");
 
-  const base::FilePath file_path = temp_dir_path_.AppendASCII("test.pb");
+  EXPECT_TRUE(cache_->WriteDeduplicateDataToDisk(data));
 
-  EXPECT_TRUE(cache_->WriteDeduplicateDataToDisk(file_path, data));
-
-  EXPECT_TRUE(base::PathExists(file_path));
+  EXPECT_TRUE(
+      base::PathExists(temp_dir_path_.AppendASCII("deduplication_data.pb")));
 
   absl::optional<proto::DeduplicateData> data_read =
-      cache_->ReadDeduplicateDataFromDisk(file_path);
+      cache_->ReadDeduplicateDataFromDisk();
 
   EXPECT_TRUE(data_read.has_value());
   EXPECT_EQ(data_read->app_group_size(), 1);
@@ -60,26 +59,34 @@
   EXPECT_EQ(observed_app.platform(), "phonehub");
 }
 
-TEST_F(AppDeduplicationCacheTest, WriteDataInvalidPath) {
-  proto::DeduplicateData data;
+TEST_F(AppDeduplicationCacheTest, WriteAndReadDataMultipleVersions) {
+  proto::DeduplicateData data_v1;
+  auto* app_v1 = data_v1.add_app_group()->add_app();
+  app_v1->set_app_id("com.skype.raidar");
+  app_v1->set_platform("phonehub");
 
-  EXPECT_FALSE(cache_->WriteDeduplicateDataToDisk(
-      temp_dir_path_.AppendASCII("fake_folder").AppendASCII("test.pb"), data));
-}
+  EXPECT_TRUE(cache_->WriteDeduplicateDataToDisk(data_v1));
+  EXPECT_TRUE(
+      base::PathExists(temp_dir_path_.AppendASCII("deduplication_data.pb")));
 
-TEST_F(AppDeduplicationCacheTest, ReadDataInvalidPath) {
-  proto::DeduplicateData data;
-  auto* app = data.add_app_group()->add_app();
-  app->set_app_id("com.skype.raidar");
-  app->set_platform("phonehub");
+  proto::DeduplicateData data_v2;
+  auto* app_v2 = data_v2.add_app_group()->add_app();
+  app_v2->set_app_id("https://web.skype.com/");
+  app_v2->set_platform("website");
 
-  EXPECT_TRUE(cache_->WriteDeduplicateDataToDisk(
-      temp_dir_path_.AppendASCII("test.pb"), data));
+  EXPECT_TRUE(cache_->WriteDeduplicateDataToDisk(data_v2));
+  EXPECT_TRUE(
+      base::PathExists(temp_dir_path_.AppendASCII("deduplication_data.pb")));
 
-  EXPECT_FALSE(cache_
-                   ->ReadDeduplicateDataFromDisk(
-                       temp_dir_path_.AppendASCII("fake_file.pb"))
-                   .has_value());
+  absl::optional<proto::DeduplicateData> data_read =
+      cache_->ReadDeduplicateDataFromDisk();
+
+  EXPECT_TRUE(data_read.has_value());
+  EXPECT_EQ(data_read->app_group_size(), 1);
+
+  auto observed_app = data_read->app_group(0).app(0);
+  EXPECT_EQ(observed_app.app_id(), "https://web.skype.com/");
+  EXPECT_EQ(observed_app.platform(), "website");
 }
 
 }  // namespace apps::deduplication
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.cc b/chrome/browser/apps/app_service/publishers/arc_apps.cc
index 3bdcdccc..cbb134b 100644
--- a/chrome/browser/apps/app_service/publishers/arc_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/arc_apps.cc
@@ -1288,13 +1288,11 @@
       continue;
     }
 
-    // When kDefaultLinkCapturingInBrowser is enabled, ignore any requests from
-    // ARC to set an app as handling supported links by default. We allow
-    // requests if they were initiated by user action, or if the app already
-    // has a non-default setting on the Ash side.
+    // Ignore any requests from the ARC system to set an app as handling
+    // supported links by default. We allow requests if they were initiated by
+    // user action, or if the app already has a non-default setting on the Ash
+    // side.
     bool should_ignore_update =
-        base::FeatureList::GetInstance()->IsEnabled(
-            features::kDefaultLinkCapturingInBrowser) &&
         AppShouldDefaultHandleLinksInBrowser(app_id) &&
         source == arc::mojom::SupportedLinkChangeSource::kArcSystem &&
         !proxy()->PreferredAppsList().IsPreferredAppForSupportedLinks(app_id);
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc b/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc
index 6a19da72..b337eae 100644
--- a/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc
+++ b/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/functional/callback_helpers.h"
 #include "base/strings/string_util.h"
 #include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/app_service_test.h"
@@ -28,7 +27,6 @@
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
-#include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/arc/intent_helper/intent_constants.h"
@@ -124,8 +122,6 @@
  public:
   void SetUp() override {
     testing::Test::SetUp();
-    scoped_feature_list_.InitAndDisableFeature(
-        features::kDefaultLinkCapturingInBrowser);
 
     // Do not destroy the ArcServiceManager during TearDown, so that Arc
     // KeyedServices can be correctly destroyed during profile shutdown.
@@ -221,7 +217,6 @@
 
  private:
   content::BrowserTaskEnvironment task_environment_;
-  base::test::ScopedFeatureList scoped_feature_list_;
   ArcAppTest arc_test_;
   TestingProfile profile_;
   apps::AppServiceTest app_service_test_;
@@ -230,9 +225,9 @@
   std::unique_ptr<arc::ArcFileSystemBridge> arc_file_system_bridge_;
 };
 
-// Verifies that a call to set the supported links preference from ARC persists
-// the setting in app service.
-TEST_F(ArcAppsPublisherTest, SetSupportedLinksFromArc) {
+// Verifies that a call to set the supported links preference from the ARC
+// system doesn't change the setting in app service.
+TEST_F(ArcAppsPublisherTest, SetSupportedLinksFromArcSystem) {
   constexpr char kTestAuthority[] = "www.example.com";
   const auto& fake_apps = arc_test()->fake_apps();
   std::string package_name = fake_apps[0]->package_name;
@@ -249,8 +244,8 @@
       CreateSupportedLinks(package_name), {},
       arc::mojom::SupportedLinkChangeSource::kArcSystem);
 
-  ASSERT_EQ(app_id, preferred_apps().FindPreferredAppForUrl(
-                        GURL("https://www.example.com/foo")));
+  ASSERT_EQ(absl::nullopt, preferred_apps().FindPreferredAppForUrl(
+                               GURL("https://www.example.com/foo")));
 }
 
 // Verifies that a call to set the supported links preference from App Service
@@ -273,36 +268,9 @@
       intent_helper_instance()->verified_links().find(package_name)->second);
 }
 
-// Verifies that when the behavior to open links in the browser by default is
-// enabled, Android apps are not set to handle links during first install.
-TEST_F(ArcAppsPublisherTest, SetSupportedLinksDefaultBrowserBehavior) {
-  base::test::ScopedFeatureList scoped_features(
-      features::kDefaultLinkCapturingInBrowser);
-
-  constexpr char kTestAuthority[] = "www.example.com";
-  const auto& fake_apps = arc_test()->fake_apps();
-  std::string package_name = fake_apps[0]->package_name;
-  std::string app_id = ArcAppListPrefs::GetAppId(fake_apps[0]->package_name,
-                                                 fake_apps[0]->activity);
-  arc_test()->app_instance()->SendRefreshAppList(fake_apps);
-
-  // Update intent filters and supported links for the app, as if it was just
-  // installed.
-  intent_helper()->OnIntentFiltersUpdatedForPackage(
-      package_name, CreateFilterList(package_name, {kTestAuthority}));
-  VerifyIntentFilters(app_id, {kTestAuthority});
-  intent_helper()->OnSupportedLinksChanged(
-      CreateSupportedLinks(package_name), {},
-      arc::mojom::SupportedLinkChangeSource::kArcSystem);
-
-  ASSERT_EQ(absl::nullopt, preferred_apps().FindPreferredAppForUrl(
-                               GURL("https://www.example.com/foo")));
-}
-
-// Verifies that when the behavior to open links in the browser by default is
-// enabled, apps which are already preferred can still update their filters.
-TEST_F(ArcAppsPublisherTest,
-       SetSupportedLinksDefaultBrowserBehaviorAllowsUpdates) {
+// Verifies that the ARC system can still update preferred intent filters for
+// apps which are already preferred.
+TEST_F(ArcAppsPublisherTest, SetSupportedLinksAllowsUpdates) {
   constexpr char kTestAuthority[] = "www.example.com";
   constexpr char kTestAuthority2[] = "www.newexample.com";
   const auto& fake_apps = arc_test()->fake_apps();
@@ -316,12 +284,10 @@
   intent_helper()->OnIntentFiltersUpdatedForPackage(
       package_name, CreateFilterList(package_name, {kTestAuthority}));
   VerifyIntentFilters(app_id, {kTestAuthority});
-  intent_helper()->OnSupportedLinksChanged(
-      CreateSupportedLinks(package_name), {},
-      arc::mojom::SupportedLinkChangeSource::kArcSystem);
 
-  base::test::ScopedFeatureList scoped_features(
-      features::kDefaultLinkCapturingInBrowser);
+  // Set a user preference for the app.
+  apps::AppServiceProxyFactory::GetForProfile(profile())
+      ->SetSupportedLinksPreference(app_id);
 
   // Update filters with a new authority added.
   intent_helper()->OnIntentFiltersUpdatedForPackage(
@@ -332,17 +298,13 @@
       CreateSupportedLinks(package_name), {},
       arc::mojom::SupportedLinkChangeSource::kArcSystem);
 
+  // Verify that the user preference has been extended to the new filter.
   ASSERT_EQ(app_id, preferred_apps().FindPreferredAppForUrl(
                         GURL("https://www.newexample.com/foo")));
 }
 
-// Verifies that when the behavior to open links in the browser by default is
-// enabled, the user can still set an app as preferred through ARC settings.
-TEST_F(ArcAppsPublisherTest,
-       SetSupportedLinksDefaultBrowserBehaviorAllowsUserChanges) {
-  base::test::ScopedFeatureList scoped_features(
-      features::kDefaultLinkCapturingInBrowser);
-
+// Verifies that the user can set an app as preferred through ARC settings.
+TEST_F(ArcAppsPublisherTest, SetSupportedLinksAllowsUserChanges) {
   constexpr char kTestAuthority[] = "www.example.com";
   const auto& fake_apps = arc_test()->fake_apps();
   std::string package_name = fake_apps[0]->package_name;
@@ -362,13 +324,8 @@
                         GURL("https://www.example.com/foo")));
 }
 
-// Verifies that when the behavior to open links in the browser by default is
-// enabled, the Play Store app can still be set as preferred by the system.
-TEST_F(ArcAppsPublisherTest,
-       SetSupportedLinksDefaultBrowserBehaviorAllowsPlayStore) {
-  base::test::ScopedFeatureList scoped_features(
-      features::kDefaultLinkCapturingInBrowser);
-
+// Verifies that the Play Store app can be set as preferred by the system.
+TEST_F(ArcAppsPublisherTest, SetSupportedLinksAllowsPlayStoreDefault) {
   constexpr char kTestAuthority[] = "play.google.com";
 
   std::vector<arc::mojom::AppInfoPtr> apps;
diff --git a/chrome/browser/apps/intent_helper/intent_picker_features.cc b/chrome/browser/apps/intent_helper/intent_picker_features.cc
index a50f516..57d21b3 100644
--- a/chrome/browser/apps/intent_helper/intent_picker_features.cc
+++ b/chrome/browser/apps/intent_helper/intent_picker_features.cc
@@ -3,13 +3,20 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/apps/intent_helper/intent_picker_features.h"
+
 #include "base/feature_list.h"
+#include "build/build_config.h"
 
 namespace apps::features {
 
 BASE_FEATURE(kLinkCapturingUiUpdate,
              "LinkCapturingUiUpdate",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+#if BUILDFLAG(IS_CHROMEOS)
+             base::FEATURE_ENABLED_BY_DEFAULT
+#else
+             base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+);
 
 BASE_FEATURE(kLinkCapturingInfoBar,
              "LinkCapturingInfoBar",
@@ -21,7 +28,12 @@
 
 BASE_FEATURE(kIntentChipAppIcon,
              "AppIconInIntentChip",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+#if BUILDFLAG(IS_CHROMEOS)
+             base::FEATURE_ENABLED_BY_DEFAULT
+#else
+             base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+);
 
 BASE_FEATURE(kLinkCapturingAutoDisplayIntentPicker,
              "LinkCapturingAutoDisplayIntentPicker",
diff --git a/chrome/browser/ash/app_list/search/OWNERS b/chrome/browser/ash/app_list/search/OWNERS
index eb3513f..af48bed 100644
--- a/chrome/browser/ash/app_list/search/OWNERS
+++ b/chrome/browser/ash/app_list/search/OWNERS
@@ -1,5 +1,6 @@
 amandadeacon@chromium.org
 chenjih@google.com
+laurencom@chromium.org
 tby@chromium.org
 thanhdng@chromium.org
 wrong@chromium.org
diff --git a/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc
index 8d632be99..6ca282b9 100644
--- a/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc
@@ -104,6 +104,58 @@
   EXPECT_GE(proto.weights()[1], 0.9);
 }
 
+TEST_F(FtrlRankerTest, TrainAndRankResultsWithMultipleProviders) {
+  // Set up an FTRL result ranker with two experts that statically return scores
+  // for eight items.
+  auto good_ranker = std::make_unique<TestRanker>();
+  auto bad_ranker = std::make_unique<TestRanker>();
+  good_ranker->SetNextScores({1.0, 2.0, 3.0, 4.0});
+  bad_ranker->SetNextScores({4.0, 3.0, 2.0, 1.0});
+
+  FtrlRanker ranker(FtrlRanker::RankingKind::kResults, TestingParams(2),
+                    FtrlOptimizer::Proto(GetPath(), base::Seconds(0)));
+  ranker.AddExpert(std::move(good_ranker));
+  ranker.AddExpert(std::move(bad_ranker));
+  Wait();
+
+  // Make four results within each provider and mimic several rank/train cycles
+  // where we always launch "h" from kFileSearch provider, so the good/bad
+  // ranker always performs well poorly.
+  ResultsMap results;
+  results[ResultType::kInstalledApp] = MakeResults({"a", "b", "c", "d"});
+  results[ResultType::kFileSearch] = MakeResults({"e", "f", "g", "h"});
+
+  for (int i = 0; i < 10; ++i) {
+    ranker.UpdateResultRanks(results, ResultType::kInstalledApp);
+    ranker.UpdateResultRanks(results, ResultType::kFileSearch);
+    ranker.Train(MakeLaunchData("h"));
+  }
+
+  // The weights of the FTRL optimizer should reflect that good_ranker is
+  // better than the bad_ranker and that Train() apply to results from both
+  // providers.
+  Wait();
+  auto proto = ReadProtoFromDisk<FtrlOptimizerProto>();
+  ASSERT_EQ(proto.weights_size(), 2);
+  EXPECT_GE(proto.weights()[0], 0.9);
+  EXPECT_LE(proto.weights()[1], 0.1);
+
+  // Now reverse the situation: change the clicked result so bad_ranker is
+  // now performing well.
+  for (int i = 0; i < 10; ++i) {
+    ranker.UpdateResultRanks(results, ResultType::kInstalledApp);
+    ranker.UpdateResultRanks(results, ResultType::kFileSearch);
+    ranker.Train(MakeLaunchData("a"));
+  }
+
+  // The weights of the 'bad' expert should have recovered.
+  Wait();
+  proto = ReadProtoFromDisk<FtrlOptimizerProto>();
+  ASSERT_EQ(proto.weights_size(), 2);
+  EXPECT_LE(proto.weights()[0], 0.1);
+  EXPECT_GE(proto.weights()[1], 0.9);
+}
+
 TEST_F(FtrlRankerTest, TrainAndRankCategories) {
   auto good_ranker = std::make_unique<TestRanker>();
   auto bad_ranker = std::make_unique<TestRanker>();
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 441b354..125f6a0 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
@@ -10,9 +10,11 @@
 
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
+#include "base/strings/strcat.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/system_info_util.h"
+#include "chrome/browser/ui/webui/settings/ash/device_storage_util.h"
 #include "chrome/common/channel_info.h"
 #include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h"
 #include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
@@ -22,15 +24,17 @@
 #include "components/version_info/version_info.h"
 #include "components/version_info/version_string.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/bytes_formatting.h"
 
 namespace app_list {
 namespace {
 
-using ProbeCategories = ash::cros_healthd::mojom::ProbeCategoryEnum;
-using ash::cros_healthd::mojom::BatteryInfo;
-using ash::cros_healthd::mojom::CpuInfo;
-using ash::cros_healthd::mojom::PhysicalCpuInfoPtr;
-using ash::cros_healthd::mojom::TelemetryInfoPtr;
+using SizeCalculator = ::ash::settings::SizeCalculator;
+using ProbeCategories = ::ash::cros_healthd::mojom::ProbeCategoryEnum;
+using ::ash::cros_healthd::mojom::BatteryInfo;
+using ::ash::cros_healthd::mojom::CpuInfo;
+using ::ash::cros_healthd::mojom::PhysicalCpuInfoPtr;
+using ::ash::cros_healthd::mojom::TelemetryInfoPtr;
 using ::ash::string_matching::FuzzyTokenizedStringMatch;
 using ::ash::string_matching::TokenizedString;
 
@@ -39,17 +43,25 @@
 }  // namespace
 
 SystemInfoCardProvider::SystemInfoCardProvider(Profile* profile)
-    : profile_(profile) {
+    : total_disk_space_calculator_(profile),
+      free_disk_space_calculator_(profile),
+      my_files_size_calculator_(profile),
+      browsing_data_size_calculator_(profile),
+      apps_size_calculator_(profile),
+      crostini_size_calculator_(profile),
+      profile_(profile) {
   DCHECK(profile_);
   ash::cros_healthd::ServiceConnection::GetInstance()->BindProbeService(
       probe_service_.BindNewPipeAndPassReceiver());
   probe_service_.set_disconnect_handler(
       base::BindOnce(&SystemInfoCardProvider::OnProbeServiceDisconnect,
                      weak_factory_.GetWeakPtr()));
+  StartObservingCalculators();
 }
 
 SystemInfoCardProvider::~SystemInfoCardProvider() {
   chromeos::PowerManagerClient::Get()->RemoveObserver(this);
+  StopObservingCalculators();
 }
 
 void SystemInfoCardProvider::Start(const std::u16string& query) {
@@ -57,7 +69,7 @@
   // stored in translation unit.
   std::vector<std::u16string> memory_keywords = {
       u"memory", u"memory usage", u"ram", u"ram usage", u"activity monitor"};
-  for (std::u16string keyword : memory_keywords) {
+  for (const std::u16string& keyword : memory_keywords) {
     if (CalculateRelevance(query, keyword) > kRelevanceThreshold) {
       UpdateMemoryUsage();
       break;
@@ -66,7 +78,7 @@
 
   std::vector<std::u16string> cpu_keywords = {
       u"cpu", u"cpu usage", u"device slow", u"why is my device slow"};
-  for (std::u16string keyword : cpu_keywords) {
+  for (const std::u16string& keyword : cpu_keywords) {
     if (CalculateRelevance(query, keyword) > kRelevanceThreshold) {
       UpdateCpuUsage();
       break;
@@ -75,7 +87,7 @@
 
   std::vector<std::u16string> battery_keywords = {u"battery", u"battery life",
                                                   u"battery health"};
-  for (std::u16string keyword : battery_keywords) {
+  for (const std::u16string& keyword : battery_keywords) {
     if (CalculateRelevance(query, keyword) > kRelevanceThreshold) {
       if (!chromeos::PowerManagerClient::Get()->HasObserver(this)) {
         chromeos::PowerManagerClient::Get()->AddObserver(this);
@@ -87,12 +99,25 @@
 
   std::vector<std::u16string> version_keywords = {u"version", u"my device",
                                                   u"about"};
-  for (std::u16string keyword : version_keywords) {
+  for (const std::u16string& keyword : version_keywords) {
     if (CalculateRelevance(query, keyword) > kRelevanceThreshold) {
       UpdateChromeOsVersion();
       break;
     }
   }
+
+  std::vector<std::u16string> storage_keywords = {u"storage", u"storage use",
+                                                  u"storage management"};
+  for (const std::u16string& keyword : storage_keywords) {
+    if (CalculateRelevance(query, keyword) > kRelevanceThreshold) {
+      // Do not calculate the storage size again if already calculated recently.
+      // TODO(b/263994165): Add in a refresh period here.
+      if (!calculation_state_.all()) {
+        UpdateStorageInfo();
+      }
+      break;
+    }
+  }
 }
 
 void SystemInfoCardProvider::StopQuery() {
@@ -264,9 +289,107 @@
 
   // TODO(b/263994165): Replace this with the correct translation string.
   chromeOS_version_ =
-      std::string("Version " + version + " (" + official + ") " +
-                  chrome::GetChannelName(chrome::WithExtendedStable(true)) +
-                  " " + processorVariation);
+      base::StrCat({"Version ", version, " (", official, ") ",
+                    chrome::GetChannelName(chrome::WithExtendedStable(true)),
+                    " ", processorVariation});
+}
+
+void SystemInfoCardProvider::UpdateStorageInfo() {
+  total_disk_space_calculator_.StartCalculation();
+  free_disk_space_calculator_.StartCalculation();
+  my_files_size_calculator_.StartCalculation();
+  browsing_data_size_calculator_.StartCalculation();
+  apps_size_calculator_.StartCalculation();
+  crostini_size_calculator_.StartCalculation();
+  other_users_size_calculator_.StartCalculation();
+}
+
+void SystemInfoCardProvider::StartObservingCalculators() {
+  total_disk_space_calculator_.AddObserver(this);
+  free_disk_space_calculator_.AddObserver(this);
+  my_files_size_calculator_.AddObserver(this);
+  browsing_data_size_calculator_.AddObserver(this);
+  apps_size_calculator_.AddObserver(this);
+  crostini_size_calculator_.AddObserver(this);
+  other_users_size_calculator_.AddObserver(this);
+}
+
+void SystemInfoCardProvider::StopObservingCalculators() {
+  total_disk_space_calculator_.RemoveObserver(this);
+  free_disk_space_calculator_.RemoveObserver(this);
+  my_files_size_calculator_.RemoveObserver(this);
+  browsing_data_size_calculator_.RemoveObserver(this);
+  apps_size_calculator_.RemoveObserver(this);
+  crostini_size_calculator_.RemoveObserver(this);
+  other_users_size_calculator_.RemoveObserver(this);
+}
+
+void SystemInfoCardProvider::OnSizeCalculated(
+    const SizeCalculator::CalculationType& calculation_type,
+    int64_t total_bytes) {
+  // The total disk space is rounded to the next power of 2.
+  if (calculation_type == SizeCalculator::CalculationType::kTotal) {
+    total_bytes = ash::settings::RoundByteSize(total_bytes);
+  }
+
+  // Store calculated item's size.
+  const int item_index = static_cast<int>(calculation_type);
+  storage_items_total_bytes_[item_index] = total_bytes;
+
+  // Mark item as calculated.
+  calculation_state_.set(item_index);
+  OnStorageInfoUpdated();
+}
+
+void SystemInfoCardProvider::OnStorageInfoUpdated() {
+  // If some size calculations are pending, return early and wait for all
+  // calculations to complete.
+  if (!calculation_state_.all()) {
+    return;
+  }
+
+  const int total_space_index =
+      static_cast<int>(SizeCalculator::CalculationType::kTotal);
+  const int free_disk_space_index =
+      static_cast<int>(SizeCalculator::CalculationType::kAvailable);
+
+  int64_t total_bytes = storage_items_total_bytes_[total_space_index];
+  int64_t available_bytes = storage_items_total_bytes_[free_disk_space_index];
+  int64_t in_use_bytes = total_bytes - available_bytes;
+
+  if (total_bytes <= 0 || available_bytes < 0) {
+    // We can't get useful information from the storage page if total_bytes <= 0
+    // or available_bytes is less than 0. This is not expected to happen.
+    NOTREACHED() << "Unable to retrieve total or available disk space";
+    return;
+  }
+
+  int64_t system_bytes = 0;
+  for (int i = 0; i < SizeCalculator::kCalculationTypeCount; ++i) {
+    const int64_t total_bytes_for_current_item =
+        std::max(storage_items_total_bytes_[i], static_cast<int64_t>(0));
+    // The total amount of disk space counts positively towards system's size.
+    if (i == static_cast<int>(SizeCalculator::CalculationType::kTotal)) {
+      if (total_bytes_for_current_item <= 0) {
+        return;
+      }
+      system_bytes += total_bytes_for_current_item;
+      continue;
+    }
+    // All other items are subtracted from the total amount of disk space.
+    if (i == static_cast<int>(SizeCalculator::CalculationType::kAvailable) &&
+        total_bytes_for_current_item < 0) {
+      return;
+    }
+    system_bytes -= total_bytes_for_current_item;
+  }
+  const int system_space_index =
+      static_cast<int>(SizeCalculator::CalculationType::kSystem);
+  storage_items_total_bytes_[system_space_index] = system_bytes;
+  std::u16string in_use_size = ui::FormatBytes(in_use_bytes);
+  std::u16string total_size = ui::FormatBytes(total_bytes);
+  // TODO(b/263994165): Add this string into an answer result.
+  std::u16string title = base::StrCat({in_use_size, u" in use / ", total_size});
 }
 
 }  // 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 49adb35..940e12d 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
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_SYSTEM_INFO_SYSTEM_INFO_CARD_PROVIDER_H_
 #define CHROME_BROWSER_ASH_APP_LIST_SEARCH_SYSTEM_INFO_SYSTEM_INFO_CARD_PROVIDER_H_
 
+#include <bitset>
 #include <memory>
 
 #include "base/memory/weak_ptr.h"
@@ -13,6 +14,7 @@
 #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/profiles/profile.h"
+#include "chrome/browser/ui/webui/settings/ash/calculator/size_calculator.h"
 #include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/dbus/power/power_manager_client.h"
@@ -25,10 +27,11 @@
 version, network information and memory usage. The answer cards link to the
 relevant pages within the Settings and Diagnostics apps.*/
 
-// TODO(b/263994165): Complete the System Info Card Provide to return results.
+// TODO(b/263994165): Complete the System Info Card Provider to return results.
 // This provider is a work in progress.
 class SystemInfoCardProvider : public SearchProvider,
-                               public chromeos::PowerManagerClient::Observer {
+                               public chromeos::PowerManagerClient::Observer,
+                               public ash::settings::SizeCalculator::Observer {
  public:
   explicit SystemInfoCardProvider(Profile* profile);
   ~SystemInfoCardProvider() override;
@@ -41,6 +44,11 @@
   void Start(const std::u16string& query) override;
   void StopQuery() override;
 
+  // SizeCalculator::Observer:
+  void OnSizeCalculated(
+      const ash::settings::SizeCalculator::CalculationType& calculation_type,
+      int64_t total_bytes) override;
+
  private:
   void BindCrosHealthdProbeServiceIfNecessary();
   void OnProbeServiceDisconnect();
@@ -67,6 +75,29 @@
 
   void UpdateChromeOsVersion();
 
+  void UpdateStorageInfo();
+  void StartObservingCalculators();
+  void OnStorageInfoUpdated();
+  void StopObservingCalculators();
+
+  // Instances calculating the size of each storage items.
+  ::ash::settings::TotalDiskSpaceCalculator total_disk_space_calculator_;
+  ::ash::settings::FreeDiskSpaceCalculator free_disk_space_calculator_;
+  ::ash::settings::MyFilesSizeCalculator my_files_size_calculator_;
+  ::ash::settings::BrowsingDataSizeCalculator browsing_data_size_calculator_;
+  ::ash::settings::AppsSizeCalculator apps_size_calculator_;
+  ::ash::settings::CrostiniSizeCalculator crostini_size_calculator_;
+  ::ash::settings::OtherUsersSizeCalculator other_users_size_calculator_;
+
+  // Keeps track of the size of each storage item. Adding 1 since we are also
+  // saving the system storage here
+  int64_t storage_items_total_bytes_
+      [::ash::settings::SizeCalculator::kCalculationTypeCount + 1] = {0};
+
+  // Controls if the size of each storage item has been calculated.
+  std::bitset<::ash::settings::SizeCalculator::kCalculationTypeCount>
+      calculation_state_;
+
   Profile* const profile_;
   mojo::Remote<ash::cros_healthd::mojom::CrosHealthdProbeService>
       probe_service_;
diff --git a/chrome/browser/ash/app_list/search/util/ftrl_optimizer_unittest.cc b/chrome/browser/ash/app_list/search/util/ftrl_optimizer_unittest.cc
index 2d777f4..3f1bdb1 100644
--- a/chrome/browser/ash/app_list/search/util/ftrl_optimizer_unittest.cc
+++ b/chrome/browser/ash/app_list/search/util/ftrl_optimizer_unittest.cc
@@ -158,4 +158,87 @@
   EXPECT_GT(proto.weights()[1], 0.9);
 }
 
+// Test training when there're more than 1 providers and that items
+// from different call of score was selected for training purpose.
+TEST_F(FtrlOptimizerTest, TrainWithMultipleProvidersDifferentScore) {
+  WriteWeightsToDisk({0.5, 0.5});
+  FtrlOptimizer ftrl(GetProto(), TestingParams(/*num_experts=*/2u));
+  Wait();
+
+  // Train when the selected result have higher score from the first expert.
+  ftrl.Score({"a", "b", "c", "d"},
+             {{1.0, 2.0, 3.0, 4.0}, {4.0, 3.0, 2.0, 1.0}});
+  ftrl.Score({"e", "f"}, {{1.0, 2.0}, {5.0, 1.0}});
+  ftrl.Train("d");
+  Wait();
+
+  // The first expert should outweigh the second.
+  auto proto = ReadFromDisk();
+  EXPECT_GT(proto.weights()[0], 0.52);
+  EXPECT_LT(proto.weights()[1], 0.48);
+
+  // Train when the selected result have higher
+  // score from the second expert.
+  ftrl.Train("e");
+  Wait();
+
+  // The second expert should outweigh the first.
+  proto = ReadFromDisk();
+  EXPECT_LT(proto.weights()[0], 0.49);
+  EXPECT_GT(proto.weights()[1], 0.51);
+}
+
+// Test if score has been successfully override.
+TEST_F(FtrlOptimizerTest, TrainWithMultipleProvidersOverrideScore) {
+  WriteWeightsToDisk({0.5, 0.5});
+  FtrlOptimizer ftrl(GetProto(), TestingParams(/*num_experts=*/2u));
+  Wait();
+
+  // Call score twice with same items, the latest one score call
+  // should override the older one.
+  ftrl.Score({"a", "b", "c", "d"},
+             {{1.0, 2.0, 3.0, 4.0}, {4.0, 3.0, 2.0, 1.0}});
+  ftrl.Score({"a", "b", "c", "d"},
+             {{4.0, 3.0, 2.0, 1.0}, {1.0, 2.0, 3.0, 4.0}});
+  ftrl.Train("d");
+  Wait();
+
+  // The second expert should outweigh the first.
+  auto proto = ReadFromDisk();
+  EXPECT_LT(proto.weights()[0], 0.35);
+  EXPECT_GT(proto.weights()[1], 0.65);
+}
+
+// Test if the last_expert_scores_ is empty after calling Clear.
+TEST_F(FtrlOptimizerTest, Clear) {
+  WriteWeightsToDisk({0.5, 0.5});
+  FtrlOptimizer ftrl(GetProto(), TestingParams(/*num_experts=*/2u));
+  Wait();
+
+  // Call Clear() after calling Score(). Train should have no effect on weights.
+  ftrl.Score({"a", "b", "c", "d"},
+             {{1.0, 2.0, 3.0, 4.0}, {4.0, 3.0, 2.0, 1.0}});
+  ftrl.Clear();
+  ftrl.Train("d");
+  Wait();
+
+  // The weight should not change since the last_expert_scores_ is empty.
+  // The loss should return 0.
+  auto proto = ReadFromDisk();
+  EXPECT_EQ(proto.weights()[0], 0.5);
+  EXPECT_EQ(proto.weights()[1], 0.5);
+
+  // Call the Clear() after training.
+  ftrl.Score({"a", "b", "c", "d"},
+             {{1.0, 2.0, 3.0, 4.0}, {4.0, 3.0, 2.0, 1.0}});
+  ftrl.Train("d");
+  ftrl.Clear();
+  Wait();
+
+  // The weights should be trained normally.
+  proto = ReadFromDisk();
+  EXPECT_GT(proto.weights()[0], 0.65);
+  EXPECT_LT(proto.weights()[1], 0.35);
+}
+
 }  // namespace app_list::test
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.cc b/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.cc
index df3f941..493788b 100644
--- a/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.cc
+++ b/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.cc
@@ -304,10 +304,18 @@
     // Destination is a virtual filesystem, so skip checking free space.
     GenerateDestinationURL(0);
   } else {
+    // For Drive, check we have enough local disk first, then check quota.
+    base::FilePath path = progress_.destination_folder.path();
+    auto* drive_integration_service =
+        drive::util::GetIntegrationServiceByProfile(profile_);
+    if (drive_integration_service && drive_integration_service->IsMounted() &&
+        drive_integration_service->GetMountPointPath().IsParent(
+            progress_.destination_folder.path())) {
+      path = drive_integration_service->GetDriveFsHost()->GetDataPath();
+    }
     base::ThreadPool::PostTaskAndReplyWithResult(
         FROM_HERE, {base::MayBlock()},
-        base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
-                       progress_.destination_folder.path()),
+        base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace, path),
         base::BindOnce(&CopyOrMoveIOTaskImpl::GotFreeDiskSpace,
                        weak_ptr_factory_.GetWeakPtr()));
   }
@@ -317,11 +325,13 @@
 void CopyOrMoveIOTaskImpl::GotFreeDiskSpace(int64_t free_space) {
   auto* drive_integration_service =
       drive::util::GetIntegrationServiceByProfile(profile_);
+  bool is_drive = drive_integration_service &&
+                  drive_integration_service->IsMounted() &&
+                  drive_integration_service->GetMountPointPath().IsParent(
+                      progress_.destination_folder.path());
   if (progress_.destination_folder.filesystem_id() ==
           util::GetDownloadsMountPointName(profile_) ||
-      (drive_integration_service &&
-       drive_integration_service->GetMountPointPath().IsParent(
-           progress_.destination_folder.path()))) {
+      is_drive) {
     free_space -= cryptohome::kMinFreeSpaceInBytes;
   }
 
@@ -345,6 +355,42 @@
     return;
   }
 
+  if (is_drive) {
+    drive_integration_service->GetPooledQuotaUsage(base::BindOnce(
+        base::BindOnce(&CopyOrMoveIOTaskImpl::GotDrivePooledQuota,
+                       weak_ptr_factory_.GetWeakPtr(), required_bytes)));
+    return;
+  }
+
+  GenerateDestinationURL(0);
+}
+
+void CopyOrMoveIOTaskImpl::GotDrivePooledQuota(
+    int64_t required_bytes,
+    drive::FileError error,
+    drivefs::mojom::PooledQuotaUsagePtr usage) {
+  if (error != drive::FileError::FILE_ERROR_OK) {
+    // Log the error if we couldn't fetch the quota (probably because we are
+    // offline), but continue the operation and we will show an error later
+    // when we come back online and try to sync.
+    LOG(ERROR) << "Error fetching drive quota: "
+               << drive::FileErrorToString(error);
+  } else {
+    bool org_exceeded =
+        usage->user_type == drivefs::mojom::UserType::kOrganization &&
+        usage->organization_limit_exceeded;
+    bool user_exceeded =
+        usage->total_user_bytes != -1 &&
+        (usage->total_user_bytes - usage->used_user_bytes) < required_bytes;
+    if (org_exceeded || user_exceeded) {
+      progress_.outputs.emplace_back(progress_.destination_folder,
+                                     base::File::FILE_ERROR_NO_SPACE);
+      LOG(ERROR) << "Insufficient drive quota";
+      Complete(State::kError);
+      return;
+    }
+  }
+
   GenerateDestinationURL(0);
 }
 
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h b/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h
index 46d0ee8..58e64b8 100644
--- a/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h
+++ b/chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h
@@ -13,11 +13,14 @@
 #include "base/containers/flat_map.h"
 #include "base/files/file.h"
 #include "base/files/file_error_or.h"
+#include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/file_manager/file_manager_copy_or_move_hook_delegate.h"
 #include "chrome/browser/ash/file_manager/io_task.h"
 #include "chrome/browser/ash/file_manager/speedometer.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chromeos/ash/components/drivefs/mojom/drivefs.mojom.h"
+#include "components/drive/file_errors.h"
 #include "storage/browser/file_system/file_system_context.h"
 #include "storage/browser/file_system/file_system_operation_runner.h"
 #include "storage/browser/file_system/file_system_url.h"
@@ -104,6 +107,9 @@
   ProgressCallback progress_callback_;
 
  private:
+  friend class CopyOrMoveIOTaskTest;
+  FRIEND_TEST_ALL_PREFIXES(CopyOrMoveIOTaskTest, DriveQuota);
+
   // Verifies the transfer, e.g., by using enterprise connectors for checking
   // whether a transfer is allowed.
   virtual void VerifyTransfer();
@@ -120,6 +126,9 @@
                    base::File::Error error,
                    const base::File::Info& file_info);
   void GotFreeDiskSpace(int64_t free_space);
+  void GotDrivePooledQuota(int64_t required_bytes,
+                           drive::FileError error,
+                           drivefs::mojom::PooledQuotaUsagePtr usage);
   void GenerateDestinationURL(size_t idx);
   void CopyOrMoveFile(
       size_t idx,
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task_unittest.cc b/chrome/browser/ash/file_manager/copy_or_move_io_task_unittest.cc
index 11e9b11..49c56ba1 100644
--- a/chrome/browser/ash/file_manager/copy_or_move_io_task_unittest.cc
+++ b/chrome/browser/ash/file_manager/copy_or_move_io_task_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/functional/callback_helpers.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
+#include "base/test/bind.h"
 #include "base/test/gmock_callback_support.h"
 #include "base/test/mock_callback.h"
 #include "chrome/browser/ash/file_manager/copy_or_move_io_task_impl.h"
@@ -32,6 +33,7 @@
 #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/drivefs/mojom/drivefs.mojom.h"
 #include "content/public/test/browser_task_environment.h"
 #include "storage/browser/file_system/file_system_url.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
@@ -54,7 +56,6 @@
 
 namespace file_manager {
 namespace io_task {
-namespace {
 
 MATCHER_P(EntryStatusUrls, matcher, "") {
   std::vector<storage::FileSystemURL> urls;
@@ -113,6 +114,22 @@
         base::FilePath::FromUTF8Unsafe(path));
   }
 
+  State CheckDriveQuota(drive::FileError error,
+                        drivefs::mojom::PooledQuotaUsagePtr usage) {
+    ProgressStatus progress;
+    progress.sources.emplace_back(CreateFileSystemURL("foo.txt"),
+                                  absl::nullopt);
+    base::CreateDirectory(temp_dir_.GetPath().Append("dest_folder"));
+    progress.destination_folder = CreateFileSystemURL("dest_folder/");
+    CopyOrMoveIOTaskImpl task(GetParam(), progress, {}, CreateFileSystemURL(""),
+                              &profile_, file_system_context_);
+    task.complete_callback_ = base::BindLambdaForTesting(
+        [&](ProgressStatus completed) { progress.state = completed.state; });
+    progress.state = State::kQueued;
+    task.GotDrivePooledQuota(10, error, std::move(usage));
+    return progress.state;
+  }
+
   content::BrowserTaskEnvironment task_environment_;
   file_manager::FakeDiskMountManager disk_mount_manager_;
   TestingProfile profile_;
@@ -428,6 +445,50 @@
       bar_contents);
 }
 
+TEST_P(CopyOrMoveIOTaskTest, DriveQuota) {
+  // Enough quota should succeed.
+  auto usage = drivefs::mojom::PooledQuotaUsage::New();
+  usage->user_type = drivefs::mojom::UserType::kUnmanaged;
+  usage->total_user_bytes = 100;
+  usage->used_user_bytes = 0;
+  EXPECT_EQ(State::kQueued,
+            CheckDriveQuota(drive::FileError::FILE_ERROR_OK, std::move(usage)));
+
+  // Organization exceeded quota should fail.
+  usage = drivefs::mojom::PooledQuotaUsage::New();
+  usage->user_type = drivefs::mojom::UserType::kOrganization;
+  usage->total_user_bytes = 100;
+  usage->used_user_bytes = 0;
+  usage->organization_limit_exceeded = true;
+  EXPECT_EQ(State::kError,
+            CheckDriveQuota(drive::FileError::FILE_ERROR_OK, std::move(usage)));
+
+  // User unlimited quota should succeed.
+  usage = drivefs::mojom::PooledQuotaUsage::New();
+  usage->user_type = drivefs::mojom::UserType::kUnmanaged;
+  usage->total_user_bytes = -1;
+  usage->used_user_bytes = 100;
+  EXPECT_EQ(State::kQueued,
+            CheckDriveQuota(drive::FileError::FILE_ERROR_OK, std::move(usage)));
+
+  // User exceeded quota should fail.
+  usage = drivefs::mojom::PooledQuotaUsage::New();
+  usage->user_type = drivefs::mojom::UserType::kUnmanaged;
+  usage->total_user_bytes = 100;
+  usage->used_user_bytes = 100;
+  EXPECT_EQ(State::kError,
+            CheckDriveQuota(drive::FileError::FILE_ERROR_OK, std::move(usage)));
+
+  // Error fetching quota should succeed.
+  usage = drivefs::mojom::PooledQuotaUsage::New();
+  usage->user_type = drivefs::mojom::UserType::kUnmanaged;
+  usage->total_user_bytes = 100;
+  usage->used_user_bytes = 100;
+  EXPECT_EQ(State::kQueued,
+            CheckDriveQuota(drive::FileError::FILE_ERROR_NO_CONNECTION,
+                            std::move(usage)));
+}
+
 INSTANTIATE_TEST_SUITE_P(CopyOrMove,
                          CopyOrMoveIOTaskTest,
                          testing::Values(OperationType::kCopy,
@@ -1174,8 +1235,6 @@
                                          OperationType::kMove),
                          &CopyOrMoveIOTaskWithScansTest::ParamToString);
 
-}  // namespace
-
 class CopyOrMoveIsCrossFileSystemTest : public testing::Test {
  public:
   CopyOrMoveIsCrossFileSystemTest() = default;
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
index 59b09d6..b035d38 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -199,6 +199,11 @@
     return *this;
   }
 
+  TestCase& EnableBulkPinning() {
+    options.enable_drive_bulk_pinning = true;
+    return *this;
+  }
+
   TestCase& SetDeviceMode(DeviceMode device_mode) {
     options.device_mode = device_mode;
     return *this;
@@ -262,6 +267,10 @@
       full_name += "_GoogleOneOfferFilesBanner";
     }
 
+    if (options.enable_drive_bulk_pinning) {
+      full_name += "_DriveBulkPinning";
+    }
+
     switch (options.device_mode) {
       case DEVICE_MODE_NOT_SET:
         break;
@@ -1456,7 +1465,8 @@
         TestCase("driveOfflineInfoBanner"),
         TestCase("driveDeleteDialogDoesntMentionPermanentDelete"),
         TestCase("driveInlineSyncStatusSingleFile").EnableInlineStatusSync(),
-        TestCase("driveInlineSyncStatusParentFolder").EnableInlineStatusSync()
+        TestCase("driveInlineSyncStatusParentFolder").EnableInlineStatusSync(),
+        TestCase("driveLocalDeleteUnpinsItem").EnableBulkPinning()
         // TODO(b/189173190): Enable
         // TestCase("driveEnableDocsOfflineDialog"),
         // TODO(b/189173190): Enable
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
index f9a1b00..cab9633 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -1325,6 +1325,10 @@
     return last_dialog_result_;
   }
 
+  absl::optional<bool> IsItemPinned(const std::string& path) {
+    return fake_drivefs_helper_->fake_drivefs().IsItemPinned(path);
+  }
+
  private:
   base::RepeatingCallback<std::unique_ptr<drivefs::DriveFsBootstrapListener>()>
   CreateDriveFsBootstrapListener() {
@@ -2002,6 +2006,12 @@
     disabled_features.push_back(ash::features::kGoogleOneOfferFilesBanner);
   }
 
+  if (options.enable_drive_bulk_pinning) {
+    enabled_features.push_back(ash::features::kDriveFsBulkPinning);
+  } else {
+    disabled_features.push_back(ash::features::kDriveFsBulkPinning);
+  }
+
   // This is destroyed in |TearDown()|. We cannot initialize this in the
   // constructor due to this feature values' above dependence on virtual
   // method calls, but by convention subclasses of this fixture may initialize
@@ -3247,6 +3257,15 @@
     return;
   }
 
+  if (name == "isItemPinned") {
+    const std::string* path = value.FindString("path");
+    ASSERT_TRUE(path) << "No supplied path to isItemPinned";
+    absl::optional<bool> is_pinned = drive_volume_->IsItemPinned(*path);
+    ASSERT_TRUE(is_pinned.has_value()) << "Supplied path is unknown: " << *path;
+    base::JSONWriter::Write(base::Value(is_pinned.value()), output);
+    return;
+  }
+
   if (HandleGuestOsCommands(name, value, output)) {
     return;
   }
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.h b/chrome/browser/ash/file_manager/file_manager_browsertest_base.h
index 5c1870f1..18e7cbd 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.h
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.h
@@ -159,6 +159,9 @@
 
     // Whether tests should enable Google One offer Files banner.
     bool enable_google_one_offer_files_banner = false;
+
+    // Whether tests should enable the Google Drive bulk pinning feature.
+    bool enable_drive_bulk_pinning = false;
   };
 
   FileManagerBrowserTestBase(const FileManagerBrowserTestBase&) = delete;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index fff3bee0..e40c270 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -671,6 +671,11 @@
     "expiry_milestone": 115
   },
   {
+    "name": "background-resource-fetch",
+    "owners": ["horo"],
+    "expiry_milestone": 115
+  },
+  {
     "name": "battery-saver-mode-available",
     "owners": [ "chrome-performance-ui-team@google.com" ],
     "expiry_milestone": 115
@@ -948,11 +953,6 @@
     "expiry_milestone": 115
   },
   {
-    "name": "check-offline-capability",
-    "owners": [ "asamidoi", "//content/browser/service_worker/OWNERS" ],
-    "expiry_milestone": 93
-  },
-  {
     "name": "chip-location-bar-icon-override",
     "owners": [
       "fjacky",
@@ -1328,11 +1328,6 @@
     "expiry_milestone": 104
   },
   {
-    "name": "default-link-capturing-in-browser",
-    "owners": [ "tsergeant", "chromeos-apps-foundation-team@google.com"],
-    "expiry_milestone": 112
-  },
-  {
     "name": "deferred-font-shaping",
     "owners": [ "tkent", "layout-dev" ],
     "expiry_milestone": 122
@@ -1602,7 +1597,7 @@
   {
     "name": "drive-fs-chrome-networking",
     "owners": [ "travislane@google.com" ],
-    "expiry_milestone": 112
+    "expiry_milestone": 115
   },
   {
     "name": "drop-input-events-before-first-paint",
@@ -4343,12 +4338,12 @@
   {
     "name": "intent-chip-app-icon",
     "owners": ["tsergeant", "chromeos-apps-foundation-team@google.com"],
-    "expiry_milestone": 112
+    "expiry_milestone": 115
   },
   {
     "name": "intent-chip-skips-intent-picker",
     "owners": ["tsergeant", "chromeos-apps-foundation-team@google.com"],
-    "expiry_milestone": 112
+    "expiry_milestone": 115
   },
   {
     "name": "intents-on-email",
@@ -4645,17 +4640,17 @@
   {
     "name": "link-capturing-auto-display-intent-picker",
     "owners": [ "tsergeant", "chromeos-apps-foundation-team@google.com" ],
-    "expiry_milestone": 112
+    "expiry_milestone": 115
   },
   {
     "name": "link-capturing-infobar",
     "owners": ["tsergeant", "chromeos-apps-foundation-team@google.com"],
-    "expiry_milestone": 112
+    "expiry_milestone": 115
   },
   {
     "name": "link-capturing-ui-update",
     "owners": ["tsergeant", "chromeos-apps-foundation-team@google.com"],
-    "expiry_milestone": 112
+    "expiry_milestone": 115
   },
   {
     "name": "list-all-display-modes",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 0cbccc6..1f8acfa 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -89,6 +89,10 @@
     "reporting delays and noise. Only works if the Attribution Reporting API "
     "is already enabled.";
 
+const char kBackgroundResourceFetchName[] = "Background Resource Fetch";
+const char kBackgroundResourceFetchDescription[] =
+    "Process resource requests in a background thread inside Blink.";
+
 const char kBlockInsecureDownloadsName[] = "Block insecure downloads";
 const char kBlockInsecureDownloadsDescription[] =
     "Enables insecure download blocking. This shows a 'blocked' message if the "
@@ -666,11 +670,6 @@
     "and handles subresources. If the main resource could be handled in the "
     "fetch handler, the feature may affect the page load.";
 
-const char kCheckOfflineCapabilityName[] = "Check offline capability for PWAs";
-const char kCheckOfflineCapabilityDescription[] =
-    "Use advanced offline capability check to decide whether the browser "
-    "displays install prompts for PWAs.";
-
 const char kChromeLabsName[] = "Chrome Labs";
 const char kChromeLabsDescription[] =
     "Access Chrome Labs through the toolbar menu to see featured user-facing "
@@ -4878,12 +4877,6 @@
     "the system logs, where they are potentially visible to all users of the "
     "device.";
 
-const char kDefaultLinkCapturingInBrowserName[] =
-    "Default link capturing in the browser";
-const char kDefaultLinkCapturingInBrowserDescription[] =
-    "When enabled, newly installed apps will not capture links clicked in the "
-    "browser.";
-
 extern const char kDesks16Name[] = "Enable up to 16 virtual desks";
 extern const char kDesks16Description[] =
     "When enabled, up to 16 virtual desks are allowed.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 0a9188d4..1abee7b 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -80,6 +80,9 @@
 extern const char kAppDeduplicationServiceFondueName[];
 extern const char kAppDeduplicationServiceFondueDescription[];
 
+extern const char kBackgroundResourceFetchName[];
+extern const char kBackgroundResourceFetchDescription[];
+
 extern const char kBlockInsecureDownloadsName[];
 extern const char kBlockInsecureDownloadsDescription[];
 
@@ -367,9 +370,6 @@
 extern const char kCanvasOopRasterizationName[];
 extern const char kCanvasOopRasterizationDescription[];
 
-extern const char kCheckOfflineCapabilityName[];
-extern const char kCheckOfflineCapabilityDescription[];
-
 extern const char kChromeLabsName[];
 extern const char kChromeLabsDescription[];
 
@@ -2794,9 +2794,6 @@
 extern const char kCalendarModelDebugModeName[];
 extern const char kCalendarModelDebugModeDescription[];
 
-extern const char kDefaultLinkCapturingInBrowserName[];
-extern const char kDefaultLinkCapturingInBrowserDescription[];
-
 extern const char kCaptureModeDemoToolsName[];
 extern const char kCaptureModeDemoToolsDescription[];
 
diff --git a/chrome/browser/lacros/input_method_lacros_browsertest.cc b/chrome/browser/lacros/input_method_lacros_browsertest.cc
index 784670f..47da4b74 100644
--- a/chrome/browser/lacros/input_method_lacros_browsertest.cc
+++ b/chrome/browser/lacros/input_method_lacros_browsertest.cc
@@ -245,6 +245,31 @@
 }
 
 IN_PROC_BROWSER_TEST_F(InputMethodLacrosBrowserTest,
+                       CommitEmptyTextDeletesCompositionText) {
+  mojo::Remote<InputMethodTestInterface> input_method =
+      BindInputMethodTestInterface(
+          {InputMethodTestInterface::MethodMinVersions::kWaitForFocusMinVersion,
+           InputMethodTestInterface::MethodMinVersions::
+               kSetCompositionMinVersion,
+           InputMethodTestInterface::MethodMinVersions::kCommitTextMinVersion});
+  if (!input_method.is_bound()) {
+    GTEST_SKIP() << "Unsupported ash version";
+  }
+  const std::string id = RenderAutofocusedInputFieldInLacros(browser());
+  InputMethodTestInterfaceAsyncWaiter input_method_async_waiter(
+      input_method.get());
+  input_method_async_waiter.WaitForFocus();
+  input_method_async_waiter.SetComposition("hello", 5);
+  ASSERT_TRUE(WaitUntilInputFieldHasText(GetActiveWebContents(browser()), id,
+                                         "hello", gfx::Range(5)));
+
+  input_method_async_waiter.CommitText("");
+
+  EXPECT_TRUE(WaitUntilInputFieldHasText(GetActiveWebContents(browser()), id,
+                                         "", gfx::Range(0)));
+}
+
+IN_PROC_BROWSER_TEST_F(InputMethodLacrosBrowserTest,
                        CommitTextReplacesSelection) {
   mojo::Remote<InputMethodTestInterface> input_method =
       BindInputMethodTestInterface(
@@ -411,6 +436,45 @@
 }
 
 IN_PROC_BROWSER_TEST_F(InputMethodLacrosBrowserTest,
+                       SendBackspaceDeletesNonEmptyTextField) {
+  mojo::Remote<InputMethodTestInterface> input_method =
+      BindInputMethodTestInterface(
+          {InputMethodTestInterface::MethodMinVersions::kWaitForFocusMinVersion,
+           InputMethodTestInterface::MethodMinVersions::
+               kKeyEventHandledMinVersion});
+  if (!input_method.is_bound()) {
+    GTEST_SKIP() << "Unsupported ash version";
+  }
+  const std::string id = RenderAutofocusedInputFieldInLacros(browser());
+  ASSERT_TRUE(SetInputFieldText(GetActiveWebContents(browser()), id, "hello",
+                                gfx::Range(3)));
+  InputMethodTestInterfaceAsyncWaiter input_method_async_waiter(
+      input_method.get());
+  input_method_async_waiter.WaitForFocus();
+
+  SendKeyEventSync(input_method_async_waiter,
+                   CreateKeyPressEvent('\b', ui::DomCode::BACKSPACE));
+  SendKeyEventSync(input_method_async_waiter,
+                   CreateKeyReleaseEvent('\b', ui::DomCode::BACKSPACE));
+  EXPECT_TRUE(WaitUntilInputFieldHasText(GetActiveWebContents(browser()), id,
+                                         "helo", gfx::Range(2)));
+
+  SendKeyEventSync(input_method_async_waiter,
+                   CreateKeyPressEvent('\b', ui::DomCode::BACKSPACE));
+  SendKeyEventSync(input_method_async_waiter,
+                   CreateKeyReleaseEvent('\b', ui::DomCode::BACKSPACE));
+  EXPECT_TRUE(WaitUntilInputFieldHasText(GetActiveWebContents(browser()), id,
+                                         "hlo", gfx::Range(1)));
+
+  SendKeyEventSync(input_method_async_waiter,
+                   CreateKeyPressEvent('\b', ui::DomCode::BACKSPACE));
+  SendKeyEventSync(input_method_async_waiter,
+                   CreateKeyReleaseEvent('\b', ui::DomCode::BACKSPACE));
+  EXPECT_TRUE(WaitUntilInputFieldHasText(GetActiveWebContents(browser()), id,
+                                         "lo", gfx::Range(0)));
+}
+
+IN_PROC_BROWSER_TEST_F(InputMethodLacrosBrowserTest,
                        SetCompositionWhileHandlingKeyEvent) {
   mojo::Remote<InputMethodTestInterface> input_method =
       BindInputMethodTestInterface(
diff --git a/chrome/browser/resources/chromeos/drive_internals.html b/chrome/browser/resources/chromeos/drive_internals.html
index 0d7d086ce..a5a981c 100644
--- a/chrome/browser/resources/chromeos/drive_internals.html
+++ b/chrome/browser/resources/chromeos/drive_internals.html
@@ -145,6 +145,10 @@
           <th>Failed Files</th>
           <td id="bulk-pinning-failed-files">?</td>
         </tr>
+        <tr>
+          <th>Pinning Files</th>
+          <td id="bulk-pinning-syncing-files">?</td>
+        </tr>
       </table>
     </section>
 
diff --git a/chrome/browser/resources/chromeos/drive_internals.js b/chrome/browser/resources/chromeos/drive_internals.js
index f4284d5..870e420 100644
--- a/chrome/browser/resources/chromeos/drive_internals.js
+++ b/chrome/browser/resources/chromeos/drive_internals.js
@@ -112,6 +112,7 @@
   $('bulk-pinning-files-to-pin').innerText = progress.files_to_pin;
   $('bulk-pinning-pinned-files').innerText = progress.pinned_files;
   $('bulk-pinning-failed-files').innerText = progress.failed_files;
+  $('bulk-pinning-syncing-files').innerText = progress.syncing_files;
 }
 
 function updateStartupArguments(args) {
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_permissions_browser_proxy.ts b/chrome/browser/resources/settings/site_settings/site_settings_permissions_browser_proxy.ts
index 207702c..84258b34 100644
--- a/chrome/browser/resources/settings/site_settings/site_settings_permissions_browser_proxy.ts
+++ b/chrome/browser/resources/settings/site_settings/site_settings_permissions_browser_proxy.ts
@@ -16,6 +16,7 @@
 export interface UnusedSitePermissions {
   origin: string;
   permissions: ContentSettingsTypes[];
+  expiration: string;
 }
 
 /**
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_cy.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_cy.xtb
index 411e32aa..4291770 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_cy.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_cy.xtb
@@ -182,6 +182,7 @@
 <translation id="1995884366040846621">I barhau, bydd <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> yn rhannu eich enw, eich e-bost, eich cyfeiriad, a'ch llun proffil gyda'r wefan. Gweld <ph name="BEGIN_LINK1" />polisi preifatrwydd<ph name="END_LINK1" /> y wefan hon.</translation>
 <translation id="2000419248597011803">Yn anfon rhai cwcis a chwiliadau o'r bar cyfeiriadau a'r blwch chwilio i'ch peiriant chwilio diofyn</translation>
 <translation id="200114059308480249">Cynnwys testun o'i amgylch mewn chwiliadau Google?</translation>
+<translation id="2009341475524975924">I fesur perfformiad hysbyseb, gellir rhannu mathau cyfyngedig o ddata rhwng gwefannau, megis yr amser o'r dydd y dangoswyd hysbyseb i chi.</translation>
 <translation id="2013642289801508067">{FILE_COUNT,plural, =1{# Ffeil}zero{# Ffeil}two{# Ffeil}few{# Ffeil}many{# Ffeil}other{# Ffeil}}</translation>
 <translation id="2021896219286479412">Rheolyddion gwefan sgrîn lawn</translation>
 <translation id="2038563949887743358">Troi Gofyn am wefan bwrdd gwaith ymlaen</translation>
@@ -652,6 +653,7 @@
 <translation id="4616150815774728855">Agor <ph name="WEBAPK_NAME" /></translation>
 <translation id="4619564267100705184">Cadarnhewch mai chi sydd yno</translation>
 <translation id="4634124774493850572">Defnyddio cyfrinair</translation>
+<translation id="4637420359569396807">Gyda mesur hysbysebion, gellir rhannu mathau cyfyngedig o ddata rhwng gwefannau ac apiau i fesur perfformiad eu hysbysebion, megis yr amser o'r dydd y dangoswyd hysbyseb i chi.</translation>
 <translation id="4640331037679501949">{NUM_PASSWORDS,plural, =1{1 cyfrinair sydd wedi'i ddarganfod}zero{# cyfrinair sydd wedi'u darganfod}two{# gyfrinair sydd wedi'u darganfod}few{# chyfrinair sydd wedi'u darganfod}many{# chyfrinair mewn perygl}other{# cyfrinair sydd wedi'u darganfod}}</translation>
 <translation id="4650364565596261010">System ddiofyn</translation>
 <translation id="465657074423018424">Mae Pori'n Ddiogel yn eich amddiffyn rhag gwefannau twyllodrus. Os byddwch yn ei ddiffodd, byddwch yn ofalus wrth bori, yn enwedig cyn rhoi unrhyw gyfrineiriau.</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb
index 95fabc5c..d9ae94e 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb
@@ -182,6 +182,7 @@
 <translation id="1995884366040846621">برای ادامه دادن، <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> نام، نشانی ایمیل، و عکس نمایه‌تان را با این سایت هم‌رسانی خواهد کرد. <ph name="BEGIN_LINK1" />خط‌مشی رازداری<ph name="END_LINK1" /> این سایت را مطالعه کنید.</translation>
 <translation id="2000419248597011803">برخی کوکی‌ها و جستجوها را از نوار نشانی و جعبه جستجو به موتور جستجوی پیش‌فرض ارسال می‌کند</translation>
 <translation id="200114059308480249">‏نوشتار اطراف در جستجوهای Google لحاظ شوند؟</translation>
+<translation id="2009341475524975924">برای سنجش عملکرد آگهی، انواع محدودی از داده‌ها را می‌توان بین سایت‌ها هم‌رسانی کرد؛ داده‌هایی مثل زمانی از روز که آگهی به شما نشان داده شده است.</translation>
 <translation id="2013642289801508067">{FILE_COUNT,plural, =1{# فایل}one{# فایل}other{# فایل}}</translation>
 <translation id="2021896219286479412">کنترل‌های سایت تمام‌صفحه</translation>
 <translation id="2038563949887743358">روشن کردن درخواست سایت رایانه‌ای</translation>
@@ -236,6 +237,7 @@
 <translation id="2321086116217818302">درحال آماده‌سازی گذرواژه‌ها…</translation>
 <translation id="2323763861024343754">فضای ذخیره‌سازی سایت</translation>
 <translation id="2328985652426384049">ورود به سیستم امکان‌پذیر نیست</translation>
+<translation id="2341410551640223969"><ph name="WEBAPK_NAME" /> نصب نشد.</translation>
 <translation id="234265804618409743">نمی‌توان دوربین را باز کرد. مشکلی پیش آمد.</translation>
 <translation id="2349710944427398404">‏کل داده‌های استفاده‌شده توسط Chrome، شامل حساب‌ها، نشانک‌ها و تنظیمات ذخیره‌شده</translation>
 <translation id="235789365079050412">‏خط‌مشی رازداری Google</translation>
@@ -344,6 +346,7 @@
 <translation id="2909615210195135082">‏پلتفورم اعلان‌های Google</translation>
 <translation id="2912296070571964914">مدیریت موضوع‌هایی که به آن‌ها علاقه دارید</translation>
 <translation id="2912345083818861431">استفاده از قفل صفحه برای دیدن برگه‌های ناشناس باز</translation>
+<translation id="2922568440285376746">‏جستجو در تصویر با Google <ph name="BEGIN_NEW" />جدید<ph name="END_NEW" /></translation>
 <translation id="2923908459366352541">نام نامعتبر است</translation>
 <translation id="2932150158123903946">‏فضای ذخیره‌سازی Google <ph name="APP_NAME" /></translation>
 <translation id="2932222164150889403">صفحه‌کلیدتان تغییر نخواهد کرد</translation>
@@ -652,6 +655,7 @@
 <translation id="4616150815774728855">باز کردن <ph name="WEBAPK_NAME" /></translation>
 <translation id="4619564267100705184">تأیید کنید این شمایید</translation>
 <translation id="4634124774493850572">استفاده از گذرواژه</translation>
+<translation id="4637420359569396807">با سنجش آگهی، انواع محدودی از داده‌ها را می‌توان بین سایت‌ها و برنامه‌ها هم‌رسانی کرد تا عملکرد آگهی‌ها سنجیده شود؛ داده‌هایی مثل زمانی از روز که آگهی به شما نشان داده شده است.</translation>
 <translation id="4640331037679501949">{NUM_PASSWORDS,plural, =1{۱ گذرواژه لورفته}one{# گذرواژه لورفته}other{# گذرواژه لورفته}}</translation>
 <translation id="4650364565596261010">پیش‌فرض سیستم</translation>
 <translation id="465657074423018424">«مرور ایمن» از شما دربرابر وب‌سایت‌های فریب‌کار محافظت می‌کند. اگر آن را خاموش کنید، هنگام مرور کردن بیشتر مراقب باشید؛ مخصوصاً قبل از وارد کردن گذرواژه‌ها.</translation>
@@ -664,6 +668,7 @@
 <translation id="4684427112815847243">همگام‌سازی همه</translation>
 <translation id="4685741273709472646">انتخاب از فهرست کرکره‌ای</translation>
 <translation id="4687718960473379118">آگهی‌های پیشنهادی سایت</translation>
+<translation id="4689792375321623175">‏جستجوی تصویر با Google <ph name="BEGIN_NEW" />جدید<ph name="END_NEW" /></translation>
 <translation id="4695891336199304370">{SHIPPING_OPTIONS,plural, =1{‏<ph name="SHIPPING_OPTION_PREVIEW" />\u2026 و <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> گزینه دیگر}one{‏<ph name="SHIPPING_OPTION_PREVIEW" />\u2026 و <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> گزینه دیگر}other{‏<ph name="SHIPPING_OPTION_PREVIEW" />\u2026 و <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> گزینه دیگر}}</translation>
 <translation id="4699172675775169585">تصاویر و فایل‌های قرار گرفته در حافظه پنهان</translation>
 <translation id="4719927025381752090">پیشنهاد برای ترجمه</translation>
@@ -810,6 +815,7 @@
 <translation id="5438292632479953702">بارگیری مجدد</translation>
 <translation id="5441466871879044658">به این زبان ترجمه شود</translation>
 <translation id="5441522332038954058">رفتن به نوار نشانی</translation>
+<translation id="5444999712122199445">برگشتن به سایت</translation>
 <translation id="544776284582297024">برای باز کردن برگه‌ها و بازدید هم‌زمان از صفحه‌های مختلف، روی دکمه «بازکردن برگه‌ها» ضربه بزنید</translation>
 <translation id="5454166040603940656">با <ph name="PROVIDER" /></translation>
 <translation id="5456381639095306749">بارگیری صفحه</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb
index ef19972..a2c92355 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb
@@ -182,6 +182,7 @@
 <translation id="1995884366040846621">Үргэлжүүлэхийн тулд <ph name="IDENTITY_PROVIDER_ETLD_PLUS_ONE" /> таны нэр, имэйл хаяг болон профайл зургийг энэ сайттай хуваалцана. Энэ сайтын <ph name="BEGIN_LINK1" />нууцлалын бодлогыг<ph name="END_LINK1" /> харна уу.</translation>
 <translation id="2000419248597011803">Таны өгөгдмөл хайлтын системд хаяг оруулах хэсэг, хайх хэсгийн зарим күүки болон хайлтыг илгээдэг</translation>
 <translation id="200114059308480249">Google-н хайлтуудад эргэн тойрны текстийг оруулах уу?</translation>
+<translation id="2009341475524975924">Зарын гүйцэтгэлийг хэмжихийн тулд танд зар харуулсан өдрийн цаг зэрэг хязгаарлагдмал төрлийн өгөгдлийг сайтуудын хооронд хуваалцах боломжтой.</translation>
 <translation id="2013642289801508067">{FILE_COUNT,plural, =1{# Файл}other{# Файл}}</translation>
 <translation id="2021896219286479412">Бүтэн дэлгэцийн сайтын хяналт</translation>
 <translation id="2038563949887743358">Сайтыг компьютерийн горимоор харах хүсэлтийг асаах</translation>
@@ -236,6 +237,7 @@
 <translation id="2321086116217818302">Нууц үгийг бэлтгэж байна…</translation>
 <translation id="2323763861024343754">Сайтын сан</translation>
 <translation id="2328985652426384049">Нэвтрэх боломжгүй</translation>
+<translation id="2341410551640223969"><ph name="WEBAPK_NAME" />-г суулгаж чадсангүй.</translation>
 <translation id="234265804618409743">Таны камерыг нээх боломжгүй байна. Алдаа гарлаа.</translation>
 <translation id="2349710944427398404">Бүртгэл, хавчуурга, хадгалсан тохиргоо зэрэг Chrome-н ашигласан нийт өгөгдөл</translation>
 <translation id="235789365079050412">Google-н нууцлалын бодлого</translation>
@@ -344,6 +346,7 @@
 <translation id="2909615210195135082">Google мэдэгдлийн платформ</translation>
 <translation id="2912296070571964914">Сонирхдог сэдвүүдээ удирдана уу</translation>
 <translation id="2912345083818861431">Нээлттэй нууцлалтай табуудыг харахын тулд дэлгэцийн түгжээг ашиглана уу</translation>
+<translation id="2922568440285376746">Google-р зургаас хайх <ph name="BEGIN_NEW" />Шинэ<ph name="END_NEW" /></translation>
 <translation id="2923908459366352541">Нэр буруу байна</translation>
 <translation id="2932150158123903946">Google <ph name="APP_NAME" /> сан</translation>
 <translation id="2932222164150889403">Таны гар өөрчлөгдөхгүй</translation>
@@ -652,6 +655,7 @@
 <translation id="4616150815774728855"><ph name="WEBAPK_NAME" />-г нээх</translation>
 <translation id="4619564267100705184">Өөрийгөө мөн болохыг бататгах</translation>
 <translation id="4634124774493850572">Нууц үг ашиглах</translation>
+<translation id="4637420359569396807">Зарын хэмжилтийн тусламжтай танд зар харуулсан өдрийн цаг зэрэг сайтууд болон аппуудын зарын гүйцэтгэлийг хэмжихийн тулд тэдгээрийн хооронд хязгаарлагдмал төрлийн өгөгдлийг хуваалцах боломжтой.</translation>
 <translation id="4640331037679501949">{NUM_PASSWORDS,plural, =1{Алдагдсан 1 нууц үг}other{Алдагдсан # нууц үг}}</translation>
 <translation id="4650364565596261010">Системийн өгөгдмөл</translation>
 <translation id="465657074423018424">Аюулгүй үзэх үйлчилгээ нь сэжигтэй вебсайтаас таныг хамгаалдаг. Хэрэв та энэ үйлчилгээг идэвхгүй болгох бол вебсайт үзэхдээ, ялангуяа нууц үг оруулахаасаа өмнө маш болгоомжтой байгаарай.</translation>
@@ -664,6 +668,7 @@
 <translation id="4684427112815847243">Бүгдийг sync хийх</translation>
 <translation id="4685741273709472646">Унадаг цэсийн жагсаалтаас сонгох</translation>
 <translation id="4687718960473379118">Сайтын санал болгосон зар</translation>
+<translation id="4689792375321623175">Google-р зургаас хайх <ph name="BEGIN_NEW" />Шинэ<ph name="END_NEW" /></translation>
 <translation id="4695891336199304370">{SHIPPING_OPTIONS,plural, =1{<ph name="SHIPPING_OPTION_PREVIEW" />\u2026 болон бусад <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" />\u2026 болон бусад <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
 <translation id="4699172675775169585">Кэшлсэн дүрс ба файл</translation>
 <translation id="4719927025381752090">Орчуулахыг санал болгох</translation>
@@ -809,6 +814,7 @@
 <translation id="5438292632479953702">Дахин татах</translation>
 <translation id="5441466871879044658">Энэ хэл рүү орчуулах</translation>
 <translation id="5441522332038954058">Хаяг оруулах хэсэгт очих</translation>
+<translation id="5444999712122199445">Сайт руу буцах</translation>
 <translation id="544776284582297024">Табуудыг нээн, өөр хуудаснуудад нэгэн зэрэг зочлохын тулд табуудыг нээх товчлуурыг товшино уу</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" />-тэй</translation>
 <translation id="5456381639095306749">Хуудсыг татах</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb
index 662abe3..f975a08 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb
@@ -237,6 +237,7 @@
 <translation id="2321086116217818302">Pripravujú sa heslá…</translation>
 <translation id="2323763861024343754">Úložisko webu</translation>
 <translation id="2328985652426384049">Nedá sa prihlásiť</translation>
+<translation id="2341410551640223969"><ph name="WEBAPK_NAME" /> sa nepodarilo nainštalovať.</translation>
 <translation id="234265804618409743">Vaša kamera sa nedá otvoriť. Vyskytol sa problém.</translation>
 <translation id="2349710944427398404">Celkové dáta využívané Chromom vrátane účtov, záložiek a uložených nastavení</translation>
 <translation id="235789365079050412">Pravidlá ochrany súkromia spoločnosti Google</translation>
@@ -345,6 +346,7 @@
 <translation id="2909615210195135082">Google Notifications Platform</translation>
 <translation id="2912296070571964914">Spravujte témy, ktoré vás zaujímajú</translation>
 <translation id="2912345083818861431">Zobrazte si otvorené karty inkognito pomocou zámky obrazovky</translation>
+<translation id="2922568440285376746">Hľadať na obrázku Googlom <ph name="BEGIN_NEW" />Novinka<ph name="END_NEW" /></translation>
 <translation id="2923908459366352541">Názov je neplatný</translation>
 <translation id="2932150158123903946">Úložisko Google <ph name="APP_NAME" /></translation>
 <translation id="2932222164150889403">Klávesnica sa nezmení</translation>
@@ -666,6 +668,7 @@
 <translation id="4684427112815847243">Synchronizovať všetko</translation>
 <translation id="4685741273709472646">Vybrať z rozbaľovacieho zoznamu</translation>
 <translation id="4687718960473379118">Reklamy navrhované webmi</translation>
+<translation id="4689792375321623175">Hľadať na obrázku Googlom <ph name="BEGIN_NEW" />Novinka<ph name="END_NEW" /></translation>
 <translation id="4695891336199304370">{SHIPPING_OPTIONS,plural, =1{<ph name="SHIPPING_OPTION_PREVIEW" />\u2026 a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ďalšia}few{<ph name="SHIPPING_OPTION_PREVIEW" />\u2026 a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ďalšie}many{<ph name="SHIPPING_OPTION_PREVIEW" />\u2026 a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ďalšej}other{<ph name="SHIPPING_OPTION_PREVIEW" />\u2026 a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ďalších}}</translation>
 <translation id="4699172675775169585">Obrázky a súbory vo vyrovnávacej pamäti</translation>
 <translation id="4719927025381752090">Ponúkať preklad</translation>
@@ -812,6 +815,7 @@
 <translation id="5438292632479953702">Stiahnuť znova</translation>
 <translation id="5441466871879044658">Preložiť do tohto jazyka</translation>
 <translation id="5441522332038954058">Prechod na panel s adresou</translation>
+<translation id="5444999712122199445">Prejdite späť na web</translation>
 <translation id="544776284582297024">Ak chcete otvoriť karty a navštíviť naraz rôzne stránky, klepnite na tlačidlo Otvoriť karty</translation>
 <translation id="5454166040603940656">s poskytovateľom <ph name="PROVIDER" /></translation>
 <translation id="5456381639095306749">Stránka sťahovania</translation>
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index 48eaa0dd..b07d1bc 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -16,6 +16,7 @@
 #include "base/files/file_util.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
+#include "base/location.h"
 #include "base/memory/raw_ptr.h"
 #include "base/notreached.h"
 #include "base/path_service.h"
@@ -421,7 +422,9 @@
   BrowserAddedWaiter() { BrowserList::AddObserver(this); }
   ~BrowserAddedWaiter() override { BrowserList::RemoveObserver(this); }
 
-  void Wait() { run_loop_.Run(); }
+  void Wait(const base::Location& location = base::Location::Current()) {
+    run_loop_.Run(location);
+  }
 
   // BrowserListObserver
   void OnBrowserAdded(Browser* browser) override {
diff --git a/chrome/browser/ui/webui/ash/drive_internals_ui.cc b/chrome/browser/ui/webui/ash/drive_internals_ui.cc
index ef62815..9b0604c 100644
--- a/chrome/browser/ui/webui/ash/drive_internals_ui.cc
+++ b/chrome/browser/ui/webui/ash/drive_internals_ui.cc
@@ -644,6 +644,7 @@
     d.Set("files_to_pin", ToString(progress.files_to_pin));
     d.Set("pinned_files", ToString(progress.pinned_files));
     d.Set("failed_files", ToString(progress.failed_files));
+    d.Set("syncing_files", ToString(progress.syncing_files));
     MaybeCallJavascript("onBulkPinningProgress", base::Value(std::move(d)));
   }
 
diff --git a/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher.cc b/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher.cc
index 22ded80..bdac7cc 100644
--- a/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher.cc
+++ b/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/functional/bind.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "chrome/browser/ui/webui/ash/emoji/emoji_picker.mojom.h"
@@ -22,6 +23,9 @@
 #include "url/gurl.h"
 
 namespace ash {
+
+namespace {
+
 using emoji_picker::mojom::PageHandler;
 
 constexpr char kTenorBaseUrl[] = "https://tenor.googleapis.com";
@@ -40,23 +44,24 @@
 constexpr char kPosName[] = "pos";
 const int64_t kTimeoutMs = 10000;
 
-GifTenorApiFetcher::GifTenorApiFetcher() = default;
-
-GifTenorApiFetcher::~GifTenorApiFetcher() = default;
-
-GURL GifTenorApiFetcher::GetURL(const char* endpoint,
-                                const absl::optional<std::string>& pos) {
-  GURL url = net::AppendQueryParameter(GURL(kTenorBaseUrl).Resolve(endpoint),
-                                       kContentFilterName, kContentFilterValue);
-  url = net::AppendQueryParameter(url, kArRangeName, kArRangeValue);
-  url = net::AppendQueryParameter(url, kMediaFilterName, kMediaFilterValue);
-  if (pos) {
-    url = net::AppendQueryParameter(url, kPosName, pos.value());
-  }
-  return url;
+std::unique_ptr<EndpointFetcher> CreateEndpointFetcher(
+    const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+    const GURL& url,
+    const net::NetworkTrafficAnnotationTag& annotation_tag) {
+  return std::make_unique<EndpointFetcher>(
+      /*url_loader_factory=*/url_loader_factory,
+      /*url=*/url,
+      /*http_method=*/kHttpMethod,
+      /*content_type=*/kHttpContentType,
+      /*timeout_ms=*/kTimeoutMs,
+      /*post_data=*/"",
+      /*headers=*/std::vector<std::string>(),
+      /*annotation_tag=*/annotation_tag,
+      /*is_stable_channel=*/chrome::GetChannel() ==
+          version_info::Channel::STABLE);
 }
 
-const base::Value::List* GifTenorApiFetcher::FindList(
+const base::Value::List* FindList(
     data_decoder::DataDecoder::ValueOrError& result,
     const std::string& key) {
   if (!result.has_value()) {
@@ -72,16 +77,7 @@
   return list ? list : nullptr;
 }
 
-void GifTenorApiFetcher::TenorGifsApiResponseHandler(
-    TenorGifsApiCallback callback,
-    std::unique_ptr<EndpointResponse> response) {
-  data_decoder::DataDecoder::ParseJsonIsolated(
-      response->response,
-      base::BindOnce(&GifTenorApiFetcher::OnGifsJsonParsed,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-}
-
-std::vector<emoji_picker::mojom::GifResponsePtr> GifTenorApiFetcher::ParseGifs(
+std::vector<emoji_picker::mojom::GifResponsePtr> ParseGifs(
     const base::Value::List* results) {
   std::vector<emoji_picker::mojom::GifResponsePtr> gifs;
   for (const auto& result : *results) {
@@ -163,6 +159,37 @@
   return gifs;
 }
 
+GURL GetUrl(const char* endpoint, const absl::optional<std::string>& pos) {
+  GURL url = net::AppendQueryParameter(GURL(kTenorBaseUrl).Resolve(endpoint),
+                                       kContentFilterName, kContentFilterValue);
+  url = net::AppendQueryParameter(url, kArRangeName, kArRangeValue);
+  url = net::AppendQueryParameter(url, kMediaFilterName, kMediaFilterValue);
+  if (pos) {
+    url = net::AppendQueryParameter(url, kPosName, pos.value());
+  }
+  return url;
+}
+
+}  // namespace
+
+GifTenorApiFetcher::GifTenorApiFetcher()
+    : endpoint_fetcher_creator_{base::BindRepeating(&CreateEndpointFetcher)} {}
+
+GifTenorApiFetcher::GifTenorApiFetcher(
+    EndpointFetcherCreator endpoint_fetcher_creator)
+    : endpoint_fetcher_creator_{endpoint_fetcher_creator} {}
+
+GifTenorApiFetcher::~GifTenorApiFetcher() = default;
+
+void GifTenorApiFetcher::TenorGifsApiResponseHandler(
+    TenorGifsApiCallback callback,
+    std::unique_ptr<EndpointResponse> response) {
+  data_decoder::DataDecoder::ParseJsonIsolated(
+      response->response,
+      base::BindOnce(&GifTenorApiFetcher::OnGifsJsonParsed,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
 void GifTenorApiFetcher::OnGifsJsonParsed(
     TenorGifsApiCallback callback,
     data_decoder::DataDecoder::ValueOrError result) {
@@ -172,34 +199,6 @@
       next ? *next : "", ParseGifs(gifs)));
 }
 
-void GifTenorApiFetcher::OnGifsByIdsJsonParsed(
-    emoji_picker::mojom::PageHandler::GetGifsByIdsCallback callback,
-    data_decoder::DataDecoder::ValueOrError result) {
-  const auto* gifs = FindList(result, "results");
-  if (!gifs) {
-    return;
-  }
-
-  std::move(callback).Run(ParseGifs(gifs));
-}
-
-std::unique_ptr<EndpointFetcher> GifTenorApiFetcher::CreateEndpointFetcher(
-    const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    const GURL& url,
-    const net::NetworkTrafficAnnotationTag& annotation_tag) {
-  return std::make_unique<EndpointFetcher>(
-      /*url_loader_factory=*/url_loader_factory,
-      /*url=*/url,
-      /*http_method=*/kHttpMethod,
-      /*content_type=*/kHttpContentType,
-      /*timeout_ms=*/kTimeoutMs,
-      /*post_data=*/"",
-      /*headers=*/std::vector<std::string>(),
-      /*annotation_tag=*/annotation_tag,
-      /*is_stable_channel=*/chrome::GetChannel() ==
-          version_info::Channel::STABLE);
-}
-
 void GifTenorApiFetcher::FetchCategories(
     PageHandler::GetCategoriesCallback callback,
     const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
@@ -230,7 +229,7 @@
       }
   )");
 
-  endpoint_fetcher_ = CreateEndpointFetcher(
+  endpoint_fetcher_ = endpoint_fetcher_creator_.Run(
       url_loader_factory, GURL(kTenorBaseUrl).Resolve(kCategoriesApi),
       kTrafficAnnotation);
   endpoint_fetcher_->PerformRequest(
@@ -307,8 +306,8 @@
       }
   )");
 
-  endpoint_fetcher_ = CreateEndpointFetcher(
-      url_loader_factory, GetURL(kFeaturedApi, pos), kTrafficAnnotation);
+  endpoint_fetcher_ = endpoint_fetcher_creator_.Run(
+      url_loader_factory, GetUrl(kFeaturedApi, pos), kTrafficAnnotation);
   endpoint_fetcher_->PerformRequest(
       base::BindOnce(&GifTenorApiFetcher::TenorGifsApiResponseHandler,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
@@ -350,11 +349,11 @@
       }
   )");
 
-  GURL url = GetURL(kSearchApi, pos);
+  GURL url = GetUrl(kSearchApi, pos);
   url = net::AppendQueryParameter(url, "q", query);
 
-  endpoint_fetcher_ =
-      CreateEndpointFetcher(url_loader_factory, url, kTrafficAnnotation);
+  endpoint_fetcher_ = endpoint_fetcher_creator_.Run(url_loader_factory, url,
+                                                    kTrafficAnnotation);
   endpoint_fetcher_->PerformRequest(
       base::BindOnce(&GifTenorApiFetcher::TenorGifsApiResponseHandler,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
@@ -393,7 +392,7 @@
       }
   )");
 
-  endpoint_fetcher_ = CreateEndpointFetcher(
+  endpoint_fetcher_ = endpoint_fetcher_creator_.Run(
       url_loader_factory,
       net::AppendQueryParameter(GURL(kTenorBaseUrl).Resolve(kPostsApi), "ids",
                                 base::JoinString(ids, ",")),
@@ -412,4 +411,15 @@
       base::BindOnce(&GifTenorApiFetcher::OnGifsByIdsJsonParsed,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
+
+void GifTenorApiFetcher::OnGifsByIdsJsonParsed(
+    emoji_picker::mojom::PageHandler::GetGifsByIdsCallback callback,
+    data_decoder::DataDecoder::ValueOrError result) {
+  const auto* gifs = FindList(result, "results");
+  if (!gifs) {
+    return;
+  }
+
+  std::move(callback).Run(ParseGifs(gifs));
+}
 }  // namespace ash
diff --git a/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher.h b/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher.h
index 36ec6dc..49e64c9 100644
--- a/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher.h
+++ b/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher.h
@@ -16,8 +16,18 @@
 
 class GifTenorApiFetcher {
  public:
+  // Used in tests to mock a creation of the endpoint_fetcher
+  using EndpointFetcherCreator =
+      base::RepeatingCallback<std::unique_ptr<EndpointFetcher>(
+          const scoped_refptr<network::SharedURLLoaderFactory>
+              url_loader_factory,
+          const GURL& url,
+          const net::NetworkTrafficAnnotationTag& annotation_tag)>;
+
   GifTenorApiFetcher();
 
+  explicit GifTenorApiFetcher(EndpointFetcherCreator endpoint_fetcher_creator);
+
   ~GifTenorApiFetcher();
 
   using TenorGifsApiCallback =
@@ -49,8 +59,8 @@
 
  private:
   std::unique_ptr<EndpointFetcher> endpoint_fetcher_;
+  const EndpointFetcherCreator endpoint_fetcher_creator_;
   base::WeakPtrFactory<GifTenorApiFetcher> weak_ptr_factory_{this};
-  GURL GetURL(const char* endpoint, const absl::optional<std::string>& pos);
 
   void FetchCategoriesResponseHandler(
       emoji_picker::mojom::PageHandler::GetCategoriesCallback callback,
@@ -73,18 +83,6 @@
   void OnGifsByIdsJsonParsed(
       emoji_picker::mojom::PageHandler::GetGifsByIdsCallback callback,
       data_decoder::DataDecoder::ValueOrError result);
-
-  std::vector<emoji_picker::mojom::GifResponsePtr> ParseGifs(
-      const base::Value::List* results);
-
-  const base::Value::List* FindList(
-      data_decoder::DataDecoder::ValueOrError& result,
-      const std::string& key);
-
-  std::unique_ptr<EndpointFetcher> CreateEndpointFetcher(
-      const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      const GURL& url,
-      const net::NetworkTrafficAnnotationTag& annotation_tag);
 };
 }  // namespace ash
 
diff --git a/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher_unittest.cc b/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher_unittest.cc
new file mode 100644
index 0000000..7994ef6
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/emoji/gif_tenor_api_fetcher_unittest.cc
@@ -0,0 +1,148 @@
+// 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 "gif_tenor_api_fetcher.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
+#include "chrome/browser/ui/webui/ash/emoji/emoji_picker.mojom-forward.h"
+#include "components/endpoint_fetcher/endpoint_fetcher.h"
+#include "content/public/test/browser_task_environment.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace ash {
+
+namespace {
+
+constexpr char kFakeCategoriesResponse[] =
+    "{\"tags\":[{\"image\":\"url1\",\"name\":\"#awesome\",\"path\":\"/v2/"
+    "path1\","
+    "\"searchterm\":\"awesome\"}, "
+    "{\"image\":\"url2\",\"name\":\"#jk\",\"path\":\"/v2/"
+    "path2\","
+    "\"searchterm\":\"jk\"}]}";
+
+constexpr char kFakeGifsResponse[] =
+    "{\"next\":\"1\",\"results\":[{\"id\":\"0\","
+    "\"content_description\":\"GIF0\",\"media_formats\":{\"gif\":{\"dims\":"
+    "["
+    "498,339],\"url\":\"https://tenor.com/view/media.tenor.com/"
+    "full_url0\"},\"tinygif\":{\"dims\":[220,150]"
+    ",\"url\":\"https://tenor.com/view/media.tenor.com/"
+    "preview_url0\"}}},{\"id\":\"1\",\"content_description\":\"GIF1\","
+    "\"media_formats\":{\"gif\":{\"dims\":[498,498],\"url\":\"https://"
+    "tenor.com/view/media.tenor.com/"
+    "full_url1\"},\"tinygif\":{\"dims\":[220,220],\"url\":\"https://"
+    "tenor.com/view/media.tenor.com/preview_url1\"}}}]}";
+
+std::vector<emoji_picker::mojom::GifResponsePtr> GetFakeGifs() {
+  std::vector<emoji_picker::mojom::GifResponsePtr> gifs;
+  gifs.push_back(emoji_picker::mojom::GifResponse::New(
+      "0", "GIF0",
+      emoji_picker::mojom::GifUrls::New(
+          GURL("https://tenor.com/view/media.tenor.com/full_url0"),
+          GURL("https://tenor.com/view/media.tenor.com/preview_url0")),
+      gfx::Size(220, 150)));
+  gifs.push_back(emoji_picker::mojom::GifResponse::New(
+      "1", "GIF1",
+      emoji_picker::mojom::GifUrls::New(
+          GURL("https://tenor.com/view/media.tenor.com/full_url1"),
+          GURL("https://tenor.com/view/media.tenor.com/preview_url1")),
+      gfx::Size(220, 220)));
+  return gifs;
+}
+}  // namespace
+
+class FakeEndpointFetcher : public EndpointFetcher {
+ public:
+  explicit FakeEndpointFetcher(EndpointResponse response)
+      : EndpointFetcher(net::DefineNetworkTrafficAnnotation(
+            "chromeos_emoji_picker_mock_fetcher",
+            R"()")),
+        response_(response) {}
+
+  void PerformRequest(EndpointFetcherCallback endpoint_fetcher_callback,
+                      const char* key) override {
+    std::move(endpoint_fetcher_callback)
+        .Run(std::make_unique<EndpointResponse>(response_));
+  }
+
+ private:
+  EndpointResponse response_;
+};
+
+class GifTenorApiFetcherTest : public testing::Test {
+ public:
+  GifTenorApiFetcherTest()
+      : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP,
+                          base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+
+  std::unique_ptr<EndpointFetcher> CreateEndpointFetcher(
+      const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const GURL& url,
+      const net::NetworkTrafficAnnotationTag& annotation_tag) {
+    return std::make_unique<FakeEndpointFetcher>(response_);
+  }
+
+ protected:
+  content::BrowserTaskEnvironment task_environment_;
+  EndpointResponse response_;
+  data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+  GifTenorApiFetcher gif_tenor_api_fetcher_ = GifTenorApiFetcher(
+      base::BindRepeating(&GifTenorApiFetcherTest::CreateEndpointFetcher,
+                          base::Unretained(this)));
+};
+
+TEST_F(GifTenorApiFetcherTest, FetchCategories) {
+  task_environment_.RunUntilIdle();
+  response_.response = kFakeCategoriesResponse;
+  base::test::TestFuture<const std::vector<std::string>&> create_future;
+  gif_tenor_api_fetcher_.FetchCategories(create_future.GetCallback(),
+                                         url_loader_factory_);
+  std::vector<std::string> expected{"#awesome", "#jk"};
+  ASSERT_EQ(create_future.Get<0>(), expected);
+}
+
+TEST_F(GifTenorApiFetcherTest, FetchFeaturedGifs) {
+  task_environment_.RunUntilIdle();
+  response_.response = kFakeGifsResponse;
+  base::test::TestFuture<emoji_picker::mojom::TenorGifResponsePtr>
+      create_future;
+  gif_tenor_api_fetcher_.FetchFeaturedGifs(create_future.GetCallback(),
+                                           url_loader_factory_, "");
+  ASSERT_EQ(create_future.Get<0>(),
+            emoji_picker::mojom::TenorGifResponse::New("1", GetFakeGifs()));
+}
+
+TEST_F(GifTenorApiFetcherTest, FetchGifSearch) {
+  task_environment_.RunUntilIdle();
+  response_.response = kFakeGifsResponse;
+  base::test::TestFuture<emoji_picker::mojom::TenorGifResponsePtr>
+      create_future;
+  gif_tenor_api_fetcher_.FetchGifSearch(create_future.GetCallback(),
+                                        url_loader_factory_, "", "");
+  ASSERT_EQ(create_future.Get<0>(),
+            emoji_picker::mojom::TenorGifResponse::New("1", GetFakeGifs()));
+}
+
+TEST_F(GifTenorApiFetcherTest, FetchGifsByIds) {
+  task_environment_.RunUntilIdle();
+  response_.response = kFakeGifsResponse;
+  base::test::TestFuture<std::vector<emoji_picker::mojom::GifResponsePtr>>
+      create_future;
+  gif_tenor_api_fetcher_.FetchGifsByIds(create_future.GetCallback(),
+                                        url_loader_factory_,
+                                        std::vector<std::string>());
+  ASSERT_EQ(create_future.Get<0>(), GetFakeGifs());
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ui/webui/settings/site_settings_permissions_handler.cc b/chrome/browser/ui/webui/settings/site_settings_permissions_handler.cc
index f9ea66c..97d7640 100644
--- a/chrome/browser/ui/webui/settings/site_settings_permissions_handler.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_permissions_handler.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/webui/settings/site_settings_permissions_handler.h"
 
 #include "base/check.h"
+#include "base/json/values_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/clock.h"
@@ -33,6 +34,10 @@
 // Using a single bucket per day, following the value of
 // |kAllowAgainMetricsExclusiveMaxCount|.
 size_t kAllowAgainMetricsBuckets = 31;
+// Key of the expiration time in the |UnusedSitePermissions| object. Indicates
+// the time after which the associated origin and permissions are no longer
+// shown in the UI.
+constexpr char kExpirationKey[] = "expiration";
 }  // namespace
 
 SiteSettingsPermissionsHandler::SiteSettingsPermissionsHandler(Profile* profile)
@@ -88,6 +93,50 @@
   SendUnusedSitePermissionsReviewList();
 }
 
+void SiteSettingsPermissionsHandler::
+    HandleUndoAcknowledgeRevokedUnusedSitePermissionsList(
+        const base::Value::List& args) {
+  CHECK_EQ(1U, args.size());
+  CHECK(args[0].is_list());
+
+  const base::Value::List& unused_site_permissions_list = args[0].GetList();
+  permissions::UnusedSitePermissionsService* service =
+      UnusedSitePermissionsServiceFactory::GetForProfile(profile_);
+
+  for (const auto& unused_site_permissions : unused_site_permissions_list) {
+    CHECK(unused_site_permissions.is_dict());
+    const std::string* origin_str =
+        unused_site_permissions.GetDict().FindString(site_settings::kOrigin);
+    CHECK(origin_str);
+    const auto url = GURL(*origin_str);
+    CHECK(url.is_valid());
+
+    const base::Value::List* permissions =
+        unused_site_permissions.GetDict().FindList(site_settings::kPermissions);
+    CHECK(permissions);
+    std::list<ContentSettingsType> permission_types;
+    for (const auto& permission : *permissions) {
+      CHECK(permission.is_string());
+      const std::string& type = permission.GetString();
+      permission_types.push_back(
+          site_settings::ContentSettingsTypeFromGroupName(type));
+    }
+
+    const base::Value* js_expiration =
+        unused_site_permissions.GetDict().Find(kExpirationKey);
+    CHECK(js_expiration);
+    auto expiration = base::ValueToTime(js_expiration);
+
+    const content_settings::ContentSettingConstraints constraint{
+        .expiration = *expiration};
+
+    service->StorePermissionInRevokedPermissionSetting(
+        permission_types, constraint, url::Origin::Create(url));
+  }
+
+  SendUnusedSitePermissionsReviewList();
+}
+
 base::Value::List
 SiteSettingsPermissionsHandler::PopulateUnusedSitePermissionsData() {
   base::Value::List result;
@@ -126,6 +175,10 @@
         site_settings::kPermissions,
         base::Value(std::move(permissions_value_list)));
 
+    revoked_permission_value.Set(
+        kExpirationKey,
+        base::TimeToValue(revoked_permissions.metadata.expiration));
+
     result.Append(std::move(revoked_permission_value));
   }
   return result;
@@ -149,6 +202,12 @@
       base::BindRepeating(&SiteSettingsPermissionsHandler::
                               HandleAcknowledgeRevokedUnusedSitePermissionsList,
                           base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "undoAcknowledgeRevokedUnusedSitePermissionsList",
+      base::BindRepeating(
+          &SiteSettingsPermissionsHandler::
+              HandleUndoAcknowledgeRevokedUnusedSitePermissionsList,
+          base::Unretained(this)));
 }
 
 void SiteSettingsPermissionsHandler::SendUnusedSitePermissionsReviewList() {
diff --git a/chrome/browser/ui/webui/settings/site_settings_permissions_handler.h b/chrome/browser/ui/webui/settings/site_settings_permissions_handler.h
index 05fa225..6f122dcc 100644
--- a/chrome/browser/ui/webui/settings/site_settings_permissions_handler.h
+++ b/chrome/browser/ui/webui/settings/site_settings_permissions_handler.h
@@ -50,6 +50,12 @@
   void HandleAcknowledgeRevokedUnusedSitePermissionsList(
       const base::Value::List& args);
 
+  // Reverse the changes made by
+  // |HandleAcknowledgeRevokedUnusedSitePermissionsList|. List of revoked
+  // permissions is repopulated. Permission settings are not changed.
+  void HandleUndoAcknowledgeRevokedUnusedSitePermissionsList(
+      const base::Value::List& args);
+
   // Returns the list of revoked permissions that belongs to origins which
   // haven't been visited recently.
   base::Value::List PopulateUnusedSitePermissionsData();
diff --git a/chrome/browser/ui/webui/settings/site_settings_permissions_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_permissions_handler_unittest.cc
index 60942e0..f0a1ebff 100644
--- a/chrome/browser/ui/webui/settings/site_settings_permissions_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_permissions_handler_unittest.cc
@@ -171,4 +171,11 @@
   const auto& revoked_permissions_after =
       handler()->PopulateUnusedSitePermissionsData();
   EXPECT_EQ(revoked_permissions_after.size(), 0U);
+
+  // Undo reverts the list to its initial state.
+  base::Value::List undo_args;
+  undo_args.Append(revoked_permissions_before.Clone());
+  handler()->HandleUndoAcknowledgeRevokedUnusedSitePermissionsList(undo_args);
+  EXPECT_EQ(revoked_permissions_before,
+            handler()->PopulateUnusedSitePermissionsData());
 }
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 01ef07fe..3edbdb22 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1674971873-60a25579703201d86347e4d3d96c23ea58313842.profdata
+chrome-linux-main-1675036157-2a352d548f125d4ddfa254d9ff226e80d9f9799f.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index b7bbb407..af91563 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1674971873-92113744b91d314d2438d6c83c40f6170e5ca098.profdata
+chrome-mac-arm-main-1675036157-de5577c6796a1bae18ce319db757618a629d2e71.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 48e6161..1584026 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1674949590-a3ce8cd404e3b8fa647248be32cf8d477971d230.profdata
+chrome-mac-main-1675036157-e555aeb936bea0d1b9f27d276ecf828dcb9f34b8.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index fd7e046d..2c68003 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1674959591-18f81918e744fba9b298c1605eb565faa5aab1ee.profdata
+chrome-win32-main-1675036157-9739a839008de7437c454eb8e749518c73a3ba0f.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 15469d8f..d52e1a6 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1674959591-7093108f46d7fdd413fa6241fa272e4fe7433e07.profdata
+chrome-win64-main-1675036157-176866fa78a28cac409a46b4c32fbd9099017b45.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 363e2391..22653f14 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -204,15 +204,6 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-// When enabled, newly installed ARC apps will not capture links clicked in the
-// browser by default. Users can still enable link capturing for apps through
-// the intent picker or settings.
-BASE_FEATURE(kDefaultLinkCapturingInBrowser,
-             "DefaultLinkCapturingInBrowser",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-#endif
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
 // Enables passing additional user authentication in requests to DMServer
 // (policy fetch, status report upload).
 BASE_FEATURE(kDMServerOAuthForChildUser,
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index b901a2c..60d2b78 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -121,11 +121,6 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 COMPONENT_EXPORT(CHROME_FEATURES)
-BASE_DECLARE_FEATURE(kDefaultLinkCapturingInBrowser);
-#endif
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-COMPONENT_EXPORT(CHROME_FEATURES)
 BASE_DECLARE_FEATURE(kDMServerOAuthForChildUser);
 #endif
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index defc2df..ada7e67 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -7462,6 +7462,7 @@
       "../browser/ui/webui/ash/add_supervision/add_supervision_handler_utils_unittest.cc",
       "../browser/ui/webui/ash/arc_graphics_tracing/arc_graphics_tracing_handler_unittest.cc",
       "../browser/ui/webui/ash/edu_account_login_handler_unittest.cc",
+      "../browser/ui/webui/ash/emoji/gif_tenor_api_fetcher_unittest.cc",
       "../browser/ui/webui/ash/sync/os_sync_handler_unittest.cc",
       "../browser/ui/webui/help/version_updater_chromeos_unittest.cc",
       "../browser/ui/webui/signin/ash/user_cloud_signin_restriction_policy_fetcher_unittest.cc",
diff --git a/chrome/test/data/webapps_integration/standalone/manifest_tabbed.json b/chrome/test/data/webapps_integration/standalone/manifest_tabbed.json
new file mode 100644
index 0000000..6bcb542
--- /dev/null
+++ b/chrome/test/data/webapps_integration/standalone/manifest_tabbed.json
@@ -0,0 +1,31 @@
+{
+    "name": "Site A",
+    "icons": [
+      {
+        "src": "48x48-green.png",
+        "sizes": "48x48",
+        "type": "image/png"
+      },
+      {
+        "src": "128x128-green.png",
+        "sizes": "128x128",
+        "type": "image/png"
+      },
+      {
+        "src": "192x192-green.png",
+        "sizes": "192x192",
+        "type": "image/png"
+      },
+      {
+        "src": "256x256-green.png",
+        "sizes": "256x256",
+        "type": "image/png"
+      }
+    ],
+    "start_url": "/webapps_integration/standalone/basic.html",
+    "scope": "/webapps_integration/standalone/",
+    "display": "standalone",
+    "display_override": [
+      "tabbed"
+    ]
+  }
\ No newline at end of file
diff --git a/chrome/test/data/webapps_integration/tabbed/192x192-green.png b/chrome/test/data/webapps_integration/tabbed/192x192-green.png
new file mode 100644
index 0000000..60217629
--- /dev/null
+++ b/chrome/test/data/webapps_integration/tabbed/192x192-green.png
Binary files differ
diff --git a/chrome/test/data/webapps_integration/tabbed/192x192-red.webp b/chrome/test/data/webapps_integration/tabbed/192x192-red.webp
new file mode 100644
index 0000000..376d8f12
--- /dev/null
+++ b/chrome/test/data/webapps_integration/tabbed/192x192-red.webp
Binary files differ
diff --git a/chrome/test/data/webapps_integration/tabbed/256x256-green.png b/chrome/test/data/webapps_integration/tabbed/256x256-green.png
new file mode 100644
index 0000000..b644451
--- /dev/null
+++ b/chrome/test/data/webapps_integration/tabbed/256x256-green.png
Binary files differ
diff --git a/chrome/test/data/webapps_integration/tabbed/256x256-red.webp b/chrome/test/data/webapps_integration/tabbed/256x256-red.webp
new file mode 100644
index 0000000..9cf910d1
--- /dev/null
+++ b/chrome/test/data/webapps_integration/tabbed/256x256-red.webp
Binary files differ
diff --git a/chrome/test/data/webapps_integration/tabbed/basic.html b/chrome/test/data/webapps_integration/tabbed/basic.html
new file mode 100644
index 0000000..8cad944
--- /dev/null
+++ b/chrome/test/data/webapps_integration/tabbed/basic.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Tabbed</title>
+    <script src="/webapps_integration/test_utils.js"></script>
+    <script>
+      // If a "manifest=/path/to/manifest.json" query argument is provided to
+      // the URL accessing this page, that path is injected as the manifest tag.
+      // Otherwise, "basic.json" is used as the manifest tag.
+      addManifestLinkTag();
+    </script>
+</head>
+<body onload="startWorker('/webapps_integration/tabbed/service_worker.js', { scope: '/webapps_integration/tabbed/' })">
+  <h1>Tabbed Home Page</h1>
+  <div>
+    <p>
+      This site is used for dPWA integration tests, and is subject to modification to support that framework. See
+      <a
+        href="https://chromium.googlesource.com/chromium/src/+/main/docs/webapps/integration-testing-framework.md">https://chromium.googlesource.com/chromium/src/+/main/docs/webapps/integration-testing-framework.md</a>
+    </p>
+  </div>
+</body>
+</html>
diff --git a/chrome/test/data/webapps_integration/tabbed/basic.json b/chrome/test/data/webapps_integration/tabbed/basic.json
new file mode 100644
index 0000000..84e8e35
--- /dev/null
+++ b/chrome/test/data/webapps_integration/tabbed/basic.json
@@ -0,0 +1,39 @@
+{
+    "name": "Tabbed",
+    "icons": [
+      {
+        "src": "192x192-red.webp",
+        "sizes": "192x192",
+        "type": "image/webp"
+      },
+      {
+        "src": "256x256-red.webp",
+        "sizes": "256x256",
+        "type": "image/webp"
+      }
+    ],
+    "start_url": "/webapps_integration/tabbed/basic.html",
+    "scope": "/webapps_integration/tabbed/",
+    "display": "standalone",
+    "display_override": ["tabbed"],
+    "tab_strip": {
+        "home_tab": {
+            "url": "/webapps_integration/tabbed/basic.html",
+            "icons": [
+              {
+                "src": "192x192-green.png",
+                "sizes": "192x192",
+                "type": "image/png"
+              },
+              {
+                "src": "256x256-green.png",
+                "sizes": "256x256",
+                "type": "image/png"
+              }
+            ]
+      },
+        "new_tab_button": {
+          "url": "/webapps_integration/tabbed/new_page.html"
+        }
+    }
+  }
\ No newline at end of file
diff --git a/chrome/test/data/webapps_integration/tabbed/new_page.html b/chrome/test/data/webapps_integration/tabbed/new_page.html
new file mode 100644
index 0000000..783b1d7
--- /dev/null
+++ b/chrome/test/data/webapps_integration/tabbed/new_page.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Tabbed</title>
+    <script src="/webapps_integration/test_utils.js"></script>
+    <script>
+      // If a "manifest=/path/to/manifest.json" query argument is provided to
+      // the URL accessing this page, that path is injected as the manifest tag.
+      // Otherwise, "basic.json" is used as the manifest tag.
+      addManifestLinkTag();
+    </script>
+</head>
+<body onload="startWorker('/webapps_integration/tabbed/service_worker.js', { scope: '/webapps_integration/tabbed/' })">
+  <h1>Tabbed Page One</h1>
+  <div>
+    <p>
+      This site is used for dPWA integration tests, and is subject to modification to support that framework. See
+      <a
+        href="https://chromium.googlesource.com/chromium/src/+/main/docs/webapps/integration-testing-framework.md">https://chromium.googlesource.com/chromium/src/+/main/docs/webapps/integration-testing-framework.md</a>
+    </p>
+  </div>
+</body>
+</html>
diff --git a/chrome/test/data/webapps_integration/tabbed/service_worker.js b/chrome/test/data/webapps_integration/tabbed/service_worker.js
new file mode 100644
index 0000000..0eeb46e
--- /dev/null
+++ b/chrome/test/data/webapps_integration/tabbed/service_worker.js
@@ -0,0 +1,11 @@
+// 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.
+
+'use strict';
+
+self.addEventListener('fetch', event => {
+  event.respondWith(fetch(event.request).catch(_ => {
+    return new Response('Offline test.');
+  }));
+});
diff --git a/chrome/test/data/webui/settings/safety_check_permissions_test.ts b/chrome/test/data/webui/settings/safety_check_permissions_test.ts
index 7fc8c5c..2ca6585 100644
--- a/chrome/test/data/webui/settings/safety_check_permissions_test.ts
+++ b/chrome/test/data/webui/settings/safety_check_permissions_test.ts
@@ -64,11 +64,13 @@
           ContentSettingsTypes.GEOLOCATION,
           ContentSettingsTypes.CAMERA,
         ],
+        expiration: '13317004800000000',  // Represents 2023-01-01T00:00:00.
       },
       {
         origin: origin2,
         permissions:
             [ContentSettingsTypes.POPUPS, ContentSettingsTypes.SENSORS],
+        expiration: '13348540800000000',  // Represents 2024-01-01T00:00:00.
       },
     ];
     createPage(mockData);
@@ -234,6 +236,7 @@
       origin: 'www.example1.com',
       permissions:
           [ContentSettingsTypes.GEOLOCATION, ContentSettingsTypes.CAMERA],
+      expiration: '13317004800000000',  // Represents 2023-01-01T00:00:00.
     },
   ];
 
diff --git a/chrome/test/data/webui/settings/site_settings_page_test.ts b/chrome/test/data/webui/settings/site_settings_page_test.ts
index 6e7448e..2fee89b 100644
--- a/chrome/test/data/webui/settings/site_settings_page_test.ts
+++ b/chrome/test/data/webui/settings/site_settings_page_test.ts
@@ -248,6 +248,7 @@
 const unusedSitePermissionMockData = [{
   origin: 'www.example.com',
   permissions: [ContentSettingsTypes.CAMERA],
+  expiration: '13317004800000000',  // Represents 2023-01-01T00:00:00.
 }];
 
 suite('UnusedSitePermissionsReview', function() {
diff --git a/chrome/test/data/webui/settings/unused_site_permissions_test.ts b/chrome/test/data/webui/settings/unused_site_permissions_test.ts
index 32411057..61df583 100644
--- a/chrome/test/data/webui/settings/unused_site_permissions_test.ts
+++ b/chrome/test/data/webui/settings/unused_site_permissions_test.ts
@@ -29,10 +29,12 @@
     ContentSettingsTypes.NOTIFICATIONS,
   ];
 
-  const mockData = [1, 2, 3, 4].map(i => ({
-                                      origin: `https://www.example${i}.com:443`,
-                                      permissions: permissions.slice(0, i),
-                                    }));
+  const mockData = [1, 2, 3, 4].map(
+      i => ({
+        origin: `https://www.example${i}.com:443`,
+        permissions: permissions.slice(0, i),
+        expiration: '13317004800000000',  // Represents 2023-01-01T00:00:00.
+      }));
 
   /* Asserts for each row whether or not it is animating. */
   function assertAnimation(expectedAnimation: boolean[]) {
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
index 80fb88d..adc0296 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
@@ -199,33 +199,24 @@
              : metadata.size;
 }
 
-bool CanPinItem(const mojom::FileMetadata& metadata,
-                const base::FilePath& path) {
+bool CanPinItem(const mojom::FileMetadata& md, const base::FilePath& path) {
   using Type = mojom::FileMetadata::Type;
-  const auto id = PinManager::Id(metadata.stable_id);
+  const auto id = PinManager::Id(md.stable_id);
 
-  if (metadata.type == Type::kDirectory) {
+  if (md.type == Type::kDirectory) {
     VLOG(2) << "Skipped " << id << " " << Quote(path) << ": Directory";
     return false;
   }
 
   // TODO (b/264596214) Drive shortcuts masquerade as empty files. Is there a
   // better way to recognize Drive shortcuts?
-  if (metadata.type == Type::kFile && metadata.size == 0) {
+  if (md.type == Type::kFile && md.size == 0) {
     VLOG(2) << "Skipped " << id << " " << Quote(path)
             << ": Empty file or shortcut";
     return false;
   }
 
-  if (metadata.pinned) {
-    VLOG(2) << "Skipped " << id << " " << Quote(path) << ": Already pinned";
-    VLOG_IF(3, !metadata.available_offline)
-        << "Already pinned but not available offline yet: " << id << " "
-        << Quote(path);
-    return false;
-  }
-
-  if (metadata.can_pin != mojom::FileMetadata::CanPinStatus::kOk) {
+  if (md.can_pin != mojom::FileMetadata::CanPinStatus::kOk) {
     VLOG(2) << "Skipped " << id << " " << Quote(path) << ": Cannot be pinned";
     return false;
   }
@@ -294,6 +285,13 @@
              << ")";
 }
 
+std::ostream& PinManager::File::PrintTo(std::ostream& out) const {
+  return out << "{transferred: " << HumanReadableSize(transferred)
+             << ", total: " << HumanReadableSize(total)
+             << ", pinned: " << pinned << ", in_progress: " << in_progress
+             << "}";
+}
+
 Progress::Progress() = default;
 Progress::Progress(const Progress&) = default;
 Progress& Progress::operator=(const Progress&) = default;
@@ -323,7 +321,8 @@
   progress_.bytes_to_pin += size;
   progress_.required_space += RoundToBlockSize(size);
   progress_.files_to_pin++;
-  DCHECK_EQ(static_cast<size_t>(progress_.files_to_pin), files_to_pin_.size());
+  DCHECK_EQ(static_cast<size_t>(progress_.files_to_pin),
+            files_to_pin_.size() + files_to_track_.size());
   return true;
 }
 
@@ -345,6 +344,9 @@
   }
 
   files_to_track_.erase(it);
+  progress_.syncing_files--;
+  DCHECK_EQ(static_cast<size_t>(progress_.syncing_files),
+            files_to_track_.size());
   VLOG(3) << "Stopped tracking " << id << " " << Quote(path);
   return true;
 }
@@ -439,6 +441,7 @@
   progress_ = {};
   files_to_pin_.clear();
   files_to_track_.clear();
+  DCHECK_EQ(progress_.syncing_files, 0);
 
   VLOG(1) << "Calculating free space...";
   timer_ = base::ElapsedTimer();
@@ -528,11 +531,36 @@
       continue;
     }
 
+    int64_t size = GetSize(md);
+
+    if (md.pinned) {
+      if (md.available_offline) {
+        VLOG(2) << "Skipped " << id << " " << Quote(path) << ": Already pinned";
+        continue;
+      }
+
+      VLOG(1) << "Already pinned but not available offline yet: " << id << " "
+              << Quote(path);
+      const auto [it, ok] = files_to_track_.try_emplace(
+          id, File{.path = path.value(), .total = size, .pinned = true});
+      DCHECK(ok);
+      DCHECK_EQ(it->first, id);
+      progress_.syncing_files++;
+      DCHECK_EQ(static_cast<size_t>(progress_.syncing_files),
+                files_to_track_.size());
+      progress_.bytes_to_pin += size;
+      progress_.required_space += RoundToBlockSize(size);
+      progress_.files_to_pin++;
+      DCHECK_EQ(static_cast<size_t>(progress_.files_to_pin),
+                files_to_pin_.size() + files_to_track_.size());
+      continue;
+    }
+
     VLOG_IF(1, md.available_offline)
         << "Not pinned yet but already available offline: " << id << " "
         << Quote(path) << ": " << Quote(md);
 
-    Add(id, path.value(), GetSize(md));
+    Add(id, path.value(), size);
   }
 
   NotifyProgress();
@@ -571,6 +599,7 @@
   search_query_.reset();
   files_to_pin_.clear();
   files_to_track_.clear();
+  progress_.syncing_files = 0;
 
   if (completion_callback_) {
     std::move(completion_callback_).Run(stage);
@@ -640,7 +669,7 @@
     Files::node_type node = files_to_pin_.extract(files_to_pin_.begin());
     DCHECK(node);
     const Id id = node.key();
-    const File& file = node.mapped();
+    File& file = node.mapped();
     const std::string& path = file.path;
 
     VLOG(2) << "Pinning " << id << " " << Quote(path);
@@ -648,9 +677,15 @@
         static_cast<int64_t>(id), true,
         base::BindOnce(&PinManager::OnFilePinned, GetWeakPtr(), id, path));
 
+    DCHECK(!file.pinned);
+    DCHECK(!file.in_progress);
+    file.pinned = true;
     const Files::insert_return_type ir =
         files_to_track_.insert(std::move(node));
     DCHECK(ir.inserted) << " for " << id << " " << path;
+    progress_.syncing_files++;
+    DCHECK_EQ(static_cast<size_t>(progress_.syncing_files),
+              files_to_track_.size());
   }
 
   VLOG(1) << "Progress "
@@ -810,9 +845,9 @@
   }
 
   for (const auto& [id, file] : files_to_track_) {
-    if (!file.in_progress) {
+    if (file.pinned && !file.in_progress) {
       const std::string& path = file.path;
-      VLOG(2) << "Checking unstarted " << id << " " << Quote(path);
+      VLOG(2) << "Checking stalled " << id << " " << Quote(path);
       drivefs_->GetMetadataByStableId(
           static_cast<int64_t>(id),
           base::BindOnce(&PinManager::OnMetadataRetrieved, GetWeakPtr(), id,
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager.h b/chromeos/ash/components/drivefs/drivefs_pin_manager.h
index 3113417..effd7243 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager.h
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager.h
@@ -92,6 +92,9 @@
   // Number of errors encountered so far.
   int32_t failed_files = 0;
 
+  // Number of files being synced right now.
+  int32_t syncing_files = 0;
+
   // Number of "useful" (ie non-duplicated) events received from DriveFS so far.
   int32_t useful_events = 0;
 
@@ -212,13 +215,16 @@
     // Total expected number of bytes for this file.
     int64_t total = 0;
 
+    // Is this file already pinned?
+    bool pinned = false;
+
     // Have we received in-progress events for this file?
     bool in_progress = false;
 
+    std::ostream& PrintTo(std::ostream& out) const;
+
     friend std::ostream& operator<<(std::ostream& out, const File& p) {
-      return out << "{transferred: " << HumanReadableSize(p.transferred)
-                 << ", total: " << HumanReadableSize(p.total)
-                 << ", in_progress: " << p.in_progress << "}";
+      return p.PrintTo(out);
     }
   };
 
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager_unittest.cc b/chromeos/ash/components/drivefs/drivefs_pin_manager_unittest.cc
index 64b2bba..c851ace2 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager_unittest.cc
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager_unittest.cc
@@ -349,6 +349,7 @@
     const auto [it, ok] = manager.files_to_track_.try_emplace(
         id1, PinManager::File{.path = path1, .total = size1});
     ASSERT_TRUE(ok);
+    manager.progress_.syncing_files++;
   }
 
   EXPECT_THAT(manager.files_to_track_, SizeIs(1));
@@ -549,13 +550,16 @@
                               .total = 3000,
                               .in_progress = true});
     ASSERT_TRUE(ok);
+    manager.progress_.syncing_files++;
   }
 
   EXPECT_THAT(manager.files_to_track_, SizeIs(1));
+  EXPECT_EQ(manager.progress_.syncing_files, 1);
 
   // Try to remove an unknown file.
   EXPECT_FALSE(manager.Remove(id2, path2));
   EXPECT_THAT(manager.files_to_track_, SizeIs(1));
+  EXPECT_EQ(manager.progress_.syncing_files, 1);
 
   {
     const auto it = manager.files_to_track_.find(id1);
@@ -574,6 +578,7 @@
     EXPECT_EQ(progress.pinned_bytes, 5000);
     EXPECT_EQ(progress.bytes_to_pin, 10000);
     EXPECT_EQ(progress.required_space, 20480);
+    EXPECT_EQ(progress.syncing_files, 1);
   }
 
   // Remove file with default final size.
@@ -586,6 +591,7 @@
     EXPECT_EQ(progress.pinned_bytes, 6800);
     EXPECT_EQ(progress.bytes_to_pin, 10000);
     EXPECT_EQ(progress.required_space, 20480);
+    EXPECT_EQ(progress.syncing_files, 0);
   }
 
   // Put in place a file to track.
@@ -596,6 +602,7 @@
                               .total = 3000,
                               .in_progress = true});
     ASSERT_TRUE(ok);
+    manager.progress_.syncing_files++;
   }
 
   EXPECT_THAT(manager.files_to_track_, SizeIs(1));
@@ -610,6 +617,7 @@
     EXPECT_EQ(progress.pinned_bytes, 5600);
     EXPECT_EQ(progress.bytes_to_pin, 7000);
     EXPECT_EQ(progress.required_space, 16384);
+    EXPECT_EQ(progress.syncing_files, 0);
   }
 
   // Put in place a file to track.
@@ -620,6 +628,7 @@
                               .total = 6000,
                               .in_progress = true});
     ASSERT_TRUE(ok);
+    manager.progress_.syncing_files++;
   }
 
   EXPECT_THAT(manager.files_to_track_, SizeIs(1));
@@ -634,6 +643,7 @@
     EXPECT_EQ(progress.pinned_bytes, 10600);
     EXPECT_EQ(progress.bytes_to_pin, 11000);
     EXPECT_EQ(progress.required_space, 20480);
+    EXPECT_EQ(progress.syncing_files, 0);
   }
 }
 
@@ -665,11 +675,13 @@
     const auto [it, ok] = manager.files_to_track_.try_emplace(
         id1, PinManager::File{.path = path1, .total = 10000});
     ASSERT_TRUE(ok);
+    manager.progress_.syncing_files++;
   }
   {
     const auto [it, ok] = manager.files_to_track_.try_emplace(
         id2, PinManager::File{.path = path2, .total = 20000});
     ASSERT_TRUE(ok);
+    manager.progress_.syncing_files++;
   }
 
   EXPECT_THAT(manager.files_to_track_, SizeIs(2));
@@ -689,6 +701,7 @@
 
   {
     const Progress progress = manager.GetProgress();
+    EXPECT_EQ(progress.syncing_files, 2);
     EXPECT_EQ(progress.failed_files, 0);
     EXPECT_EQ(progress.pinned_files, 0);
     EXPECT_EQ(progress.pinned_bytes, 0);
@@ -711,6 +724,7 @@
 
   {
     const Progress progress = manager.GetProgress();
+    EXPECT_EQ(progress.syncing_files, 2);
     EXPECT_EQ(progress.failed_files, 0);
     EXPECT_EQ(progress.pinned_files, 0);
     EXPECT_EQ(progress.pinned_bytes, 0);
@@ -745,6 +759,7 @@
 
   {
     const Progress progress = manager.GetProgress();
+    EXPECT_EQ(progress.syncing_files, 2);
     EXPECT_EQ(progress.failed_files, 0);
     EXPECT_EQ(progress.pinned_files, 0);
     EXPECT_EQ(progress.pinned_bytes, 5000);
@@ -779,6 +794,7 @@
 
   {
     const Progress progress = manager.GetProgress();
+    EXPECT_EQ(progress.syncing_files, 1);
     EXPECT_EQ(progress.failed_files, 0);
     EXPECT_EQ(progress.pinned_files, 1);
     EXPECT_EQ(progress.pinned_bytes, 10000);
@@ -807,6 +823,7 @@
 
   {
     const Progress progress = manager.GetProgress();
+    EXPECT_EQ(progress.syncing_files, 0);
     EXPECT_EQ(progress.failed_files, 1);
     EXPECT_EQ(progress.pinned_files, 1);
     EXPECT_EQ(progress.pinned_bytes, 10000);
diff --git a/chromeos/ash/components/drivefs/fake_drivefs.cc b/chromeos/ash/components/drivefs/fake_drivefs.cc
index 555214bb..1ae5657 100644
--- a/chromeos/ash/components/drivefs/fake_drivefs.cc
+++ b/chromeos/ash/components/drivefs/fake_drivefs.cc
@@ -322,6 +322,15 @@
   delegate_->DisplayConfirmDialog(std::move(reason), std::move(callback));
 }
 
+absl::optional<bool> FakeDriveFs::IsItemPinned(const std::string& path) {
+  for (const auto& metadata : metadata_) {
+    if (metadata.first.value() == path) {
+      return metadata.second.pinned;
+    }
+  }
+  return absl::nullopt;
+}
+
 void FakeDriveFs::Init(
     drivefs::mojom::DriveFsConfigurationPtr config,
     mojo::PendingReceiver<drivefs::mojom::DriveFs> receiver,
@@ -595,4 +604,6 @@
 
 void FakeDriveFs::PollHostedFilePinStates() {}
 
+void FakeDriveFs::CancelUploadByPath(const base::FilePath& path) {}
+
 }  // namespace drivefs
diff --git a/chromeos/ash/components/drivefs/fake_drivefs.h b/chromeos/ash/components/drivefs/fake_drivefs.h
index 7aac9779..680e555b 100644
--- a/chromeos/ash/components/drivefs/fake_drivefs.h
+++ b/chromeos/ash/components/drivefs/fake_drivefs.h
@@ -82,6 +82,8 @@
 
   const base::FilePath& mount_path() { return mount_path_; }
 
+  absl::optional<bool> IsItemPinned(const std::string& path);
+
  private:
   struct FileMetadata;
   class SearchQuery;
@@ -173,6 +175,8 @@
 
   void PollHostedFilePinStates() override;
 
+  void CancelUploadByPath(const base::FilePath& path) override;
+
   const base::FilePath mount_path_;
   int64_t next_stable_id_ = 1;
 
diff --git a/chromeos/ash/components/drivefs/mojom/drivefs.mojom b/chromeos/ash/components/drivefs/mojom/drivefs.mojom
index 88f3b8e7..bbab6fa 100644
--- a/chromeos/ash/components/drivefs/mojom/drivefs.mojom
+++ b/chromeos/ash/components/drivefs/mojom/drivefs.mojom
@@ -132,6 +132,10 @@
   // Get the metadata for the supplied `stable_id`.
   GetMetadataByStableId(int64 stable_id) => (
       FileError error, FileMetadata? metadata);
+
+  // Attempts to cancel an in progress upload. `path` must be made absolute
+  // from the drive mount point.
+  CancelUploadByPath(mojo_base.mojom.FilePath path);
 };
 
 // Implemented by Chrome, used from DriveFS.
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index 44047e0..b2baa738 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "17.58",
-  "log_list_timestamp": "2023-01-28T12:54:17Z",
+  "version": "17.59",
+  "log_list_timestamp": "2023-01-29T12:55:43Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc
index 915b3529..520138bc 100644
--- a/components/omnibox/browser/autocomplete_match.cc
+++ b/components/omnibox/browser/autocomplete_match.cc
@@ -1255,6 +1255,12 @@
 
 void AutocompleteMatch::UpgradeMatchWithPropertiesFrom(
     AutocompleteMatch& duplicate_match) {
+  // TODO(manukh): There's some duplicate logic between `BetterDuplicate()` and
+  //   `UpgradeMatchWithPropertiesFrom()`. This is unavoidable due to having to
+  //   taking different fields from different duplicates, rather having 1 match
+  //   that's absolutely overrides all other matches. Perhaps we can avoid this
+  //   if we join the 2 functions.
+
   // For Entity Matches, absorb the duplicate match's |allowed_to_be_default|
   // and |inline_autocompletion| properties.
   if (type == AutocompleteMatchType::SEARCH_SUGGEST_ENTITY &&
@@ -1290,6 +1296,22 @@
     actions = std::move(duplicate_match.actions);
   }
 
+  // Prefer fresh suggestion text over potentially stale shortcut text for
+  // bookmark paths and document metadata. Don't edit the omnibox text (i.e.
+  // `fill_into_edit`, `inline_autocompletion`, and `additional_text`) as the
+  // duplicate may not be `allowed_to_be_default_match`.
+  if (GetDeduplicationProviderPreferenceScore(
+          duplicate_match.provider->type()) >
+      GetDeduplicationProviderPreferenceScore(provider->type())) {
+    contents = duplicate_match.contents;
+    contents_class = duplicate_match.contents_class;
+    description = duplicate_match.description;
+    description_class = duplicate_match.description_class;
+    description_for_shortcuts = duplicate_match.description_for_shortcuts;
+    description_class_for_shortcuts =
+        duplicate_match.description_class_for_shortcuts;
+  }
+
   // Copy `rich_autocompletion_triggered` for counterfactual logging.
   if (rich_autocompletion_triggered == RichAutocompletionType::kNone) {
     rich_autocompletion_triggered =
diff --git a/components/omnibox/browser/autocomplete_match.h b/components/omnibox/browser/autocomplete_match.h
index 9195360..ca4f515 100644
--- a/components/omnibox/browser/autocomplete_match.h
+++ b/components/omnibox/browser/autocomplete_match.h
@@ -687,10 +687,15 @@
   // Additional helper text for each entry, such as a title or description.
   std::u16string description;
   ACMatchClassifications description_class;
-  // In the case of the document provider, the description includes a last
-  // updated date that may become stale. To avoid showing stale descriptions,
-  // when |description_for_shortcut| is not empty, it will be stored instead of
-  // |description| in the shortcuts provider.
+  // In the case of the document provider, `description` includes a last
+  // updated date that may become stale. Likewise for the bookmark provider,
+  // `contents` may be the path which may become stale when the bookmark is
+  // moved. To avoid showing stale text, when `description_for_shortcut`
+  // is not empty, it will be stored instead of `description` (or `contents` if
+  // `swap_contents_and_description` is true) in the shortcuts provider.
+  // TODO(manukh) This is a temporary misnomer (since it can represent both
+  //   `description` and `contents`) until `swap_contents_and_description` is
+  //   removed.
   std::u16string description_for_shortcuts;
   ACMatchClassifications description_class_for_shortcuts;
 
diff --git a/components/omnibox/browser/autocomplete_match_unittest.cc b/components/omnibox/browser/autocomplete_match_unittest.cc
index 799d5336..1e8145f 100644
--- a/components/omnibox/browser/autocomplete_match_unittest.cc
+++ b/components/omnibox/browser/autocomplete_match_unittest.cc
@@ -443,28 +443,52 @@
     CheckDuplicateCase(caseI);
 }
 
-TEST(AutocompleteMatchTest, UpgradeMatchPropertiesWhileMergingDuplicates) {
-  AutocompleteMatch search_history_match(nullptr, 500, true,
+TEST(AutocompleteMatchTest, UpgradeMatchWithPropertiesFrom) {
+  scoped_refptr<FakeAutocompleteProvider> bookmark_provider =
+      new FakeAutocompleteProvider(AutocompleteProvider::Type::TYPE_BOOKMARK);
+  scoped_refptr<FakeAutocompleteProvider> history_provider =
+      new FakeAutocompleteProvider(
+          AutocompleteProvider::Type::TYPE_HISTORY_QUICK);
+  scoped_refptr<FakeAutocompleteProvider> search_provider =
+      new FakeAutocompleteProvider(AutocompleteProvider::Type::TYPE_SEARCH);
+
+  AutocompleteMatch search_history_match(search_provider.get(), 500, true,
                                          AutocompleteMatchType::SEARCH_HISTORY);
 
   // Entity match should get the increased score, but not change types.
-  AutocompleteMatch entity_match(nullptr, 400, false,
+  AutocompleteMatch entity_match(search_provider.get(), 400, false,
                                  AutocompleteMatchType::SEARCH_SUGGEST_ENTITY);
   entity_match.UpgradeMatchWithPropertiesFrom(search_history_match);
-  EXPECT_EQ(500, entity_match.relevance);
-  EXPECT_EQ(AutocompleteMatchType::SEARCH_SUGGEST_ENTITY, entity_match.type);
+  EXPECT_EQ(entity_match.relevance, 500);
+  EXPECT_EQ(entity_match.type, AutocompleteMatchType::SEARCH_SUGGEST_ENTITY);
 
   // Suggest and search-what-typed matches should get the search history type.
-  AutocompleteMatch suggest_match(nullptr, 400, true,
+  AutocompleteMatch suggest_match(search_provider.get(), 400, true,
                                   AutocompleteMatchType::SEARCH_SUGGEST);
   AutocompleteMatch search_what_you_typed(
-      nullptr, 400, true, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED);
+      search_provider.get(), 400, true,
+      AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED);
   suggest_match.UpgradeMatchWithPropertiesFrom(search_history_match);
   search_what_you_typed.UpgradeMatchWithPropertiesFrom(search_history_match);
-  EXPECT_EQ(500, suggest_match.relevance);
-  EXPECT_EQ(500, search_what_you_typed.relevance);
-  EXPECT_EQ(AutocompleteMatchType::SEARCH_HISTORY, suggest_match.type);
-  EXPECT_EQ(AutocompleteMatchType::SEARCH_HISTORY, search_what_you_typed.type);
+  EXPECT_EQ(suggest_match.relevance, 500);
+  EXPECT_EQ(search_what_you_typed.relevance, 500);
+  EXPECT_EQ(suggest_match.type, AutocompleteMatchType::SEARCH_HISTORY);
+  EXPECT_EQ(search_what_you_typed.type, AutocompleteMatchType::SEARCH_HISTORY);
+
+  // Some providers should bestow their suggestion texts even if not the primary
+  // duplicate.
+  AutocompleteMatch history_match(history_provider.get(), 800, true,
+                                  AutocompleteMatchType::HISTORY_TITLE);
+  AutocompleteMatch bookmark_match(bookmark_provider.get(), 400, true,
+                                   AutocompleteMatchType::BOOKMARK_TITLE);
+  history_match.contents = u"overwrite";
+  history_match.inline_autocompletion = u"preserve";
+  bookmark_match.contents = u"propagate";
+  bookmark_match.inline_autocompletion = u"discard";
+  history_match.UpgradeMatchWithPropertiesFrom(bookmark_match);
+  EXPECT_EQ(history_match.type, AutocompleteMatchType::HISTORY_TITLE);
+  EXPECT_EQ(history_match.contents, u"propagate");
+  EXPECT_EQ(history_match.inline_autocompletion, u"preserve");
 }
 
 TEST(AutocompleteMatchTest, MergeScoringSignals) {
diff --git a/components/omnibox/browser/shortcuts_backend.cc b/components/omnibox/browser/shortcuts_backend.cc
index a460d3c..ed3ff4b 100644
--- a/components/omnibox/browser/shortcuts_backend.cc
+++ b/components/omnibox/browser/shortcuts_backend.cc
@@ -66,23 +66,6 @@
   }
 }
 
-// Get either `description_for_shortcuts` if non-empty or fallback to
-// `description`.
-const std::u16string& GetDescription(const AutocompleteMatch& match) {
-  return match.description_for_shortcuts.empty()
-             ? match.description
-             : match.description_for_shortcuts;
-}
-
-// Get either `description_class_for_shortcuts` if non-empty or fallback to
-// `description_class`.
-const ACMatchClassifications& GetDescriptionClass(
-    const AutocompleteMatch& match) {
-  return match.description_class_for_shortcuts.empty()
-             ? match.description_class
-             : match.description_class_for_shortcuts;
-}
-
 // Expand the last word in `text` to a full word in `match_text`. E.g., if
 // `text` is 'Cha Aznav' and the `match_text` is 'Charles Aznavour', will return
 // 'Cha Aznavour'.
@@ -182,6 +165,56 @@
 
 // ShortcutsBackend -----------------------------------------------------------
 
+// static
+const std::u16string& ShortcutsBackend::GetDescription(
+    const AutocompleteMatch& match) {
+  return match.swap_contents_and_description ||
+                 match.description_for_shortcuts.empty()
+             ? match.description
+             : match.description_for_shortcuts;
+}
+
+// static
+const std::u16string& ShortcutsBackend::GetSwappedDescription(
+    const AutocompleteMatch& match) {
+  return match.swap_contents_and_description ? GetContents(match)
+                                             : GetDescription(match);
+}
+
+// static
+const ACMatchClassifications& ShortcutsBackend::GetDescriptionClass(
+    const AutocompleteMatch& match) {
+  return match.swap_contents_and_description ||
+                 match.description_class_for_shortcuts.empty()
+             ? match.description_class
+             : match.description_class_for_shortcuts;
+}
+
+// static
+const std::u16string& ShortcutsBackend::GetContents(
+    const AutocompleteMatch& match) {
+  return !match.swap_contents_and_description ||
+                 match.description_for_shortcuts.empty()
+             ? match.contents
+             : match.description_for_shortcuts;
+}
+
+// static
+const std::u16string& ShortcutsBackend::GetSwappedContents(
+    const AutocompleteMatch& match) {
+  return match.swap_contents_and_description ? match.description
+                                             : match.contents;
+}
+
+// static
+const ACMatchClassifications& ShortcutsBackend::GetContentsClass(
+    const AutocompleteMatch& match) {
+  return !match.swap_contents_and_description ||
+                 match.description_class_for_shortcuts.empty()
+             ? match.contents_class
+             : match.description_class_for_shortcuts;
+}
+
 ShortcutsBackend::ShortcutsBackend(
     TemplateURLService* template_url_service,
     std::unique_ptr<SearchTermsData> search_terms_data,
@@ -305,13 +338,10 @@
   // is usually also recognizable and helpful when there are whitespace or other
   // discrepancies between the title and host (e.g. 'Stack Overflow' and
   // 'stackoverflow.com').
-  const auto& match_text = match.swap_contents_and_description
-                               ? GetDescription(match)
-                               : match.contents;
   const auto expanded_text =
       OmniboxFieldTrial::IsShortcutExpandingEnabled()
           ? ExpandToFullWord(
-                text, match_text + u" " +
+                text, GetSwappedContents(match) + u" " +
                           base::UTF8ToUTF16(match.destination_url.host()))
           : text;
   AddShortcut(ShortcutsDatabase::Shortcut(
@@ -346,8 +376,8 @@
 
   return ShortcutsDatabase::Shortcut::MatchCore(
       normalized_match->fill_into_edit, normalized_match->destination_url,
-      normalized_match->document_type, normalized_match->contents,
-      StripMatchMarkers(normalized_match->contents_class),
+      normalized_match->document_type, GetContents(*normalized_match),
+      StripMatchMarkers(GetContentsClass(*normalized_match)),
       GetDescription(*normalized_match),
       StripMatchMarkers(GetDescriptionClass(*normalized_match)),
       normalized_match->transition, match_type, normalized_match->keyword);
diff --git a/components/omnibox/browser/shortcuts_backend.h b/components/omnibox/browser/shortcuts_backend.h
index a42a53b..08b1fb1 100644
--- a/components/omnibox/browser/shortcuts_backend.h
+++ b/components/omnibox/browser/shortcuts_backend.h
@@ -47,6 +47,23 @@
   typedef std::multimap<std::u16string, const ShortcutsDatabase::Shortcut>
       ShortcutMap;
 
+  // Get either `contents`, `description`, or `description_class_for_shortcuts`
+  // (or their classifications) depending on the method called,
+  // `swap_contents_and_description`, and whether
+  // `description_class_for_shortcuts` is empty.
+  // TODO(manukh): Simplify these once `swap_contents_and_description` is
+  //   removed.
+  static const std::u16string& GetDescription(const AutocompleteMatch& match);
+  static const std::u16string& GetSwappedDescription(
+      const AutocompleteMatch& match);
+  static const ACMatchClassifications& GetDescriptionClass(
+      const AutocompleteMatch& match);
+  static const std::u16string& GetContents(const AutocompleteMatch& match);
+  static const std::u16string& GetSwappedContents(
+      const AutocompleteMatch& match);
+  static const ACMatchClassifications& GetContentsClass(
+      const AutocompleteMatch& match);
+
   // For unit testing, set |suppress_db| to true to prevent creation
   // of the database, in which case all operations are performed in memory only.
   ShortcutsBackend(TemplateURLService* template_url_service,
diff --git a/components/omnibox/browser/shortcuts_provider.cc b/components/omnibox/browser/shortcuts_provider.cc
index d52037a..b94cc29 100644
--- a/components/omnibox/browser/shortcuts_provider.cc
+++ b/components/omnibox/browser/shortcuts_provider.cc
@@ -508,17 +508,18 @@
 #else
     } else {
 #endif
-      // Try rich autocompletion first. For document suggestions,
-      // `match.contents` is the title, while `description` is something like
-      // 'Google Docs' and shouldn't be autocompleted. For all other nav
-      // suggestions, `contents` is the URL and `description` is the title.
+      // Try rich autocompletion first. For document suggestions, hide the
+      // URL from `additional_text` and don't try to inline the metadata (e.g.
+      // 'Google Docs' or '1/1/2023').
       bool autocompleted =
           match.type == AutocompleteMatch::Type::DOCUMENT_SUGGESTION
-              ? match.TryRichAutocompletion(u"", match.contents, input,
-                                            shortcut.text)
-              : match.TryRichAutocompletion(match.contents, match.description,
-                                            input, shortcut.text);
-
+              ? match.TryRichAutocompletion(
+                    u"", ShortcutsBackend::GetSwappedContents(match), input,
+                    shortcut.text)
+              : match.TryRichAutocompletion(
+                    ShortcutsBackend::GetSwappedContents(match),
+                    ShortcutsBackend::GetSwappedDescription(match), input,
+                    shortcut.text);
       if (!autocompleted) {
         const size_t inline_autocomplete_offset =
             URLPrefix::GetInlineAutocompleteOffset(
diff --git a/components/omnibox/browser/titled_url_match_utils.cc b/components/omnibox/browser/titled_url_match_utils.cc
index 510b7356..a9c1230 100644
--- a/components/omnibox/browser/titled_url_match_utils.cc
+++ b/components/omnibox/browser/titled_url_match_utils.cc
@@ -85,11 +85,14 @@
   // Otherwise, display the path, even if the input matches both or neither.
   // Except if kBookmarkPaths is disabled, in which case, always display the
   // URL.
-  match.contents = !base::FeatureList::IsEnabled(omnibox::kBookmarkPaths) ||
-                           (!titled_url_match.has_ancestor_match &&
-                            !titled_url_match.url_match_positions.empty())
-                       ? formatted_url
-                       : path;
+  bool show_path = base::FeatureList::IsEnabled(omnibox::kBookmarkPaths) &&
+                   (titled_url_match.has_ancestor_match ||
+                    titled_url_match.url_match_positions.empty());
+  match.contents = show_path ? path : formatted_url;
+  // The path can become stale (when the bookmark is moved). So persist the URL
+  // instead when creating shortcuts.
+  if (show_path)
+    match.description_for_shortcuts = formatted_url;
 
   // Bookmark classification diverges from relevance scoring. Specifically,
   // 1) All occurrences of the input contribute to relevance; e.g. for the input
@@ -108,6 +111,14 @@
       ACMatchClassification::MATCH | ACMatchClassification::URL,
       ACMatchClassification::URL);
 
+  if (show_path) {
+    auto terms = FindTermMatches(input.text(), match.description_for_shortcuts);
+    match.description_class_for_shortcuts = ClassifyTermMatches(
+        terms, match.description_for_shortcuts.length(),
+        ACMatchClassification::MATCH | ACMatchClassification::URL,
+        ACMatchClassification::URL);
+  }
+
   match.description = title;
 
   base::TrimWhitespace(match.description, base::TRIM_LEADING,
diff --git a/components/permissions/unused_site_permissions_service.cc b/components/permissions/unused_site_permissions_service.cc
index b19f855..c57a533 100644
--- a/components/permissions/unused_site_permissions_service.cc
+++ b/components/permissions/unused_site_permissions_service.cc
@@ -285,7 +285,15 @@
        itr != recently_unused_permissions_.end();) {
     std::list<ContentSettingEntry>& unused_site_permissions = itr->second;
 
-    std::list<ContentSettingEntry> revoked_permissions;
+    // All |primary_pattern|s are equal across list items, the same is true for
+    // |secondary_pattern|s. This property is needed later and checked in the
+    // loop.
+    ContentSettingsPattern primary_pattern =
+        unused_site_permissions.front().source.primary_pattern;
+    ContentSettingsPattern secondary_pattern =
+        unused_site_permissions.front().source.secondary_pattern;
+
+    std::list<ContentSettingsType> revoked_permissions;
     for (auto permission_itr = unused_site_permissions.begin();
          permission_itr != unused_site_permissions.end();) {
       const ContentSettingEntry& entry = *permission_itr;
@@ -297,6 +305,9 @@
         continue;
       }
 
+      DCHECK_EQ(entry.source.primary_pattern, primary_pattern);
+      DCHECK_EQ(entry.source.secondary_pattern, secondary_pattern);
+
       // Reset the permission to default if the site is visited before
       // threshold. Also, the secondary pattern should be wildcard.
       DCHECK(entry.source.metadata.last_visited != base::Time());
@@ -304,7 +315,7 @@
       if (entry.source.metadata.last_visited < threshold &&
           entry.source.secondary_pattern ==
               ContentSettingsPattern::Wildcard()) {
-        revoked_permissions.push_back(entry);
+        revoked_permissions.push_back(entry.type);
         hcsm_->SetContentSettingCustomScope(
             entry.source.primary_pattern, entry.source.secondary_pattern,
             entry.type, ContentSetting::CONTENT_SETTING_DEFAULT);
@@ -316,7 +327,9 @@
 
     // Store revoked permissions on HCSM.
     if (!revoked_permissions.empty()) {
-      StorePermissionInRevokedPermissionSetting(revoked_permissions);
+      StorePermissionInRevokedPermissionSetting(revoked_permissions,
+                                                absl::nullopt, primary_pattern,
+                                                secondary_pattern);
     }
 
     // Handle clean up of recently_unused_permissions_ map after revocation.
@@ -338,14 +351,24 @@
 }
 
 void UnusedSitePermissionsService::StorePermissionInRevokedPermissionSetting(
-    const std::list<UnusedSitePermissionsService::ContentSettingEntry>&
-        recently_revoked_permissions) {
-  DCHECK(!recently_revoked_permissions.empty());
-  const ContentSettingsPattern& primary_pattern =
-      recently_revoked_permissions.front().source.primary_pattern;
-  const ContentSettingsPattern& secondary_pattern =
-      recently_revoked_permissions.front().source.secondary_pattern;
+    const std::list<ContentSettingsType> permissions,
+    const absl::optional<content_settings::ContentSettingConstraints>
+        constraint,
+    const url::Origin origin) {
+  // The |secondary_pattern| for
+  // |ContentSettingsType::REVOKED_UNUSED_SITE_PERMISSIONS| is always wildcard.
+  StorePermissionInRevokedPermissionSetting(
+      permissions, constraint,
+      ContentSettingsPattern::FromURLNoWildcard(origin.GetURL()),
+      ContentSettingsPattern::Wildcard());
+}
 
+void UnusedSitePermissionsService::StorePermissionInRevokedPermissionSetting(
+    const std::list<ContentSettingsType> permissions,
+    const absl::optional<content_settings::ContentSettingConstraints>
+        constraint,
+    const ContentSettingsPattern& primary_pattern,
+    const ContentSettingsPattern& secondary_pattern) {
   GURL url = GURL(primary_pattern.ToString());
   // The url should be valid as it is checked that the pattern represents a
   // single origin.
@@ -362,13 +385,13 @@
           ? std::move(*dict.FindList(permissions::kRevokedKey))
           : base::Value::List();
 
-  for (const auto& permission : recently_revoked_permissions) {
-    permission_type_list.Append(static_cast<int32_t>(permission.type));
+  for (const auto& permission : permissions) {
+    permission_type_list.Append(static_cast<int32_t>(permission));
   }
 
   dict.Set(kRevokedKey, base::Value::List(std::move(permission_type_list)));
 
-  const content_settings::ContentSettingConstraints constraint{
+  const content_settings::ContentSettingConstraints default_constraint = {
       .expiration = clock_->Now() + GetCleanUpThreshold()};
 
   // Set website setting for the list of recently revoked permissions and
@@ -376,7 +399,8 @@
   hcsm_->SetWebsiteSettingCustomScope(
       primary_pattern, secondary_pattern,
       ContentSettingsType::REVOKED_UNUSED_SITE_PERMISSIONS,
-      base::Value(std::move(dict)), constraint);
+      base::Value(std::move(dict)),
+      constraint.has_value() ? constraint.value() : default_constraint);
 }
 
 void UnusedSitePermissionsService::UpdateUnusedPermissionsForTesting() {
diff --git a/components/permissions/unused_site_permissions_service.h b/components/permissions/unused_site_permissions_service.h
index a5cc514..dadd2a45 100644
--- a/components/permissions/unused_site_permissions_service.h
+++ b/components/permissions/unused_site_permissions_service.h
@@ -14,6 +14,7 @@
 #include "base/time/clock.h"
 #include "base/timer/timer.h"
 #include "components/content_settings/core/common/content_settings.h"
+#include "components/content_settings/core/common/content_settings_pattern.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -90,6 +91,13 @@
   // the user. Does not change permissions themselves.
   void ClearRevokedPermissionsList();
 
+  // Stores revoked permissions data on HCSM.
+  void StorePermissionInRevokedPermissionSetting(
+      const std::list<ContentSettingsType> permissions,
+      const absl::optional<content_settings::ContentSettingConstraints>
+          constraint,
+      const url::Origin origin);
+
   // Test support:
   void SetClockForTesting(base::Clock* clock);
   std::vector<ContentSettingEntry> GetTrackedUnusedPermissionsForTesting();
@@ -115,8 +123,11 @@
 
   // Stores revoked permissions data on HCSM.
   void StorePermissionInRevokedPermissionSetting(
-      const std::list<UnusedSitePermissionsService::ContentSettingEntry>&
-          recently_revoked_permissions);
+      const std::list<ContentSettingsType> permissions,
+      const absl::optional<content_settings::ContentSettingConstraints>
+          constraint,
+      const ContentSettingsPattern& primary_pattern,
+      const ContentSettingsPattern& secondary_pattern);
 
   // Set of permissions that haven't been used for at least a week.
   UnusedPermissionMap recently_unused_permissions_;
diff --git a/components/permissions/unused_site_permissions_service_unittest.cc b/components/permissions/unused_site_permissions_service_unittest.cc
index 9051dc3..85ec54e 100644
--- a/components/permissions/unused_site_permissions_service_unittest.cc
+++ b/components/permissions/unused_site_permissions_service_unittest.cc
@@ -223,6 +223,49 @@
   EXPECT_EQ(GetRevokedPermissionsForOneOrigin(hcsm(), url).size(), 0u);
 }
 
+TEST_F(UnusedSitePermissionsServiceTest, SecondaryPatternAlwaysWildcard) {
+  base::test::ScopedFeatureList scoped_feature;
+  scoped_feature.InitAndEnableFeature(
+      content_settings::features::kSafetyCheckUnusedSitePermissions);
+
+  const ContentSettingsType types[] = {
+      ContentSettingsType::GEOLOCATION,
+      ContentSettingsType::AUTOMATIC_DOWNLOADS};
+  const content_settings::ContentSettingConstraints constraint{
+      .track_last_visit_for_autoexpiration = true};
+
+  // Test combinations of a single origin |primary_pattern| and different
+  // |secondary_pattern|s: equal to primary pattern, different single origin
+  // pattern, with domain with wildcard, wildcard.
+  for (const auto type : types) {
+    hcsm()->SetContentSettingDefaultScope(
+        GURL("https://example1.com"), GURL("https://example1.com"), type,
+        ContentSetting::CONTENT_SETTING_ALLOW, constraint);
+    hcsm()->SetContentSettingDefaultScope(
+        GURL("https://example2.com"), GURL("https://example3.com"), type,
+        ContentSetting::CONTENT_SETTING_ALLOW, constraint);
+    hcsm()->SetContentSettingDefaultScope(
+        GURL("https://example3.com"), GURL("https://[*.]example1.com"), type,
+        ContentSetting::CONTENT_SETTING_ALLOW, constraint);
+    hcsm()->SetContentSettingDefaultScope(
+        GURL("https://example4.com"), GURL("*"), type,
+        ContentSetting::CONTENT_SETTING_ALLOW, constraint);
+  }
+
+  service()->UpdateUnusedPermissionsForTesting();
+  EXPECT_EQ(GetRevokedUnusedPermissions(hcsm()).size(), 0u);
+
+  // Travel through time for 70 days so that permissions are revoked.
+  clock()->Advance(base::Days(70));
+  service()->UpdateUnusedPermissionsForTesting();
+
+  EXPECT_EQ(GetRevokedUnusedPermissions(hcsm()).size(), 4u);
+  for (auto unused_permission : GetRevokedUnusedPermissions(hcsm())) {
+    EXPECT_EQ(unused_permission.secondary_pattern,
+              ContentSettingsPattern::Wildcard());
+  }
+}
+
 TEST_F(UnusedSitePermissionsServiceTest, MultipleRevocationsForSameOrigin) {
   base::test::ScopedFeatureList scoped_feature;
   scoped_feature.InitAndEnableFeature(
diff --git a/components/services/app_service/public/cpp/preferred_apps_converter.cc b/components/services/app_service/public/cpp/preferred_apps_converter.cc
index b04448aac..d2a8fad 100644
--- a/components/services/app_service/public/cpp/preferred_apps_converter.cc
+++ b/components/services/app_service/public/cpp/preferred_apps_converter.cc
@@ -3,58 +3,63 @@
 // found in the LICENSE file.
 
 #include <memory>
+#include <string>
 #include <utility>
 
 #include "base/logging.h"
+#include "base/values.h"
 #include "components/services/app_service/public/cpp/intent_filter.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/cpp/preferred_apps_converter.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace {
 
 constexpr int kVersionInitial = 0;
 constexpr int kVersionSupportsSharing = 1;
 
-base::Value ConvertConditionValueToValue(
+base::Value::Dict ConvertConditionValueToDict(
     const apps::ConditionValuePtr& condition_value) {
-  base::Value condition_value_dict(base::Value::Type::DICT);
-  condition_value_dict.SetStringKey(apps::kValueKey, condition_value->value);
-  condition_value_dict.SetIntKey(apps::kMatchTypeKey,
-                                 static_cast<int>(condition_value->match_type));
+  base::Value::Dict condition_value_dict;
+  condition_value_dict.Set(apps::kValueKey, condition_value->value);
+  condition_value_dict.Set(apps::kMatchTypeKey,
+                           static_cast<int>(condition_value->match_type));
   return condition_value_dict;
 }
 
-base::Value ConvertConditionToValue(const apps::ConditionPtr& condition) {
-  base::Value condition_dict(base::Value::Type::DICT);
-  condition_dict.SetIntKey(apps::kConditionTypeKey,
-                           static_cast<int>(condition->condition_type));
+base::Value::Dict ConvertConditionToDict(const apps::ConditionPtr& condition) {
+  base::Value::Dict condition_dict;
+  condition_dict.Set(apps::kConditionTypeKey,
+                     static_cast<int>(condition->condition_type));
   base::Value condition_values_list(base::Value::Type::LIST);
   for (auto& condition_value : condition->condition_values) {
-    condition_values_list.Append(ConvertConditionValueToValue(condition_value));
+    condition_values_list.Append(
+        base::Value(ConvertConditionValueToDict(condition_value)));
   }
-  condition_dict.SetKey(apps::kConditionValuesKey,
-                        std::move(condition_values_list));
+  condition_dict.Set(apps::kConditionValuesKey,
+                     std::move(condition_values_list));
   return condition_dict;
 }
 
-base::Value ConvertIntentFilterToValue(
+base::Value::List ConvertIntentFilterToList(
     const apps::IntentFilterPtr& intent_filter) {
-  base::Value intent_filter_value(base::Value::Type::LIST);
+  base::Value::List intent_filter_list;
   for (auto& condition : intent_filter->conditions) {
-    intent_filter_value.Append(ConvertConditionToValue(condition));
+    intent_filter_list.Append(base::Value(ConvertConditionToDict(condition)));
   }
-  return intent_filter_value;
+  return intent_filter_list;
 }
 
-apps::ConditionValuePtr ParseValueToConditionValue(const base::Value& value) {
-  auto* value_string = value.FindStringKey(apps::kValueKey);
+apps::ConditionValuePtr ParseDictToConditionValue(
+    const base::Value::Dict& dict) {
+  const std::string* value_string = dict.FindString(apps::kValueKey);
   if (!value_string) {
     DVLOG(0) << "Fail to parse condition value. Cannot find \""
              << apps::kValueKey << "\" key with string value.";
     return nullptr;
   }
-  auto match_type = value.FindIntKey(apps::kMatchTypeKey);
-  if (!match_type.has_value()) {
+  const absl::optional<int> match_type = dict.FindInt(apps::kMatchTypeKey);
+  if (!match_type) {
     DVLOG(0) << "Fail to parse condition value. Cannot find \""
              << apps::kMatchTypeKey << "\" key with int value.";
     return nullptr;
@@ -71,23 +76,25 @@
                                                 pattern_match_type);
 }
 
-apps::ConditionPtr ParseValueToCondition(const base::Value& value) {
-  auto condition_type = value.FindIntKey(apps::kConditionTypeKey);
-  if (!condition_type.has_value()) {
+apps::ConditionPtr ParseDictToCondition(const base::Value::Dict& dict) {
+  const absl::optional<int> condition_type =
+      dict.FindInt(apps::kConditionTypeKey);
+  if (!condition_type) {
     DVLOG(0) << "Fail to parse condition. Cannot find \""
              << apps::kConditionTypeKey << "\" key with int value.";
     return nullptr;
   }
 
   apps::ConditionValues condition_values;
-  auto* values = value.FindKey(apps::kConditionValuesKey);
-  if (!values || !values->is_list()) {
+  const base::Value::List* values = dict.FindList(apps::kConditionValuesKey);
+  if (!values) {
     DVLOG(0) << "Fail to parse condition. Cannot find \""
              << apps::kConditionValuesKey << "\" key with list value.";
     return nullptr;
   }
-  for (auto& condition_value : values->GetList()) {
-    auto parsed_condition_value = ParseValueToConditionValue(condition_value);
+  for (const base::Value& condition_value : *values) {
+    auto parsed_condition_value =
+        ParseDictToConditionValue(condition_value.GetDict());
     if (!parsed_condition_value) {
       DVLOG(0) << "Fail to parse condition. Cannot parse condition values";
       return nullptr;
@@ -106,8 +113,8 @@
     return nullptr;
   }
   auto intent_filter = std::make_unique<apps::IntentFilter>();
-  for (auto& condition : value->GetList()) {
-    auto parsed_condition = ParseValueToCondition(condition);
+  for (const base::Value& condition : value->GetList()) {
+    auto parsed_condition = ParseDictToCondition(condition.GetDict());
     if (!parsed_condition) {
       DVLOG(0) << "Fail to parse intent filter. Cannot parse conditions.";
       return nullptr;
@@ -131,21 +138,19 @@
 const char kVersionKey[] = "version";
 
 base::Value ConvertPreferredAppsToValue(const PreferredApps& preferred_apps) {
-  base::Value preferred_apps_value(base::Value::Type::DICT);
+  base::Value::Dict preferred_apps_dict;
   int version = kVersionSupportsSharing;
-  preferred_apps_value.SetIntKey(kVersionKey, version);
-  base::Value preferred_apps_list(base::Value::Type::LIST);
+  preferred_apps_dict.Set(kVersionKey, version);
+  base::Value::List preferred_apps_list;
   for (auto& preferred_app : preferred_apps) {
-    base::Value preferred_app_dict(base::Value::Type::DICT);
-    preferred_app_dict.SetKey(
-        kIntentFilterKey,
-        ConvertIntentFilterToValue(preferred_app->intent_filter));
-    preferred_app_dict.SetStringKey(kAppIdKey, preferred_app->app_id);
+    base::Value::Dict preferred_app_dict;
+    preferred_app_dict.Set(kIntentFilterKey, ConvertIntentFilterToList(
+                                                 preferred_app->intent_filter));
+    preferred_app_dict.Set(kAppIdKey, preferred_app->app_id);
     preferred_apps_list.Append(std::move(preferred_app_dict));
   }
-  preferred_apps_value.SetKey(kPreferredAppsKey,
-                              std::move(preferred_apps_list));
-  return preferred_apps_value;
+  preferred_apps_dict.Set(kPreferredAppsKey, std::move(preferred_apps_list));
+  return base::Value(std::move(preferred_apps_dict));
 }
 
 PreferredApps ParseValueToPreferredApps(
@@ -163,15 +168,16 @@
   }
 
   PreferredApps preferred_apps;
-  for (auto& entry : preferred_apps_list->GetList()) {
-    auto* app_id = entry.FindStringKey(kAppIdKey);
+  for (const base::Value& entry_val : preferred_apps_list->GetList()) {
+    const base::Value::Dict& entry = entry_val.GetDict();
+    const std::string* app_id = entry.FindString(kAppIdKey);
     if (!app_id) {
       DVLOG(0) << "Fail to parse condition value. Cannot find \""
                << apps::kAppIdKey << "\" key with string value.";
       return PreferredApps();
     }
     auto parsed_intent_filter =
-        ParseValueToIntentFilter(entry.FindKey(kIntentFilterKey));
+        ParseValueToIntentFilter(entry.Find(kIntentFilterKey));
     if (!parsed_intent_filter) {
       DVLOG(0) << "Fail to parse condition value. Cannot parse intent filter.";
       return PreferredApps();
diff --git a/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc b/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc
index 8e103e8..67d77fa6 100644
--- a/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc
+++ b/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/services/app_service/public/cpp/preferred_apps_converter.h"
 
 #include "base/json/json_reader.h"
+#include "base/values.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/cpp/intent_test_util.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
@@ -32,30 +33,34 @@
       apps::ConvertPreferredAppsToValue(preferred_apps.GetReference());
 
   auto* converted_preferred_apps =
-      converted_value.FindKey(apps::kPreferredAppsKey);
+      converted_value.GetDict().Find(apps::kPreferredAppsKey);
   // Check that each entry is correct.
   ASSERT_EQ(1u, converted_preferred_apps->GetList().size());
-  auto& entry = converted_preferred_apps->GetList()[0];
-  EXPECT_EQ(kAppId1, *entry.FindStringKey(apps::kAppIdKey));
+  const base::Value& entry_val = converted_preferred_apps->GetList()[0];
+  const base::Value::Dict& entry = entry_val.GetDict();
+  EXPECT_EQ(kAppId1, *entry.FindString(apps::kAppIdKey));
 
-  auto* converted_intent_filter = entry.FindKey(apps::kIntentFilterKey);
-  ASSERT_EQ(intent_filter->conditions.size(),
-            converted_intent_filter->GetList().size());
+  const base::Value::List* converted_intent_filter =
+      entry.FindList(apps::kIntentFilterKey);
+  ASSERT_EQ(intent_filter->conditions.size(), converted_intent_filter->size());
 
   for (size_t i = 0; i < intent_filter->conditions.size(); i++) {
     auto& condition = intent_filter->conditions[i];
-    auto& converted_condition = converted_intent_filter->GetList()[i];
+    const base::Value::Dict& converted_condition =
+        (*converted_intent_filter)[i].GetDict();
     auto& condition_values = condition->condition_values;
-    const auto& converted_condition_values =
-        converted_condition.FindKey(apps::kConditionValuesKey)->GetList();
+    const base::Value::List* converted_condition_values =
+        converted_condition.FindList(apps::kConditionValuesKey);
 
     EXPECT_EQ(static_cast<int>(condition->condition_type),
-              converted_condition.FindIntKey(apps::kConditionTypeKey));
-    ASSERT_EQ(1u, converted_condition_values.size());
+              converted_condition.FindInt(apps::kConditionTypeKey));
+    ASSERT_EQ(1u, converted_condition_values->size());
     EXPECT_EQ(condition_values[0]->value,
-              *converted_condition_values[0].FindStringKey(apps::kValueKey));
+              *(*converted_condition_values)[0].GetDict().FindString(
+                  apps::kValueKey));
     EXPECT_EQ(static_cast<int>(condition_values[0]->match_type),
-              converted_condition_values[0].FindIntKey(apps::kMatchTypeKey));
+              (*converted_condition_values)[0].GetDict().FindInt(
+                  apps::kMatchTypeKey));
   }
 
   preferred_apps.Init();
diff --git a/components/strings/components_strings_fa.xtb b/components/strings/components_strings_fa.xtb
index 4b26948..e0562773 100644
--- a/components/strings/components_strings_fa.xtb
+++ b/components/strings/components_strings_fa.xtb
@@ -188,6 +188,7 @@
 <translation id="1384725838384960382">برگ اصالت‌سنجی اطلاعات کاربری پرداخت امن</translation>
 <translation id="1386623374109090026">حاشیه‌نویسی</translation>
 <translation id="1391289752476847787">سهام و اوراق قرضه</translation>
+<translation id="1391625539203220400">‏IBAN در این دستگاه ذخیره شود؟</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> داده‌ای ارسال نکرد.</translation>
 <translation id="1396259464226642517">این نتیجه غیرمنتظره بود؟ <ph name="BEGIN_LINK" />ارسال بازخورد<ph name="END_LINK" /></translation>
 <translation id="1405567553485452995">سبز روشن</translation>
diff --git a/components/strings/components_strings_mn.xtb b/components/strings/components_strings_mn.xtb
index 363c4e3..6e5b46ed 100644
--- a/components/strings/components_strings_mn.xtb
+++ b/components/strings/components_strings_mn.xtb
@@ -188,6 +188,7 @@
 <translation id="1384725838384960382">Аюулгүй төлбөрийн мандат үнэмлэхийг баталгаажуулах хүснэгт</translation>
 <translation id="1386623374109090026">Тэмдэглэгээ</translation>
 <translation id="1391289752476847787">Хувьцаа, бонд</translation>
+<translation id="1391625539203220400">Энэ төхөөрөмжид Олон улсын банк акаунтны дугаарыг хадгалах уу?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> ямар ч өгөгдөл илгээгээгүй.</translation>
 <translation id="1396259464226642517">Ийм үр дүнг тооцоолоогүй байсан уу? <ph name="BEGIN_LINK" />Санал хүсэлт илгээх<ph name="END_LINK" /></translation>
 <translation id="1405567553485452995">Цайвар ногоон</translation>
diff --git a/components/strings/components_strings_sk.xtb b/components/strings/components_strings_sk.xtb
index 1bb93ae..82440bdf 100644
--- a/components/strings/components_strings_sk.xtb
+++ b/components/strings/components_strings_sk.xtb
@@ -188,6 +188,7 @@
 <translation id="1384725838384960382">Hárok overenia poverenia zabezpečenej platby</translation>
 <translation id="1386623374109090026">Anotácie</translation>
 <translation id="1391289752476847787">Akcie a dlhopisy</translation>
+<translation id="1391625539203220400">Chcete uložiť číslo IBAN v tomto zariadení?</translation>
 <translation id="139305205187523129">Web <ph name="HOST_NAME" /> neodoslal žiadne údaje.</translation>
 <translation id="1396259464226642517">Bol tento výsledok neočakávaný? <ph name="BEGIN_LINK" />Odoslať spätnú väzbu<ph name="END_LINK" /></translation>
 <translation id="1405567553485452995">Svetlozelená</translation>
diff --git a/components/strings/components_strings_th.xtb b/components/strings/components_strings_th.xtb
index 4a40aa3..aee8908 100644
--- a/components/strings/components_strings_th.xtb
+++ b/components/strings/components_strings_th.xtb
@@ -1335,7 +1335,7 @@
 <translation id="4282346679996504092">ปิดการแจ้งเตือนสำหรับผลิตภัณฑ์นี้และนำบุ๊กมาร์กออกแล้ว</translation>
 <translation id="4285498937028063278">เลิกปักหมุด</translation>
 <translation id="428639260510061158">{NUM_CARDS,plural, =1{บันทึกบัตรนี้ลงในบัญชี Google ของคุณแล้ว}other{บันทึกบัตรเหล่านี้ลงในบัญชี Google ของคุณแล้ว}}</translation>
-<translation id="4287495839370498922">เพิ่มความเป็นส่วนตัวเกี่ยวกับโฆษณาใน Chrome</translation>
+<translation id="4287495839370498922">ความเป็นส่วนตัวเกี่ยวกับโฆษณาที่เพิ่มขึ้นบน Chrome</translation>
 <translation id="4287885627794386150">มีสิทธิ์สำหรับการทดลองใช้ แต่ใช้งานไม่ได้</translation>
 <translation id="4297502707443874121">ภาพขนาดย่อของหน้า <ph name="THUMBNAIL_PAGE" /></translation>
 <translation id="4298000214066716287">การลงทุน</translation>
diff --git a/components/user_manager/fake_user_manager.cc b/components/user_manager/fake_user_manager.cc
index 7e6ef2e..21de882 100644
--- a/components/user_manager/fake_user_manager.cc
+++ b/components/user_manager/fake_user_manager.cc
@@ -42,8 +42,7 @@
 
 namespace user_manager {
 
-FakeUserManager::FakeUserManager()
-    : UserManagerBase(new FakeTaskRunner()), primary_user_(nullptr) {}
+FakeUserManager::FakeUserManager() : UserManagerBase(new FakeTaskRunner()) {}
 
 FakeUserManager::~FakeUserManager() {
 }
@@ -254,10 +253,6 @@
   return nullptr;
 }
 
-const User* FakeUserManager::GetPrimaryUser() const {
-  return primary_user_;
-}
-
 std::u16string FakeUserManager::GetUserDisplayName(
     const AccountId& account_id) const {
   return std::u16string();
diff --git a/components/user_manager/fake_user_manager.h b/components/user_manager/fake_user_manager.h
index 07b2aa31..676c7f2 100644
--- a/components/user_manager/fake_user_manager.h
+++ b/components/user_manager/fake_user_manager.h
@@ -100,7 +100,6 @@
   bool IsKnownUser(const AccountId& account_id) const override;
   const User* FindUser(const AccountId& account_id) const override;
   User* FindUserAndModify(const AccountId& account_id) override;
-  const User* GetPrimaryUser() const override;
   void SaveUserOAuthStatus(const AccountId& account_id,
                            User::OAuthTokenStatus oauth_token_status) override {
   }
@@ -165,8 +164,6 @@
   void OnUserRemoved(const AccountId& account_id) override {}
 
  protected:
-  raw_ptr<User> primary_user_;
-
   // Can be set by set_local_state().
   raw_ptr<PrefService> local_state_ = nullptr;
 
diff --git a/content/browser/loader/navigation_early_hints_manager.cc b/content/browser/loader/navigation_early_hints_manager.cc
index 06ed0610..009e002b 100644
--- a/content/browser/loader/navigation_early_hints_manager.cc
+++ b/content/browser/loader/navigation_early_hints_manager.cc
@@ -82,6 +82,7 @@
 
 network::mojom::CSPDirectiveName LinkAsAttributeToCSPDirective(
     network::mojom::LinkAsAttribute attr) {
+  // https://w3c.github.io/webappsec-csp/#csp-directives
   switch (attr) {
     case network::mojom::LinkAsAttribute::kUnspecified:
       return network::mojom::CSPDirectiveName::Unknown;
@@ -93,6 +94,8 @@
       return network::mojom::CSPDirectiveName::ScriptSrcElem;
     case network::mojom::LinkAsAttribute::kStyleSheet:
       return network::mojom::CSPDirectiveName::StyleSrcElem;
+    case network::mojom::LinkAsAttribute::kFetch:
+      return network::mojom::CSPDirectiveName::ConnectSrc;
   }
   NOTREACHED();
   return network::mojom::CSPDirectiveName::Unknown;
@@ -131,8 +134,9 @@
   return true;
 }
 
-network::mojom::RequestDestination LinkAsAttributeToRequestDestination(
-    const network::mojom::LinkHeaderPtr& link) {
+absl::optional<network::mojom::RequestDestination>
+LinkAsAttributeToRequestDestination(const network::mojom::LinkHeaderPtr& link) {
+  // https://fetch.spec.whatwg.org/#concept-potential-destination-translate
   switch (link->as) {
     case network::mojom::LinkAsAttribute::kUnspecified:
       // For modulepreload, the request destination should be "script" when `as`
@@ -141,7 +145,7 @@
       if (link->rel == network::mojom::LinkRelAttribute::kModulePreload) {
         return network::mojom::RequestDestination::kScript;
       }
-      return network::mojom::RequestDestination::kEmpty;
+      return absl::nullopt;
     case network::mojom::LinkAsAttribute::kImage:
       return network::mojom::RequestDestination::kImage;
     case network::mojom::LinkAsAttribute::kFont:
@@ -150,6 +154,8 @@
       return network::mojom::RequestDestination::kScript;
     case network::mojom::LinkAsAttribute::kStyleSheet:
       return network::mojom::RequestDestination::kStyle;
+    case network::mojom::LinkAsAttribute::kFetch:
+      return network::mojom::RequestDestination::kEmpty;
   }
 }
 
@@ -166,6 +172,7 @@
     case network::mojom::LinkAsAttribute::kScript:
       return net::MEDIUM;
     case network::mojom::LinkAsAttribute::kImage:
+    case network::mojom::LinkAsAttribute::kFetch:
       return net::LOWEST;
     case network::mojom::LinkAsAttribute::kUnspecified:
       return net::IDLE;
@@ -513,12 +520,13 @@
   if (!ShouldHandleResourceHints(link))
     return;
 
-  network::mojom::RequestDestination destination =
-      LinkAsAttributeToRequestDestination(link);
   // Step 2. If options's destination is not a destination, then return null.
   // https://html.spec.whatwg.org/multipage/semantics.html#create-a-link-request
-  if (destination == network::mojom::RequestDestination::kEmpty)
+  absl::optional<network::mojom::RequestDestination> destination =
+      LinkAsAttributeToRequestDestination(link);
+  if (!destination) {
     return;
+  }
 
   if (!CheckContentSecurityPolicyForPreload(link, content_security_policies))
     return;
@@ -535,7 +543,7 @@
   network::ResourceRequest request;
   request.method = net::HttpRequestHeaders::kGetMethod;
   request.priority = CalculateRequestPriority(link);
-  request.destination = destination;
+  request.destination = *destination;
   request.url = link->href;
   request.site_for_cookies = site_for_cookies;
   request.request_initiator = origin_;
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc
index f4fce45..a193348f 100644
--- a/content/browser/preloading/prerender/prerender_browsertest.cc
+++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -6328,12 +6328,21 @@
     host_observer.WaitForDestroyed();
   }
 
-  ExpectFinalStatusForSpeculationRule(
 #if BUILDFLAG(IS_ANDROID)
+  ExpectFinalStatusForSpeculationRule(
       PrerenderFinalStatus::kRendererProcessKilled);
+  histogram_tester().ExpectUniqueSample(
+      "Prerender.Experimental.KilledPrerenderProcessTerminationStatus."
+      "SpeculationRule",
+      PrerenderProcessTerminationStatus::kOomProtected, 1);
 #else
+  ExpectFinalStatusForSpeculationRule(
       PrerenderFinalStatus::kRendererProcessCrashed);
-#endif  // BUILDFLAG(IS_ANDROID)
+  histogram_tester().ExpectTotalCount(
+      "Prerender.Experimental.KilledPrerenderProcessTerminationStatus."
+      "SpeculationRule",
+      0);
+#endif
 }
 
 // Test if the host is abandoned when the renderer page is killed.
@@ -6359,6 +6368,18 @@
 
   ExpectFinalStatusForSpeculationRule(
       PrerenderFinalStatus::kRendererProcessKilled);
+  PrerenderProcessTerminationStatus expected_termination_status =
+#if BUILDFLAG(IS_ANDROID)
+      PrerenderProcessTerminationStatus::kOomProtected;
+#elif BUILDFLAG(IS_WIN)
+      PrerenderProcessTerminationStatus::kNormalTermination;
+#else
+      PrerenderProcessTerminationStatus::kProcessWasKilled;
+#endif
+  histogram_tester().ExpectUniqueSample(
+      "Prerender.Experimental.KilledPrerenderProcessTerminationStatus."
+      "SpeculationRule",
+      expected_termination_status, 1);
 }
 
 // Test if the host is abandoned when the primary main page that triggers a
diff --git a/content/browser/preloading/prerender/prerender_metrics.cc b/content/browser/preloading/prerender/prerender_metrics.cc
index 40e93e1..84b8fa3e 100644
--- a/content/browser/preloading/prerender/prerender_metrics.cc
+++ b/content/browser/preloading/prerender/prerender_metrics.cc
@@ -7,8 +7,11 @@
 #include "base/containers/flat_map.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/metrics_hashes.h"
+#include "base/notreached.h"
+#include "base/process/kill.h"
 #include "base/strings/string_util.h"
 #include "content/browser/devtools/devtools_instrumentation.h"
+#include "content/browser/preloading/prerender/prerender_final_status.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/public/browser/prerender_trigger_type.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
@@ -28,6 +31,43 @@
   kMaxValue = kValueMismatch
 };
 
+PrerenderProcessTerminationStatus TranslateToPrerenderUmaTerminationStatus(
+    base::TerminationStatus status) {
+  switch (status) {
+    case base::TerminationStatus::TERMINATION_STATUS_NORMAL_TERMINATION:
+      return PrerenderProcessTerminationStatus::kNormalTermination;
+    case base::TerminationStatus::TERMINATION_STATUS_ABNORMAL_TERMINATION:
+      return PrerenderProcessTerminationStatus::kAbnormalTermination;
+    case base::TerminationStatus::TERMINATION_STATUS_PROCESS_WAS_KILLED:
+      return PrerenderProcessTerminationStatus::kProcessWasKilled;
+    case base::TerminationStatus::TERMINATION_STATUS_PROCESS_CRASHED:
+      return PrerenderProcessTerminationStatus::kProcessCrashed;
+    case base::TerminationStatus::TERMINATION_STATUS_STILL_RUNNING:
+      return PrerenderProcessTerminationStatus::kStillRunning;
+#if BUILDFLAG(IS_CHROMEOS)
+    case base::TerminationStatus::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
+      return PrerenderProcessTerminationStatus::kProcessWasKilledByOom;
+#endif  // BUILDFLAG(IS_CHROMEOS)
+#if BUILDFLAG(IS_ANDROID)
+    case base::TerminationStatus::TERMINATION_STATUS_OOM_PROTECTED:
+      return PrerenderProcessTerminationStatus::kOomProtected;
+#endif  // BUILDFLAG(IS_ANDROID)
+    case base::TerminationStatus::TERMINATION_STATUS_LAUNCH_FAILED:
+      return PrerenderProcessTerminationStatus::kLaunchFailed;
+    case base::TerminationStatus::TERMINATION_STATUS_OOM:
+      return PrerenderProcessTerminationStatus::kOom;
+#if BUILDFLAG(IS_WIN)
+    case base::TerminationStatus::TERMINATION_STATUS_INTEGRITY_FAILURE:
+      return PrerenderProcessTerminationStatus::kIntegrityFailure;
+#endif  //  BUILDFLAG(IS_WIN)
+    case base::TerminationStatus::TERMINATION_STATUS_MAX_ENUM:
+      NOTREACHED();
+      return PrerenderProcessTerminationStatus::kInvalid;
+  }
+  NOTREACHED();
+  return PrerenderProcessTerminationStatus::kInvalid;
+}
+
 PrerenderCancelledInterface GetCancelledInterfaceType(
     const std::string& interface_name) {
   if (interface_name == "device.mojom.GamepadHapticsManager")
@@ -103,6 +143,17 @@
   }
 }
 
+void RecordRendererProcessKilledTerminationStatus(
+    base::TerminationStatus status_code,
+    PrerenderTriggerType trigger_type,
+    const std::string& embedder_histogram_suffix) {
+  base::UmaHistogramEnumeration(
+      GenerateHistogramName(
+          "Prerender.Experimental.KilledPrerenderProcessTerminationStatus",
+          trigger_type, embedder_histogram_suffix),
+      TranslateToPrerenderUmaTerminationStatus(status_code));
+}
+
 void RecordPrerenderFinalStatusUma(
     PrerenderFinalStatus final_status,
     PrerenderTriggerType trigger_type,
@@ -132,6 +183,18 @@
                                      interface_name);
 }
 
+// static
+PrerenderCancellationReason
+PrerenderCancellationReason::BuildForRendererProcessGone(
+    base::TerminationStatus status_code) {
+  if (status_code == base::TERMINATION_STATUS_PROCESS_CRASHED) {
+    return PrerenderCancellationReason(
+        PrerenderFinalStatus::kRendererProcessCrashed);
+  }
+  return PrerenderCancellationReason(
+      PrerenderFinalStatus::kRendererProcessKilled, status_code);
+}
+
 PrerenderCancellationReason::PrerenderCancellationReason(
     PrerenderFinalStatus final_status)
     : PrerenderCancellationReason(final_status, DetailedReasonVariant()) {}
@@ -165,6 +228,12 @@
                                         trigger_type,
                                         embedder_histogram_suffix);
       break;
+    case PrerenderFinalStatus::kRendererProcessKilled:
+      DCHECK(absl::holds_alternative<base::TerminationStatus>(explanation_));
+      RecordRendererProcessKilledTerminationStatus(
+          absl::get<base::TerminationStatus>(explanation_), trigger_type,
+          embedder_histogram_suffix);
+      break;
     default:
       DCHECK(absl::holds_alternative<absl::monostate>(explanation_));
       // Other types need not to report.
@@ -180,6 +249,11 @@
       // And devtool has to handle it based on the enum.xml, as the content
       // layer cannot know about the enums added by the embedder layer.
       return "";
+    case PrerenderFinalStatus::kRendererProcessKilled:
+      DCHECK(absl::holds_alternative<base::TerminationStatus>(explanation_));
+      // We do not have a plan to send the detailed crash reason to devtools
+      // yet.
+      return "";
     case PrerenderFinalStatus::kMojoBinderPolicy:
       DCHECK(absl::holds_alternative<std::string>(explanation_));
       return absl::get<std::string>(explanation_);
diff --git a/content/browser/preloading/prerender/prerender_metrics.h b/content/browser/preloading/prerender/prerender_metrics.h
index b09b85c..722696b 100644
--- a/content/browser/preloading/prerender/prerender_metrics.h
+++ b/content/browser/preloading/prerender/prerender_metrics.h
@@ -47,13 +47,32 @@
   kMaxValue = kSchemeHostPortMismatch
 };
 
+// Use this enum instead of base::TerminationStatus so that all numbers can be
+// mapped to their dedicated labels, regardless of the platform.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class PrerenderProcessTerminationStatus {
+  kNormalTermination = 0,
+  kAbnormalTermination = 1,
+  kProcessWasKilled = 2,
+  kProcessCrashed = 3,
+  kStillRunning = 4,
+  kProcessWasKilledByOom = 5,
+  kOomProtected = 6,
+  kLaunchFailed = 7,
+  kOom = 8,
+  kIntegrityFailure = 9,
+  kInvalid = 10,
+  kMaxValue = kInvalid,
+};
+
 // Assembles PrerenderHostFinalStatus with a detailed explanation if applicable.
 // Some FinalStatus enums cover multiple sub cases. To explain them in detail,
 // some explanations can be attached to the status.
 class PrerenderCancellationReason {
  public:
-  using DetailedReasonVariant =
-      absl::variant<absl::monostate, uint64_t, std::string>;
+  using DetailedReasonVariant = absl::
+      variant<absl::monostate, uint64_t, base::TerminationStatus, std::string>;
 
   static PrerenderCancellationReason BuildForDisallowActivationState(
       uint64_t disallow_activation_reason);
@@ -61,6 +80,9 @@
   static PrerenderCancellationReason BuildForMojoBinderPolicy(
       const std::string& interface_name);
 
+  static PrerenderCancellationReason BuildForRendererProcessGone(
+      base::TerminationStatus status_code);
+
   explicit PrerenderCancellationReason(PrerenderFinalStatus final_status);
   ~PrerenderCancellationReason();
 
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 8f6481b..2d35ffb 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -3051,10 +3051,8 @@
                   kRendererProcessKilled);
   }
 
-  CancelPrerendering(PrerenderCancellationReason(
-      info.status == base::TERMINATION_STATUS_PROCESS_CRASHED
-          ? PrerenderFinalStatus::kRendererProcessCrashed
-          : PrerenderFinalStatus::kRendererProcessKilled));
+  CancelPrerendering(
+      PrerenderCancellationReason::BuildForRendererProcessGone(info.status));
 
   if (owned_render_widget_host_)
     owned_render_widget_host_->RendererExited();
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 65daab4..8ddedaa 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1277,18 +1277,13 @@
   DCHECK_NE(GetTextInputType(), ui::TEXT_INPUT_TYPE_NONE);
 
   if (text_input_manager_ && text_input_manager_->GetActiveWidget()) {
-    if (text.length() > 0 || !has_composition_text_) {
-      const int relative_cursor_position =
-          cursor_behavior == InsertTextCursorBehavior::kMoveCursorBeforeText
-              ? -text.length()
-              : 0;
-      text_input_manager_->GetActiveWidget()->ImeCommitText(
-          text, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(),
-          relative_cursor_position);
-    } else {
-      DCHECK(has_composition_text_);
-      text_input_manager_->GetActiveWidget()->ImeFinishComposingText(false);
-    }
+    const int relative_cursor_position =
+        cursor_behavior == InsertTextCursorBehavior::kMoveCursorBeforeText
+            ? -text.length()
+            : 0;
+    text_input_manager_->GetActiveWidget()->ImeCommitText(
+        text, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(),
+        relative_cursor_position);
   }
   has_composition_text_ = false;
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index c205889..4630598 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -6173,7 +6173,7 @@
 }
 
 // This test is for ui::TextInputClient::InsertText with empty text.
-TEST_F(InputMethodResultAuraTest, FinishComposingText) {
+TEST_F(InputMethodResultAuraTest, InsertEmptyText) {
   base::RepeatingClosure ime_call = base::BindRepeating(
       &ui::TextInputClient::InsertText, base::Unretained(text_input_client()),
       std::u16string(),
@@ -6183,7 +6183,7 @@
     SetHasCompositionTextToTrue();
     ime_call.Run();
     base::RunLoop().RunUntilIdle();
-    EXPECT_EQ("SetComposition FinishComposingText",
+    EXPECT_EQ("SetComposition CommitText",
               GetMessageNames(widget_hosts_[index]
                                   ->input_handler()
                                   ->GetAndResetDispatchedMessages()));
diff --git a/content/browser/screen_orientation/screen_orientation_browsertest.cc b/content/browser/screen_orientation/screen_orientation_browsertest.cc
index 5a297963..acd02f34 100644
--- a/content/browser/screen_orientation/screen_orientation_browsertest.cc
+++ b/content/browser/screen_orientation/screen_orientation_browsertest.cc
@@ -533,9 +533,7 @@
 
   // Shut down the prerendered page. It shouldn't trigger orientation unlock.
   test::PrerenderHostObserver prerender_observer(*web_contents(), host_id);
-  PrerenderHostRegistry* registry =
-      static_cast<WebContentsImpl*>(web_contents())->GetPrerenderHostRegistry();
-  registry->CancelHost(host_id, PrerenderFinalStatus::kRendererProcessKilled);
+  prerender_helper_.CancelPrerenderedPage(host_id);
   prerender_observer.WaitForDestroyed();
 
   // Delegate should not apply unlock.
diff --git a/ios/chrome/app/strings/resources/ios_strings_fa.xtb b/ios/chrome/app/strings/resources/ios_strings_fa.xtb
index 7bca88ab..d1fca71 100644
--- a/ios/chrome/app/strings/resources/ios_strings_fa.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_fa.xtb
@@ -18,6 +18,7 @@
 <translation id="1066060668811609597">مدیریت همگام‌سازی</translation>
 <translation id="1076421457278169141">کد اسکن شد</translation>
 <translation id="1076785341346483463">همگام‌سازی با حساب مدیریت‌شده</translation>
+<translation id="1080365971383768617">گذرواژه‌ها در همه دستگاه‌ها دردسترس است</translation>
 <translation id="1084365883616172403">‏پست Facebook ارسال شد.</translation>
 <translation id="1085696779717592361">‏استفاده از Chrome به‌طور پیش‌فرض</translation>
 <translation id="1103523840287552314"><ph name="LANGUAGE" /> همیشه ترجمه شود</translation>
@@ -545,6 +546,7 @@
 <translation id="5056446788882570708"><ph name="TIME" /> مشکلاتی پیدا شد.</translation>
 <translation id="5059136629401106827">خوب</translation>
 <translation id="5062321486222145940">‏نصب Google Drive</translation>
+<translation id="50641035439563602">‏ازاین‌پس گذرواژه‌ها در «حساب Google» شما (<ph name="ACCOUNT" />) ذخیره می‌شود. می‌توانید در هر جایی که به سیستم وارد شده‌اید از آن‌ها استفاده کنید. برای خاموش کردن این ویژگی، به <ph name="BEGIN_LINK" />تنظیمات<ph name="END_LINK" /> بروید.</translation>
 <translation id="5083464117946352670">تعیین اندازه فایل ممکن نیست.</translation>
 <translation id="5090832849094901128">حذف این گذرواژه باعث حذف شدن حساب شما در <ph name="WEBSITE" /> نمی‌شود.</translation>
 <translation id="5094827893301452931">‏Tweet انجام شد.</translation>
@@ -595,6 +597,7 @@
 <translation id="5520466080178053306">روی «مدیر گذرواژه» و سپس روی «افزودن» ضربه بزنید</translation>
 <translation id="5525095647255982834">‏برای ارسال این برگه به دستگاهی دیگر، در آنجا به سیستم Chrome وارد شوید.</translation>
 <translation id="5525269841082836315">ایجاد گذرعبارت</translation>
+<translation id="5530084793407600786">‏جستجو درون تصاویر با Google</translation>
 <translation id="5542540507657872337"><ph name="COUNT" /> برگه پیدا شد</translation>
 <translation id="5548760955356983418">‏با Handoff می‌توانید شروع به مرور وب‌سایت در این دستگاه کنید و سپس به‌آسانی در دستگاه Mac خود به مرور ادامه دهید. وب‌سایتی که اکنون باز است در Dock (لنگرگاه) شما در Mac نمایان می‌شود.
 
diff --git a/ios/chrome/app/strings/resources/ios_strings_mn.xtb b/ios/chrome/app/strings/resources/ios_strings_mn.xtb
index 957a18a..884eff6 100644
--- a/ios/chrome/app/strings/resources/ios_strings_mn.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_mn.xtb
@@ -18,6 +18,7 @@
 <translation id="1066060668811609597">Синкийг удирдах</translation>
 <translation id="1076421457278169141">Кодыг скан хийсэн</translation>
 <translation id="1076785341346483463">Тохиргоо хийгдсэн бүртгэлтэй синк хийх</translation>
+<translation id="1080365971383768617">Таны бүх төхөөрөмж дээрх нууц үгнүүд</translation>
 <translation id="1084365883616172403">Facebook дээр постолж дууслаа.</translation>
 <translation id="1085696779717592361">Chrome-г өгөгдмөлөөр ашиглах</translation>
 <translation id="1103523840287552314"><ph name="LANGUAGE" />-ийг үргэлж орчуулах</translation>
@@ -544,6 +545,7 @@
 <translation id="5056446788882570708">Асуудлыг <ph name="TIME" />-д олсон</translation>
 <translation id="5059136629401106827">OK</translation>
 <translation id="5062321486222145940">Google Drive суулгах</translation>
+<translation id="50641035439563602">Нууц үгнүүдийг одоо таны Google Бүртгэлд (<ph name="ACCOUNT" />) хадгаллаа. Та тэдгээрийг нэвтэрсэн дурын газраасаа ашиглах боломжтой. Үүнийг унтраахын тулд <ph name="BEGIN_LINK" />тохиргоо<ph name="END_LINK" /> руу очно уу.</translation>
 <translation id="5083464117946352670">Файлын хэмжээг тодорхойлж чадахгүй байна.</translation>
 <translation id="5090832849094901128">Энэ нууц үгийг устгаснаар таны <ph name="WEBSITE" /> дээрх бүртгэлийг устгахгүй.</translation>
 <translation id="5094827893301452931">Жиргэж дууссан.</translation>
@@ -594,6 +596,7 @@
 <translation id="5520466080178053306">Нууц үгний менежер дээр товшоод нэмэх дээр товшино уу</translation>
 <translation id="5525095647255982834">Энэ табыг өөр төхөөрөмж рүү илгээхийн тулд тэндээс Chrome-д нэвтэрнэ үү.</translation>
 <translation id="5525269841082836315">Нэвтрэх үгийг үүсгэх</translation>
+<translation id="5530084793407600786">Google-р зургаас хайх</translation>
 <translation id="5542540507657872337"><ph name="COUNT" /> олдсон</translation>
 <translation id="5548760955356983418">Handoff нь танд энэ төхөөрөмж дээр веб хуудсыг ачаалж, дараа нь Mac дээр хялбархан үргэжлүүлэн ажиллах боломжийг олгодог. Одоо нээлттэй байгаа вебсайт таны Mac-ийн Dock дотор гарч ирнэ.
 
diff --git a/ios/chrome/app/strings/resources/ios_strings_sk.xtb b/ios/chrome/app/strings/resources/ios_strings_sk.xtb
index 18335ac..d795ff7 100644
--- a/ios/chrome/app/strings/resources/ios_strings_sk.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_sk.xtb
@@ -18,6 +18,7 @@
 <translation id="1066060668811609597">Správa synchronizácie</translation>
 <translation id="1076421457278169141">Kód bol naskenovaný</translation>
 <translation id="1076785341346483463">Synchronizácia so spravovaným účtom</translation>
+<translation id="1080365971383768617">Heslá vo všetkých vašich zariadeniach</translation>
 <translation id="1084365883616172403">Príspevok bol uverejnený na Facebook.</translation>
 <translation id="1085696779717592361">Predvolené používanie Chromu</translation>
 <translation id="1103523840287552314">Vždy preložiť nasledujúci jazyk: <ph name="LANGUAGE" /></translation>
@@ -545,6 +546,7 @@
 <translation id="5056446788882570708">Problémy boli nájdené o <ph name="TIME" />.</translation>
 <translation id="5059136629401106827">OK</translation>
 <translation id="5062321486222145940">Nainštalovať Disk Google</translation>
+<translation id="50641035439563602">Heslá sa teraz ukladajú do vášho účtu Google (<ph name="ACCOUNT" />). Môžete ich používať všade, kde sa prihlásite. Vypnúť ich môžete v <ph name="BEGIN_LINK" />nastaveniach<ph name="END_LINK" />.</translation>
 <translation id="5083464117946352670">Nedá sa zistiť veľkosť súboru.</translation>
 <translation id="5090832849094901128">Odstránením tohto hesla nevymažete svoj účet na <ph name="WEBSITE" />.</translation>
 <translation id="5094827893301452931">Tweet bol uverejnený.</translation>
@@ -595,6 +597,7 @@
 <translation id="5520466080178053306">Klepnite na Správcu hesiel a potom na Pridať</translation>
 <translation id="5525095647255982834">Ak chcete túto kartu odoslať do iného zariadenia, prihláste sa v ňom do Chromu.</translation>
 <translation id="5525269841082836315">Vytv. prístup. frázu</translation>
+<translation id="5530084793407600786">Hľadať na obrázku Googlom</translation>
 <translation id="5542540507657872337">Nájdené karty: <ph name="COUNT" /></translation>
 <translation id="5548760955356983418">Funkcia Handoff umožňuje začať prehliadanie webových stránok na tomto zariadení a potom jednoducho pokračovať na počítači Mac. Aktuálne otvorené stránky sa zobrazia v doku na počítači Mac.
 
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 c2823eef..3bd57aef 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 @@
-f8c2e5c7c8b99c169d409299775c4d9dc44b6443
\ No newline at end of file
+aaa617af2315b22a11ec7b5159225b7f14a66f0f
\ 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 b91262f..a4ec38dc 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 @@
-36e6a9d02dcfb60d5a8780393e60ac0307770d6d
\ No newline at end of file
+d686f9789f916117ea8260147305816099dc179d
\ 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 bbca6566..5cb8c00 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 @@
-0d84f5ce882c7887cd377ad13b7e0e4c5ded1c25
\ No newline at end of file
+507fc52fed5af89dd8420a9f95c7231ffff873b5
\ 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 ddbda167..29783da 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 @@
-b85a84176a7fb69cbd682e01718d416c19450544
\ No newline at end of file
+77ae8aa36c7ef47ed238a7de580069eb70da14e2
\ 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 9eb718a..cb79a2d 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 @@
-8c6a663e80d3abfa1b928fe1cd3b79f881966a33
\ No newline at end of file
+ca29b5f1fad1e839c576563a4b5f452731fd55f2
\ 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 82bfede..ea95448 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 @@
-8bf0f38c0b11604063335df942fbc59ef7493661
\ No newline at end of file
+a107e498fe69969c35eddb5709866fd3a22eaa0e
\ 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 8c7185f..7a3091c 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 @@
-7c45c9f0024e50a542153b1e604a937c1b7a730c
\ No newline at end of file
+ae8261e31c286e9a590a7cdf2b6313467bd93eff
\ 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 42352383..036b934 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 @@
-323207c40aa48acc64e34afaed36c4ea6d4b04f2
\ No newline at end of file
+f9b11ace8a8cef1033dc240658ef61131ac46056
\ 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 fb1734a3..7fc628d2 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 @@
-d22b78adb1f74fba42cb260e7b017c2a2234a4fd
\ No newline at end of file
+2ec45101e881357c6c80ffd79b78d1793adac7e7
\ 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 ade8bf3..a810dcf2 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 @@
-cc030df41cd6a6b5fcd2eadfa36def0858343d89
\ No newline at end of file
+2dfb4a3792d08e09aaec815bbd6d95b06570d08b
\ 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 755655b..252818895 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 @@
-e49e2527ac1920903fe1e3e01d89a017275eec42
\ No newline at end of file
+0257b25830500946a5135486adc73e2d5dc744fc
\ 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 572f173..02b18d1 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 @@
-56ae1eb98a308a85bfbf0339f31b9fdae9f9ff89
\ No newline at end of file
+0729d392259fd40afd4565841016ba863917267f
\ No newline at end of file
diff --git a/media/base/decoder_status.cc b/media/base/decoder_status.cc
index 09ef67b..84a25ed 100644
--- a/media/base/decoder_status.cc
+++ b/media/base/decoder_status.cc
@@ -47,13 +47,6 @@
 
 }  // namespace
 
-// static
-bool ScopedDecodeTrace::IsEnabled() {
-  bool enable_decode_traces = false;
-  TRACE_EVENT_CATEGORY_GROUP_ENABLED("media", &enable_decode_traces);
-  return enable_decode_traces;
-}
-
 ScopedDecodeTrace::ScopedDecodeTrace(const char* trace_name,
                                      bool is_key_frame,
                                      base::TimeDelta timestamp)
diff --git a/media/base/decoder_status.h b/media/base/decoder_status.h
index 354ff87..3dd0b6e 100644
--- a/media/base/decoder_status.h
+++ b/media/base/decoder_status.h
@@ -53,10 +53,6 @@
 // owns the class it's guaranteed to be unique.
 class MEDIA_EXPORT ScopedDecodeTrace {
  public:
-  // Returns true if tracing is enabled for the media category. If false,
-  // clients should avoid creating ScopedDecodeTrace objects.
-  static bool IsEnabled();
-
   // Begins an asynchronous trace with the given name and properties. Providing
   // the DecoderBuffer itself yields the most information in the trace.
   ScopedDecodeTrace(const char* trace_name, const DecoderBuffer& buffer);
diff --git a/media/base/media_util.cc b/media/base/media_util.cc
index 27451d9..fe4b198 100644
--- a/media/base/media_util.cc
+++ b/media/base/media_util.cc
@@ -4,6 +4,8 @@
 
 #include "media/base/media_util.h"
 
+#include "base/trace_event/trace_event.h"
+
 namespace media {
 
 std::vector<uint8_t> EmptyExtraData() {
@@ -28,4 +30,9 @@
   }
 }
 
+bool MediaTraceIsEnabled() {
+  bool enable_decode_traces = false;
+  TRACE_EVENT_CATEGORY_GROUP_ENABLED("media", &enable_decode_traces);
+  return enable_decode_traces;
+}
 }  // namespace media
diff --git a/media/base/media_util.h b/media/base/media_util.h
index 9481757..f3168b9 100644
--- a/media/base/media_util.h
+++ b/media/base/media_util.h
@@ -36,6 +36,8 @@
 MEDIA_EXPORT AudioParameters::Format ConvertAudioCodecToBitstreamFormat(
     media::AudioCodec codec);
 
+// Returns true if tracing is enabled for the media category.
+MEDIA_EXPORT bool MediaTraceIsEnabled();
 }  // namespace media
 
 #endif  // MEDIA_BASE_MEDIA_UTIL_H_
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc
index 215a17c0..d33aba7 100644
--- a/media/filters/decoder_stream.cc
+++ b/media/filters/decoder_stream.cc
@@ -19,6 +19,7 @@
 #include "media/base/limits.h"
 #include "media/base/media_log.h"
 #include "media/base/media_switches.h"
+#include "media/base/media_util.h"
 #include "media/base/timestamp_constants.h"
 #include "media/base/video_decoder.h"
 #include "media/base/video_frame.h"
@@ -512,7 +513,7 @@
   DCHECK(buffer);
 
   std::unique_ptr<ScopedDecodeTrace> trace_event;
-  if (ScopedDecodeTrace::IsEnabled()) {
+  if (MediaTraceIsEnabled()) {
     // Because multiple Decode() calls may be in flight, each call needs a
     // unique trace event class to identify it. This scoped event is bound
     // into the OnDecodeDone callback to ensure the trace is always closed.
diff --git a/media/mojo/services/mojo_video_decoder_service.cc b/media/mojo/services/mojo_video_decoder_service.cc
index bc22e0ba..85e2212 100644
--- a/media/mojo/services/mojo_video_decoder_service.cc
+++ b/media/mojo/services/mojo_video_decoder_service.cc
@@ -15,6 +15,7 @@
 #include "base/task/single_thread_task_runner.h"
 #include "base/types/optional_util.h"
 #include "media/base/decoder_buffer.h"
+#include "media/base/media_util.h"
 #include "media/base/simple_sync_token_client.h"
 #include "media/base/video_decoder.h"
 #include "media/base/video_decoder_config.h"
@@ -282,7 +283,7 @@
   DCHECK(callback);
 
   std::unique_ptr<ScopedDecodeTrace> trace_event;
-  if (ScopedDecodeTrace::IsEnabled()) {
+  if (MediaTraceIsEnabled()) {
     // Because multiple Decode() calls may be in flight, each call needs a
     // unique trace event class to identify it. This scoped event is bound
     // into the OnDecodeDone callback to ensure the trace is always closed.
diff --git a/media/mojo/services/mojo_video_encode_accelerator_service.cc b/media/mojo/services/mojo_video_encode_accelerator_service.cc
index 94517737..da268819 100644
--- a/media/mojo/services/mojo_video_encode_accelerator_service.cc
+++ b/media/mojo/services/mojo_video_encode_accelerator_service.cc
@@ -9,9 +9,11 @@
 
 #include "base/logging.h"
 #include "base/task/single_thread_task_runner.h"
+#include "base/trace_event/trace_event.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/bitstream_buffer.h"
 #include "media/base/limits.h"
+#include "media/base/media_util.h"
 #include "media/mojo/mojom/video_encoder_info.mojom.h"
 #include "media/mojo/services/mojo_media_log.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
@@ -42,7 +44,8 @@
       gpu_preferences_(gpu_preferences),
       gpu_workarounds_(gpu_workarounds),
       gpu_device_(gpu_device),
-      output_buffer_size_(0) {
+      output_buffer_size_(0),
+      timestamps_(128) {
   DVLOG(1) << __func__;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
@@ -63,6 +66,8 @@
          config.input_format == PIXEL_FORMAT_NV12)
       << "Only I420 or NV12 format supported, got "
       << VideoPixelFormatToString(config.input_format);
+  TRACE_EVENT1("media", "MojoVideoEncodeAcceleratorService::Initialize",
+               "config", config.AsHumanReadableString());
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       base::SingleThreadTaskRunner::GetCurrentDefault();
@@ -140,6 +145,9 @@
     EncodeCallback callback) {
   DVLOG(2) << __func__ << " tstamp=" << frame->timestamp();
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  TRACE_EVENT2("media", "MojoVideoEncodeAcceleratorService::Encode",
+               "timestamp", frame->timestamp().InMilliseconds(), "keyframe",
+               force_keyframe);
   if (!encoder_) {
     DLOG(ERROR) << __func__ << " Failed to encode, the encoder is invalid";
     std::move(callback).Run();
@@ -156,6 +164,11 @@
     return;
   }
 
+  if (MediaTraceIsEnabled()) {
+    timestamps_.Put(frame->timestamp().InMilliseconds(),
+                    base::TimeTicks::Now());
+  }
+
   frame->AddDestructionObserver(media::BindToCurrentLoop(std::move(callback)));
   encoder_->Encode(frame, force_keyframe);
 }
@@ -165,7 +178,9 @@
     base::UnsafeSharedMemoryRegion region) {
   DVLOG(2) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
+  TRACE_EVENT1("media",
+               "MojoVideoEncodeAcceleratorService::UseOutputBitstreamBuffer",
+               "id", bitstream_buffer_id);
   if (!encoder_)
     return;
   if (!region.IsValid()) {
@@ -198,6 +213,11 @@
         const media::VideoBitrateAllocation& bitrate_allocation,
         uint32_t framerate) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  TRACE_EVENT2("media",
+               "MojoVideoEncodeAcceleratorService::"
+               "RequestEncodingParametersChangeWithLayers",
+               "bitrate_allocation", bitrate_allocation.ToString(), "framerate",
+               framerate);
 
   if (!encoder_)
     return;
@@ -212,7 +232,10 @@
     RequestEncodingParametersChangeWithBitrate(const media::Bitrate& bitrate,
                                                uint32_t framerate) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
+  TRACE_EVENT2("media",
+               "MojoVideoEncodeAcceleratorService::"
+               "RequestEncodingParametersChangeWithBitrate",
+               "bitrate", bitrate.ToString(), "framerate", framerate);
   if (!encoder_)
     return;
 
@@ -259,6 +282,11 @@
            << " input_coded_size=" << input_coded_size.ToString()
            << " output_buffer_size=" << output_buffer_size;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  TRACE_EVENT2("media",
+               "MojoVideoEncodeAcceleratorService::RequireBitstreamBuffers",
+               "input_coded_size", input_coded_size.ToString(),
+               "output_buffer_size", output_buffer_size);
+
   if (!vea_client_)
     return;
 
@@ -276,6 +304,26 @@
            << ", payload_size=" << metadata.payload_size_bytes
            << "B,  key_frame=" << metadata.key_frame;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  TRACE_EVENT1("media",
+               "MojoVideoEncodeAcceleratorService::BitstreamBufferReady",
+               "bitstream_buffer_id", bitstream_buffer_id);
+  if (MediaTraceIsEnabled() &&
+      ((!metadata.vp9 && !metadata.av1) ||
+       (metadata.vp9 && metadata.vp9->end_of_picture) ||
+       (metadata.av1 && metadata.av1->end_of_picture))) {
+    const auto timestamp_it =
+        timestamps_.Peek(metadata.timestamp.InMilliseconds());
+    if (timestamp_it != timestamps_.end()) {
+      const int64_t timestamp = metadata.timestamp.InMilliseconds();
+      TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+          "media", "MojoVEAServicee::EncodingFrameDuration",
+          TRACE_ID_LOCAL(this), timestamp_it->second);
+      TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP1(
+          "media", "MojoVEAServicee::EncodingFrameDuration",
+          TRACE_ID_LOCAL(this), base::TimeTicks::Now(), "timestamp", timestamp);
+    }
+  }
+
   if (!vea_client_)
     return;
 
diff --git a/media/mojo/services/mojo_video_encode_accelerator_service.h b/media/mojo/services/mojo_video_encode_accelerator_service.h
index 05cf433..6066bd76 100644
--- a/media/mojo/services/mojo_video_encode_accelerator_service.h
+++ b/media/mojo/services/mojo_video_encode_accelerator_service.h
@@ -12,10 +12,12 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
+#include "base/containers/lru_cache.h"
 #include "base/memory/raw_ref.h"
 #include "base/memory/unsafe_shared_memory_region.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
+#include "base/time/time.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_info.h"
 #include "media/mojo/mojom/video_encode_accelerator.mojom.h"
@@ -119,6 +121,8 @@
   size_t output_buffer_size_;
   gfx::Size input_coded_size_;
 
+  base::LRUCache<int64_t, base::TimeTicks> timestamps_;
+
   // Note that this class is already thread hostile when bound.
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins
index 1464242..0f546fd7 100644
--- a/net/http/transport_security_state_static.pins
+++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@
 #   hash function for preloaded entries again (we have already done so once).
 #
 
-# Last updated: 2023-01-28 12:54 UTC
+# Last updated: 2023-01-29 12:55 UTC
 PinsListTimestamp
-1674910457
+1674996943
 
 TestSPKI
 sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/services/network/public/cpp/link_header_parser.cc b/services/network/public/cpp/link_header_parser.cc
index 8f32194..bfc38060 100644
--- a/services/network/public/cpp/link_header_parser.cc
+++ b/services/network/public/cpp/link_header_parser.cc
@@ -62,6 +62,8 @@
     return mojom::LinkAsAttribute::kScript;
   } else if (value == "style") {
     return mojom::LinkAsAttribute::kStyleSheet;
+  } else if (value == "fetch") {
+    return mojom::LinkAsAttribute::kFetch;
   }
   return absl::nullopt;
 }
diff --git a/services/network/public/cpp/link_header_parser_unittest.cc b/services/network/public/cpp/link_header_parser_unittest.cc
index 244723a..c31f1966 100644
--- a/services/network/public/cpp/link_header_parser_unittest.cc
+++ b/services/network/public/cpp/link_header_parser_unittest.cc
@@ -135,15 +135,17 @@
   headers->AddHeader("link", "</image.jpg>; rel=preload; as=image");
   headers->AddHeader("link", "</script.js>; rel=preload; as=script");
   headers->AddHeader("link", "</style.css>; rel=preload; as=style");
+  headers->AddHeader("link", "</foo.json>; rel=preload; as=fetch; crossorigin");
 
   std::vector<mojom::LinkHeaderPtr> parsed_headers =
       ParseLinkHeaders(*headers, kBaseUrl);
-  ASSERT_EQ(parsed_headers.size(), 5UL);
+  ASSERT_EQ(parsed_headers.size(), 6UL);
   EXPECT_EQ(parsed_headers[0]->as, mojom::LinkAsAttribute::kUnspecified);
   EXPECT_EQ(parsed_headers[1]->as, mojom::LinkAsAttribute::kFont);
   EXPECT_EQ(parsed_headers[2]->as, mojom::LinkAsAttribute::kImage);
   EXPECT_EQ(parsed_headers[3]->as, mojom::LinkAsAttribute::kScript);
   EXPECT_EQ(parsed_headers[4]->as, mojom::LinkAsAttribute::kStyleSheet);
+  EXPECT_EQ(parsed_headers[5]->as, mojom::LinkAsAttribute::kFetch);
 }
 
 TEST(LinkHeaderParserTest, CrossOriginAttribute) {
diff --git a/services/network/public/mojom/link_header.mojom b/services/network/public/mojom/link_header.mojom
index f0e3e08..a883263 100644
--- a/services/network/public/mojom/link_header.mojom
+++ b/services/network/public/mojom/link_header.mojom
@@ -19,12 +19,15 @@
 };
 
 // Represents subset of possible values for `as` attribute of the Link header.
+// https://fetch.spec.whatwg.org/#concept-potential-destination
+// https://fetch.spec.whatwg.org/#concept-request-destination
 enum LinkAsAttribute {
   kUnspecified,
   kFont,
   kImage,
   kScript,
   kStyleSheet,
+  kFetch,
 };
 
 // Represents subset of possible values for `crossorigin` attribute.
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index dd93dd05..732bb3c7 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1833,7 +1833,7 @@
       {
         "args": [],
         "cros_board": "dedede",
-        "cros_img": "dedede-release/R112-15331.0.0",
+        "cros_img": "dedede-release/R112-15332.0.0",
         "name": "lacros_all_tast_tests DEDEDE_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1897,7 +1897,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R112-15331.0.0",
+        "cros_img": "eve-release/R112-15332.0.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -2040,7 +2040,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R112-15331.0.0",
+        "cros_img": "jacuzzi-release/R112-15332.0.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -2145,7 +2145,7 @@
       {
         "args": [],
         "cros_board": "herobrine",
-        "cros_img": "herobrine-release/R112-15331.0.0",
+        "cros_img": "herobrine-release/R112-15332.0.0",
         "name": "lacros_fyi_tast_tests HEROBRINE_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index b874a812..c7c30a194 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1148,7 +1148,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R112-15331.0.0",
+        "cros_img": "octopus-release/R112-15332.0.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1196,7 +1196,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R112-15331.0.0",
+        "cros_img": "octopus-release/R112-15332.0.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1247,7 +1247,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R112-15331.0.0",
+        "cros_img": "hana-release/R112-15332.0.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1295,7 +1295,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R112-15331.0.0",
+        "cros_img": "strongbad-release/R112-15332.0.0",
         "name": "lacros_all_tast_tests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1343,7 +1343,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R112-15331.0.0",
+        "cros_img": "hana-release/R112-15332.0.0",
         "name": "ozone_unittests HANA_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1387,7 +1387,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R112-15331.0.0",
+        "cros_img": "strongbad-release/R112-15332.0.0",
         "name": "ozone_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1431,7 +1431,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R112-15331.0.0",
+        "cros_img": "hana-release/R112-15332.0.0",
         "name": "viz_unittests HANA_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -1475,7 +1475,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R112-15331.0.0",
+        "cros_img": "strongbad-release/R112-15332.0.0",
         "name": "viz_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 7ef3a63..d802db2 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -471,7 +471,7 @@
     'skylab': {
       'cros_board': 'dedede',
       'cros_chrome_version': '111.0.5562.0',
-      'cros_img': 'dedede-release/R112-15331.0.0',
+      'cros_img': 'dedede-release/R112-15332.0.0',
     },
     'enabled': True,
     'identifier': 'DEDEDE_RELEASE_LKGM',
@@ -507,7 +507,7 @@
     'skylab': {
       'cros_board': 'eve',
       'cros_chrome_version': '111.0.5562.0',
-      'cros_img': 'eve-release/R112-15331.0.0',
+      'cros_img': 'eve-release/R112-15332.0.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_LKGM',
@@ -553,7 +553,7 @@
     'skylab': {
       'cros_board': 'hana',
       'cros_chrome_version': '111.0.5562.0',
-      'cros_img': 'hana-release/R112-15331.0.0',
+      'cros_img': 'hana-release/R112-15332.0.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_LKGM',
@@ -589,7 +589,7 @@
     'skylab': {
       'cros_board': 'herobrine',
       'cros_chrome_version': '111.0.5562.0',
-      'cros_img': 'herobrine-release/R112-15331.0.0',
+      'cros_img': 'herobrine-release/R112-15332.0.0',
     },
     'enabled': True,
     'identifier': 'HEROBRINE_RELEASE_LKGM',
@@ -598,7 +598,7 @@
     'skylab': {
       'cros_board': 'jacuzzi',
       'cros_chrome_version': '111.0.5562.0',
-      'cros_img': 'jacuzzi-release/R112-15331.0.0',
+      'cros_img': 'jacuzzi-release/R112-15332.0.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_LKGM',
@@ -674,7 +674,7 @@
     'skylab': {
       'cros_board': 'octopus',
       'cros_chrome_version': '111.0.5562.0',
-      'cros_img': 'octopus-release/R112-15331.0.0',
+      'cros_img': 'octopus-release/R112-15332.0.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_LKGM',
@@ -710,7 +710,7 @@
     'skylab': {
       'cros_board': 'strongbad',
       'cros_chrome_version': '111.0.5562.0',
-      'cros_img': 'strongbad-release/R112-15331.0.0',
+      'cros_img': 'strongbad-release/R112-15332.0.0',
     },
     'enabled': True,
     'identifier': 'STRONGBAD_RELEASE_LKGM',
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 1cc64db..4aa96dd 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -113,6 +113,12 @@
              "BackForwardCacheWithKeepaliveRequest",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
+// Enable background resource fetch in Blink. See https://crbug.com/1379780 for
+// more details.
+BASE_FEATURE(kBackgroundResourceFetch,
+             "BackgroundResourceFetch",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // Enable intervention for download that was initiated from or occurred in an ad
 // frame without user activation.
 BASE_FEATURE(kBlockingDownloadsInAdFrameWithoutUserActivation,
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 4505ffb..0bed657 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -41,8 +41,8 @@
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheDedicatedWorker);
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(
     kBackForwardCacheNotReachedOnJavaScriptExecution);
-
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheWithKeepaliveRequest);
+BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBackgroundResourceFetch);
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(
     kBlockingDownloadsInAdFrameWithoutUserActivation);
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kConversionMeasurement);
diff --git a/third_party/blink/public/web/web_element.h b/third_party/blink/public/web/web_element.h
index 91e4d36..a23dd0a 100644
--- a/third_party/blink/public/web/web_element.h
+++ b/third_party/blink/public/web/web_element.h
@@ -81,9 +81,6 @@
   void SetAttribute(const WebString& name, const WebString& value);
   WebString TextContent() const;
   WebString InnerHTML() const;
-  WebString AttributeLocalName(unsigned index) const;
-  WebString AttributeValue(unsigned index) const;
-  unsigned AttributeCount() const;
 
   // Returns all <label> elements associated to this element.
   WebVector<WebLabelElement> Labels() const;
diff --git a/third_party/blink/renderer/core/css/fullscreen.css b/third_party/blink/renderer/core/css/fullscreen.css
index c86e0e0..18cc6ac 100644
--- a/third_party/blink/renderer/core/css/fullscreen.css
+++ b/third_party/blink/renderer/core/css/fullscreen.css
@@ -16,6 +16,10 @@
     user-select: text;
 }
 
+:fullscreen {
+    top-layer: browser !important;
+}
+
 iframe:fullscreen {
     border: none !important;
     padding: 0 !important;
@@ -27,6 +31,7 @@
     position: fixed;
     inset: 0;
     background: black;
+    top-layer: browser !important;
 }
 
 /* Anything below are extensions over what the Fullscreen API (29 May 2018) mandates. */
diff --git a/third_party/blink/renderer/core/css/popover.css b/third_party/blink/renderer/core/css/popover.css
index ac44f5d5..436d79f 100644
--- a/third_party/blink/renderer/core/css/popover.css
+++ b/third_party/blink/renderer/core/css/popover.css
@@ -34,6 +34,10 @@
   anchor-scroll: implicit;
 }
 
+[popover]:open:not(dialog), dialog:open:not([open]) {
+  top-layer: browser !important;
+}
+
 [popover]:open::backdrop {
   /* From the (modified) fullscreen spec: https://fullscreen.spec.whatwg.org/#user-agent-level-style-sheet-defaults: */
   position: fixed;
@@ -42,4 +46,5 @@
   pointer-events: none !important;
   /* https://github.com/openui/open-ui/issues/561#issuecomment-1242297093 */
   background-color: transparent;
+  top-layer: browser !important;
 }
diff --git a/third_party/blink/renderer/core/css/resolver/match_result.h b/third_party/blink/renderer/core/css/resolver/match_result.h
index fe74386e..6ee1222 100644
--- a/third_party/blink/renderer/core/css/resolver/match_result.h
+++ b/third_party/blink/renderer/core/css/resolver/match_result.h
@@ -26,6 +26,7 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/cascade_layer_map.h"
 #include "third_party/blink/renderer/core/css/css_selector.h"
 #include "third_party/blink/renderer/core/css/resolver/cascade_origin.h"
 #include "third_party/blink/renderer/core/css/resolver/match_flags.h"
@@ -92,7 +93,7 @@
  private:
   unsigned link_match_type_ = CSSSelector::kMatchAll;
   ValidPropertyFilter valid_property_filter_ = ValidPropertyFilter::kNoFilter;
-  unsigned layer_order_ = 0;
+  unsigned layer_order_ = CascadeLayerMap::kImplicitOuterLayerOrder;
   bool is_inline_style_ = false;
 
   friend class Builder;
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 3e0dc0e..aa8cbe32 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/core/animation/document_animations.h"
 #include "third_party/blink/renderer/core/animation/element_animations.h"
 #include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h"
+#include "third_party/blink/renderer/core/css/cascade_layer_map.h"
 #include "third_party/blink/renderer/core/css/container_query_evaluator.h"
 #include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
 #include "third_party/blink/renderer/core/css/css_default_style_sheets.h"
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
index 3a43aef9..08c5035 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
 
 #include <algorithm>
+#include "base/debug/dump_without_crashing.h"
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
 #include "third_party/blink/renderer/core/dom/node.h"
 #include "third_party/blink/renderer/core/dom/node_traversal.h"
@@ -640,7 +641,7 @@
 
   if (start > end) {
     // TODO(crbug/1114021): Investigate why this might happen.
-    NOTREACHED() << "|start| should be before |end|.";
+    base::debug::DumpWithoutCrashing();
     return node_marker_pairs;
   }
 
diff --git a/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h b/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h
index 30a790d..24cbfbb 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h
+++ b/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h
@@ -92,7 +92,7 @@
     int previous_checked_length = 0;
     int accumulated_delta = 0;
   };
-  HeapHashMap<Member<const Element>, FullyCheckedEditableEntry>
+  HeapHashMap<WeakMember<const Element>, FullyCheckedEditableEntry>
       fully_checked_root_editables_;
 
   // A test-only flag for forcing lifecycle advancing.
diff --git a/third_party/blink/renderer/core/exported/web_element.cc b/third_party/blink/renderer/core/exported/web_element.cc
index ae418a4c1..31c5027 100644
--- a/third_party/blink/renderer/core/exported/web_element.cc
+++ b/third_party/blink/renderer/core/exported/web_element.cc
@@ -106,24 +106,6 @@
                                   IGNORE_EXCEPTION_FOR_TESTING);
 }
 
-unsigned WebElement::AttributeCount() const {
-  if (!ConstUnwrap<Element>()->hasAttributes())
-    return 0;
-  return ConstUnwrap<Element>()->Attributes().size();
-}
-
-WebString WebElement::AttributeLocalName(unsigned index) const {
-  if (index >= AttributeCount())
-    return WebString();
-  return ConstUnwrap<Element>()->Attributes().at(index).LocalName();
-}
-
-WebString WebElement::AttributeValue(unsigned index) const {
-  if (index >= AttributeCount())
-    return WebString();
-  return ConstUnwrap<Element>()->Attributes().at(index).Value();
-}
-
 WebString WebElement::TextContent() const {
   return ConstUnwrap<Element>()->textContent();
 }
diff --git a/third_party/blink/renderer/core/html/resources/html.css b/third_party/blink/renderer/core/html/resources/html.css
index 1a91805..a2102e7 100644
--- a/third_party/blink/renderer/core/html/resources/html.css
+++ b/third_party/blink/renderer/core/html/resources/html.css
@@ -1407,6 +1407,7 @@
     /* https://github.com/w3c/csswg-drafts/issues/6939#issuecomment-1016679588 */
     user-select: text;
     visibility: visible;
+    top-layer: browser !important;
 }
 
 /* TODO(foolip): In the Fullscreen spec, there's a ::backdrop block with the
@@ -1415,7 +1416,8 @@
     position: fixed;
     inset: 0;
     /* https://html.spec.whatwg.org/multipage/rendering.html#flow-content-3 */
-    background: rgba(0,0,0,0.1)
+    background: rgba(0,0,0,0.1);
+    top-layer: browser !important;
 }
 
 slot {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
index 7bf869a..90d51b4 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
 
+#include "base/debug/dump_without_crashing.h"
 #include "third_party/blink/renderer/core/editing/bidi_adjustment.h"
 #include "third_party/blink/renderer/core/editing/position_with_affinity.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
@@ -817,7 +818,7 @@
     if (UNLIKELY(item->IsLayoutObjectDestroyedOrMoved())) {
       // TODO(crbug.com/1099613): This should not happen, as long as it is
       // layout-clean. It looks like there are cases where the layout is dirty.
-      NOTREACHED();
+      base::debug::DumpWithoutCrashing();
       continue;
     }
     if (UNLIKELY(item->HasSelfPaintingLayer()))
diff --git a/third_party/blink/renderer/modules/webcodecs/decoder_template.cc b/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
index 011a447..9471e97 100644
--- a/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
+++ b/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
@@ -16,6 +16,7 @@
 #include "base/trace_event/common/trace_event_common.h"
 #include "base/trace_event/trace_event.h"
 #include "media/base/decoder_status.h"
+#include "media/base/media_util.h"
 #include "media/media_buildflags.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "third_party/blink/public/common/features.h"
@@ -421,7 +422,7 @@
   --num_pending_decodes_;
   ScheduleDequeueEvent();
 
-  if (media::ScopedDecodeTrace::IsEnabled()) {
+  if (media::MediaTraceIsEnabled()) {
     request->decode_trace = std::make_unique<media::ScopedDecodeTrace>(
         GetTraceNames()->decode.c_str(), *request->decoder_buffer);
   }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index 1939d68..b723e03d 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -556,9 +556,6 @@
   // The number of sub resource loads that a service worker fetch handler
   // called respondWith. i.e. no fallback to network.
   uint32_t number_of_subresource_loads_handled_by_service_worker_ = 0;
-
-  // NOTE: This must be the last member.
-  base::WeakPtrFactory<ResourceFetcher> weak_ptr_factory_{this};
 };
 
 class ResourceCacheValidationSuppressor {
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index 73f49fe..969c6ec0 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -446,7 +446,12 @@
 crbug.com/874695 [ Mac11 Release ] fast/css-grid-layout/grid-auto-repeat-huge-grid-005.html [ Slow ]
 crbug.com/874695 [ Mac12 ] fast/css-grid-layout/grid-auto-repeat-huge-grid-005.html [ Slow ]
 crbug.com/874695 [ Release Win ] fast/css-grid-layout/grid-auto-repeat-huge-grid-005.html [ Slow ]
-crbug.com/874695 fast/css-grid-layout/grid-auto-repeat-huge-grid-006.html [ Slow ]
+crbug.com/874695 [ Linux ] fast/css-grid-layout/grid-auto-repeat-huge-grid-006.html [ Slow ]
+crbug.com/874695 [ Mac10.15 Release ] fast/css-grid-layout/grid-auto-repeat-huge-grid-006.html [ Slow ]
+crbug.com/874695 [ Mac11 Release ] fast/css-grid-layout/grid-auto-repeat-huge-grid-006.html [ Slow ]
+crbug.com/874695 [ Mac12 ] fast/css-grid-layout/grid-auto-repeat-huge-grid-006.html [ Slow ]
+crbug.com/874695 [ Mac12-arm64 Release ] fast/css-grid-layout/grid-auto-repeat-huge-grid-006.html [ Slow ]
+crbug.com/874695 [ Release Win ] fast/css-grid-layout/grid-auto-repeat-huge-grid-006.html [ Slow ]
 crbug.com/874695 fast/css-grid-layout/grid-auto-repeat-huge-grid-007.html [ Slow ]
 crbug.com/874695 [ Linux ] fast/css-grid-layout/grid-auto-repeat-huge-grid-008.html [ Slow ]
 crbug.com/874695 [ Mac10.15 Release ] fast/css-grid-layout/grid-auto-repeat-huge-grid-008.html [ Slow ]
@@ -880,7 +885,12 @@
 crbug.com/678346 [ Debug Mac ] storage/indexeddb/index-cursor.html [ Slow ]
 crbug.com/799619 [ Debug ] http/tests/devtools/profiler/heap-snapshot-inspect-dom-wrapper.js [ Slow ]
 ###crbug.com/849979 media/video-layer-crash.html [ Slow ]
-crbug.com/831673 http/tests/devtools/reveal-objects.js [ Slow ]
+crbug.com/831673 [ Linux ] http/tests/devtools/reveal-objects.js [ Slow ]
+crbug.com/831673 [ Mac10.15 Release ] http/tests/devtools/reveal-objects.js [ Slow ]
+crbug.com/831673 [ Mac11 Release ] http/tests/devtools/reveal-objects.js [ Slow ]
+crbug.com/831673 [ Mac12 ] http/tests/devtools/reveal-objects.js [ Slow ]
+crbug.com/831673 [ Mac12-arm64 Release ] http/tests/devtools/reveal-objects.js [ Slow ]
+crbug.com/831673 [ Release Win ] http/tests/devtools/reveal-objects.js [ Slow ]
 crbug.com/829952 fast/webgl/texImage-imageBitmap-from-image-resize.html [ Slow ]
 crbug.com/1064522 external/wpt/html/user-activation/propagation-crossorigin.sub.html [ Slow ]
 crbug.com/863599 [ Debug ] external/wpt/requestidlecallback/callback-iframe.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 18506eac..93008247 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2978,6 +2978,13 @@
 crbug.com/webrtc/10567 external/wpt/webrtc/simulcast/setParameters-encodings.https.html [ Failure Pass ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-tables/whitespace-001.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-overflow/overflow-overlay.tentative.html [ Failure ]
 crbug.com/626703 [ Win11 ] external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html [ Failure Timeout ]
@@ -3039,7 +3046,6 @@
 crbug.com/626703 external/wpt/geolocation-API/enabled-by-permissions-policy.https.sub.html [ Timeout ]
 crbug.com/626703 external/wpt/geolocation-API/enabled-on-self-origin-by-permissions-policy.https.sub.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/shape-detection/detection-HTMLVideoElement.https.html [ Timeout ]
-crbug.com/626703 [ Linux ] external/wpt/video-rvfc/request-video-frame-callback-during-xr-session.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/web-nfc/NDEFReader_make-read-only.https.window.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/web-nfc/NDEFReader_scan.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/webxr/ar-module/xrSession_interactionMode.https.html [ Timeout ]
@@ -5308,7 +5314,6 @@
 crbug.com/1249176 [ Mac12-arm64 ] external/wpt/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-blob.tentative.html [ Failure ]
 crbug.com/1249176 [ Mac11-arm64 ] external/wpt/largest-contentful-paint/image-src-change.html [ Failure ]
 crbug.com/1249176 [ Mac11-arm64 ] http/tests/images/document-policy-oversized-images-forced-layout.php [ Failure ]
-crbug.com/1249176 [ Mac ] transforms/transformed-document-element.html [ Failure ]
 crbug.com/1249176 [ Mac11-arm64 ] virtual/threaded/http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Failure ]
 crbug.com/1249176 [ Mac12-arm64 ] virtual/threaded/http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Failure Pass ]
 crbug.com/1249176 [ Mac11-arm64 ] webaudio/codec-tests/webm/webm-decode.html [ Failure ]
@@ -5753,8 +5758,6 @@
 crbug.com/1288264 [ Win ] http/tests/fetch/serviceworker/thorough/nocors-base-https-other-https.html [ Pass Timeout ]
 crbug.com/1288264 [ Win ] http/tests/security/aboutBlank/xss-DENIED-navigate-opener-document-write.html [ Pass Timeout ]
 
-# Flakiness of WIP MediaStreamTrack on workers.
-crbug.com/1290767 external/wpt/mediacapture-insertable-streams/MediaStreamTrackGenerator-pipes-data-in-worker.https.html [ Crash Pass ]
 
 # Sheriff 2022-01-26
 crbug.com/1290978 [ Win ] external/wpt/css/CSS2/normal-flow/crashtests/block-in-inline-ax-crash.html [ Crash Failure Pass Timeout ]
diff --git a/third_party/blink/web_tests/editing/spelling/cold_mode_no_leak_detached_node.html b/third_party/blink/web_tests/editing/spelling/cold_mode_no_leak_detached_node.html
new file mode 100644
index 0000000..f4d7a3b
--- /dev/null
+++ b/third_party/blink/web_tests/editing/spelling/cold_mode_no_leak_detached_node.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>Spellchecker should not keep an unbounded number of detached nodes alive</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<body>
+<script>
+// Spins spellchecker until idle. Return whether it's actually run.
+function spinSpellChecker() {
+  let spellCheckerIsRun = false;
+  while (internals.idleTimeSpellCheckerState(document) !== 'Inactive') {
+    internals.runIdleTimeSpellChecker(document);
+    spellCheckerIsRun = true;
+  }
+  return spellCheckerIsRun;
+}
+
+test(() => {
+  const n = 100;
+  const numLiveNodesBefore = internals.numberOfLiveNodes();
+
+  for (let i = 0; i < n; ++i) {
+    {
+      let input = document.createElement('input');
+      document.body.appendChild(input);
+      input.focus();
+      assert_true(spinSpellChecker(), 'spellchecker is run');
+      input.remove();
+    }
+    gc();
+  }
+
+  const numLiveNodesAfter = internals.numberOfLiveNodes();
+  assert_less_than_equal(numLiveNodesAfter, numLiveNodesBefore + 10);
+});
+</script>
+</body>
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 1d1e39d..3441b7b 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
@@ -5080,6 +5080,15 @@
          {}
         ]
        ]
+      },
+      "the-textarea-element": {
+       "textarea-splittext-with-range-crash.html": [
+        "9d66a4ae05cccd10bdd851205f6312f3cedd28dd",
+        [
+         null,
+         {}
+        ]
+       ]
       }
      },
      "interactive-elements": {
@@ -104784,7 +104793,7 @@
        ]
       ],
       "descriptor-prefix.html": [
-       "ecf18420aad8be51888f21d0363f89053d7a4896",
+       "b9cf1b9bb1f19d4137a4ed0765eb1e118912e30a",
        [
         null,
         [
@@ -104887,6 +104896,19 @@
         {}
        ]
       ],
+      "fallback-cycle.html": [
+       "2e63a3f4d4445f1b57b216446f8d4474ff5808b1",
+       [
+        null,
+        [
+         [
+          "/css/css-counter-styles/counter-style-at-rule/fallback-cycle-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "fallbacks-in-shadow-dom.html": [
        "d51f70bc31c011fe9853755715a710837090a700",
        [
@@ -104965,6 +104987,19 @@
         {}
        ]
       ],
+      "suffix-fallback.html": [
+       "7684c9a10a9c09bc768cbb44a7379c1599f09eed",
+       [
+        null,
+        [
+         [
+          "/css/css-counter-styles/counter-style-at-rule/suffix-fallback-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "symbols-function-invalid.html": [
        "35aa83258726c89efc2c0e31a1e3927362c7f4e2",
        [
@@ -105005,7 +105040,7 @@
        ]
       ],
       "system-additive.html": [
-       "74568bccd183ef48f35edd1dd5cdc8cb049fdfd2",
+       "415f00a97458ee7967fa170f6caa94cd8d10e66b",
        [
         null,
         [
@@ -105031,7 +105066,7 @@
        ]
       ],
       "system-alphabetic.html": [
-       "9447eaf940401aa3304634a5ba89d48b3c465ca0",
+       "a986c54ac9f9f4c65dda9ead7ac44b8fab41e264",
        [
         null,
         [
@@ -105083,7 +105118,7 @@
        ]
       ],
       "system-extends.html": [
-       "287930d0f607c0582d2069b045dfc0f6d78b39fa",
+       "a8f95323aa41f1a933e70bd1e3df553f28e89896",
        [
         null,
         [
@@ -105161,7 +105196,7 @@
        ]
       ],
       "system-symbolic.html": [
-       "a3ab8b1a98a34ed0cbd2525c3f2b61973b45999d",
+       "99c1188c18e82e568cf32b126cf993b35e6d9737",
        [
         null,
         [
@@ -263177,6 +263212,16 @@
    }
   },
   "support": {
+   ".cache": {
+    "gitignore2.json": [
+     "0049f3e5247e64b948c41f5edbd906d61b954feb",
+     []
+    ],
+    "mtime.json": [
+     "0c7d29e6a9cdda61de450dcb3990409922abc5b9",
+     []
+    ]
+   },
    ".gitignore": [
     "d93e645d547894b50149d3726de2654957b6e06f",
     []
@@ -286801,7 +286846,11 @@
        []
       ],
       "descriptor-prefix-ref.html": [
-       "aa32f53639e99a502f8e0b53c4a8f22eeeb30d51",
+       "f106e616c5265740c73c56cbbe1fd5c42ad9a265",
+       []
+      ],
+      "descriptor-prefix.html.ini": [
+       "00b63bf55e2efe0ce9ac8f796e9c08e4b4320e78",
        []
       ],
       "descriptor-range-invalid-ref.html": [
@@ -286840,6 +286889,14 @@
        "95da656cfc89158953ad33da7757c4d86168fdd3",
        []
       ],
+      "fallback-cycle-ref.html": [
+       "22bcf8d9b4ef3963020b3e834c893756426df412",
+       []
+      ],
+      "fallback-cycle.html.ini": [
+       "912e1a676a91725be6c414790968cf6c77fd2460",
+       []
+      ],
       "fallbacks-in-shadow-dom-ref.html": [
        "53e467bb391884ec9751edfcffe85f03c8502e08",
        []
@@ -286876,6 +286933,14 @@
        "7f1af7532075c983e7fc0bcec7cd14830e0c13eb",
        []
       ],
+      "suffix-fallback-ref.html": [
+       "15cd54cb24f18b64f1bbbc900287bd9734a5f093",
+       []
+      ],
+      "suffix-fallback.html.ini": [
+       "fdd848b176ff0e3edaa2decf6a7c2ecebb3e11c0",
+       []
+      ],
       "support": {
        "counter-style-testcommon.js": [
         "a3615e92ff0678d5e7b2aad0a20076cd1ac07d6e",
@@ -286907,11 +286972,19 @@
        []
       ],
       "system-additive-ref.html": [
-       "b45ab5fcecf6774ea89eeb93bba9d41da99c9fea",
+       "993371307ae1a6b8d4d5c40014c56132c5fab5c7",
+       []
+      ],
+      "system-additive.html.ini": [
+       "5c48264eb90892cb9682e32a9fd1bad1f90a8959",
        []
       ],
       "system-alphabetic-ref.html": [
-       "331d96ea4c83a4b17c77baa1503cb4b23ca66889",
+       "b4a534beb830b6a00402235f0e839913ab2e0178",
+       []
+      ],
+      "system-alphabetic.html.ini": [
+       "51d376eacf7c009c8e70bbeebdc630993484a171",
        []
       ],
       "system-common-invalid-ref.html": [
@@ -286931,11 +287004,11 @@
        []
       ],
       "system-extends-ref.html": [
-       "c988310c25b8a251b6b302ab83d8b3f2dcd1f3ec",
+       "8105956ecb8dda46573e097ab43322416caa9449",
        []
       ],
       "system-extends.html.ini": [
-       "5e1da0edb8d17775aa5f20bec67e9763c8624759",
+       "cce2bed8622a3a0a0dd36e8fdb474eec038580dc",
        []
       ],
       "system-fixed-ref.html": [
@@ -286947,7 +287020,11 @@
        []
       ],
       "system-symbolic-ref.html": [
-       "7229c895ffc099d2f73667a5ca0abb31b40e8afd",
+       "61b743f35885acf8fa38baf7878de43ef0546dda",
+       []
+      ],
+      "system-symbolic.html.ini": [
+       "e0e2984ca6383797c6b501fde8bfc61b2453d37e",
        []
       ]
      },
@@ -319318,6 +319395,10 @@
        "5e9565445a693b0bac1d54974434291a0d9604d7",
        []
       ],
+      "text-transform-capitalize-024.html.ini": [
+       "d3c4f1350d08e6e26a797c54a6e2fedf01b4b429",
+       []
+      ],
       "text-transform-capitalize-026.html.ini": [
        "ff630745fc27ca4844b809a72548171a8c32ad20",
        []
@@ -321538,7 +321619,7 @@
       []
      ],
      "text-emphasis-line-height-003c.html.ini": [
-      "7f1d539724cb87fe196b9839b69cb2c9567074fa",
+      "4ffc8706c88fe32657cb5e2293d2ef15c8e21bd3",
       []
      ],
      "text-emphasis-line-height-003d.html.ini": [
@@ -321630,7 +321711,7 @@
       []
      ],
      "text-emphasis-position-property-003a.html.ini": [
-      "f5dc766b8cdeee4b82ed3b7feffe785bfa0abdcf",
+      "3ccfeb12466ed3f2efeccaefa6aa0bd15d9fb1be",
       []
      ],
      "text-emphasis-position-property-003b.html.ini": [
@@ -321682,7 +321763,7 @@
       []
      ],
      "text-emphasis-position-property-004e.html.ini": [
-      "5f8016033777ff02ba89bc0e110d991e291dd7ea",
+      "584a2427d8bf10e213d543428577fefbc58d0388",
       []
      ],
      "text-emphasis-position-property-004f.html.ini": [
@@ -325348,6 +325429,10 @@
        "cfa46fa9706127e00580cf1e1c5f022bc8563538",
        []
       ],
+      "kind-of-widget-fallback-input-reset-border-image-source-001.html.ini": [
+       "a911df1e36bb92f5c4da85931bc273900eb17c2c",
+       []
+      ],
       "kind-of-widget-fallback-input-reset-border-top-color-001.html.ini": [
        "14b26723f548de962341d22594eefaf841cec560",
        []
@@ -325360,6 +325445,10 @@
        "7891b7b80041c049bfdbefee4d8ea2acb35ac8ff",
        []
       ],
+      "kind-of-widget-fallback-input-search-border-bottom-style-001.html.ini": [
+       "7f0c55c56c12ea30869cc5b0b212ebfbaa31640f",
+       []
+      ],
       "kind-of-widget-fallback-input-search-border-left-color-001.html.ini": [
        "6c1ca654559185d68548fc23d9dcbd8256307bf1",
        []
@@ -325612,6 +325701,10 @@
        "f3bbc312a7def4d12ce50b151b0578d9fd76a0af",
        []
       ],
+      "kind-of-widget-fallback-textarea-background-attachment-001.html.ini": [
+       "1d37ff8372b35f040fcdcc0fa88e6b6db7b6c789",
+       []
+      ],
       "kind-of-widget-fallback-textarea-border-block-end-style-001.html.ini": [
        "10d4e093393272fd1fa437f1a4147d9af353598f",
        []
@@ -325636,6 +325729,10 @@
        "eb25c78cedcee1ba38a48a557d6bc29f085d3064",
        []
       ],
+      "kind-of-widget-fallback-textarea-border-right-style-001.html.ini": [
+       "cbd5a9a261dce5809cf1866a284225c2c1a5f62e",
+       []
+      ],
       "kind-of-widget-fallback-textarea-border-start-end-radius-001.html.ini": [
        "383158fa4f2968546607660b8170257687bb1615",
        []
@@ -326468,11 +326565,11 @@
       []
      ],
      "outline-025.html.ini": [
-      "cc571ab0463da9cf32819f1e820b5ef4b9ce9ab4",
+      "c5515ab0e129b5c55bd8b4e73f4750c363cae17d",
       []
      ],
      "outline-026.html.ini": [
-      "cdedc10fb52295d0fcc92f72c24c4882f3033b0a",
+      "771fe910ccaa5d6bdd85f09aa339c6cc2c29493d",
       []
      ],
      "outline-027.html.ini": [
@@ -344805,32 +344902,56 @@
       "81f6d8aac3a8a7057b3b91cbcb1ff3b5b07eb774",
       []
      ],
+     "service-worker-fetch.https.window.js.ini": [
+      "dd7d9e4d6751a1fb914d03b97048f2875bbe8820",
+      []
+     ],
      "service-worker-update.https.window-expected.txt": [
       "0aca19f20b483f0527a40e58c9aa507986c61365",
       []
      ],
+     "service-worker-update.https.window.js.ini": [
+      "169f1746682aa007ee3de7edeca6dfe47d5f57a0",
+      []
+     ],
      "service-worker.https.window-expected.txt": [
       "9f6d82c80281d637d51f1976ccbcc883448dbcf8",
       []
      ],
+     "service-worker.https.window.js.ini": [
+      "2dbdad597586b04e19e6f05bc960aedea31cc120",
+      []
+     ],
      "shared-worker-fetch.https.window-expected.txt": [
       "0dc5268932503b1922bc3e69b523c6d78d7c29b6",
       []
      ],
+     "shared-worker-fetch.https.window.js.ini": [
+      "4009bb211131015b11ea3b5980d4ade2064a471f",
+      []
+     ],
      "shared-worker-fetch.window-expected.txt": [
       "52b68beee5fb99fa3f008353283abec889ee2396",
       []
      ],
+     "shared-worker-fetch.window.js.ini": [
+      "2ec78f33d907217530c9591692bfc351250acd78",
+      []
+     ],
      "shared-worker.https.window-expected.txt": [
       "7acfd4c64f5339a5bc11a599d3d447bed545dd7f",
       []
      ],
+     "shared-worker.https.window.js.ini": [
+      "fbe8d7875167bb5af084fda65df75cecc1773ec4",
+      []
+     ],
      "shared-worker.window-expected.txt": [
       "8718ffde7bc70a2802ec04ecd5c1e3b42e0dca32",
       []
      ],
      "shared-worker.window.js.ini": [
-      "afa6f4c187dca0da3e32d890dbc0286982f480b3",
+      "4983f9842c565b5d5e4ce877b66b6de3443821aa",
       []
      ],
      "websocket.window-expected.txt": [
@@ -358617,6 +358738,10 @@
        }
       },
       "terminology-0": {
+       "document-base-url-changes-after-nav-about-srcdoc.https.window.js.ini": [
+        "394af9a1f37914ea3ed60fc93f1bce46ab06a49a",
+        []
+       ],
        "document-base-url-initiated-grand-parent.https.window-expected.txt": [
         "0f00b10ed387682fb257b26d51c871a61ab16a60",
         []
@@ -361568,7 +361693,7 @@
         []
        ],
        "sandbox-top-navigation-child.tentative.sub.window.js.ini": [
-        "7ce20ab053fa6451af680a7ff5762f6dec0d70b5",
+        "805f62339e40876ba265dd79d589579a56913ab6",
         []
        ],
        "sandbox-top-navigation-escalate-privileges.tentative.sub.window.js.ini": [
@@ -369001,7 +369126,7 @@
      []
     ],
     "compute-pressure.idl": [
-     "2a11b84c45d5f14f6ec6f71961515f0b66783933",
+     "42ff4f207ab5349c541f042c2a21f317d23ff401",
      []
     ],
     "console.idl": [
@@ -369145,11 +369270,11 @@
      []
     ],
     "css-view-transitions.idl": [
-     "c7ac9f336cfef03302c0df7db1cb1f9e573d0f1c",
+     "cf9cb8927e42c5d24c7c6fd0ae6e5d4c001ce806",
      []
     ],
     "cssom-view.idl": [
-     "2046b38533f4c9d5f4ccd1ee709ce45208344acf",
+     "4e531a26824965dc65f833533ab122ed98b94d8d",
      []
     ],
     "cssom.idl": [
@@ -369453,7 +369578,7 @@
      []
     ],
     "payment-handler.idl": [
-     "65b64bdf31c7dfed778ba475e154cd780ca44e86",
+     "91c01297f40bb12e08dcbba2807f7b35929fd396",
      []
     ],
     "payment-request.idl": [
@@ -369593,7 +369718,7 @@
      []
     ],
     "scroll-animations.idl": [
-     "30ecbd81c908d8aff8b97c1b5f25b943fae2454e",
+     "1fd52dece191c65f8480168206a35cdd93a5d5f0",
      []
     ],
     "scroll-to-text-fragment.idl": [
@@ -369813,7 +369938,7 @@
      []
     ],
     "webnn.idl": [
-     "1bb9563c29c27071fe72801f866d8446e316256f",
+     "820c79e96666f812c0ce46d2e298859f93497149",
      []
     ],
     "webrtc-encoded-transform.idl": [
@@ -369833,11 +369958,11 @@
      []
     ],
     "webrtc-stats.idl": [
-     "397d7838b799ed148ccd608fc27d6cbd7a39f74e",
+     "f1dca4a923d46517a8a5e943aa3ac7a0cab78778",
      []
     ],
     "webrtc-svc.idl": [
-     "e42efe03b69a180df037017fd96eb863a5292643",
+     "e67ed70e8a767cef8119e912deef82930542880b",
      []
     ],
     "webrtc.idl": [
@@ -369897,7 +370022,7 @@
      []
     ],
     "webxrlayers.idl": [
-     "785a742e0b58a28a36c31680dcff4f85bda57aa0",
+     "e182f47b9c5bce5b6f3c8d47109358eb6c999856",
      []
     ],
     "window-controls-overlay.idl": [
@@ -371185,7 +371310,7 @@
        []
       ],
       "mo-axis-height-1.html.ini": [
-       "35bdfebfaee8ff8749cf110873c36f8f0d51ea9c",
+       "59bfab0531e6bb9216766998fad1020a474577b1",
        []
       ],
       "mo-form-dynamic-002-ref.html": [
@@ -375133,19 +375258,11 @@
      []
     ],
     "idlharness.https.any.js.ini": [
-     "dc57fd5daeba4ea318ab14228c262fcdc08865d9",
+     "6891dadf918640095b734b62dc31319e1db41890",
      []
     ],
     "idlharness.https.any.serviceworker-expected.txt": [
-     "90e3142f5a96dc812a5cbd21f2703f9f8b4aef04",
-     []
-    ],
-    "idlharness.https.any.sharedworker-expected.txt": [
-     "28845dfb2c7b490e78e70948a71bf006d5cfd76e",
-     []
-    ],
-    "idlharness.https.any.worker-expected.txt": [
-     "28845dfb2c7b490e78e70948a71bf006d5cfd76e",
+     "a70b18b7a282f2d0250679e58951c727c32f9f2f",
      []
     ],
     "manifest.json": [
@@ -393387,7 +393504,7 @@
      []
     ],
     "idlharness.https.any-expected.txt": [
-     "a5169a6182d1654187e28519db0db99d8fcef089",
+     "f86850a6673e0e1477c5451f2a72fd16041c3500",
      []
     ],
     "idlharness.https.any.js.ini": [
@@ -393395,7 +393512,7 @@
      []
     ],
     "idlharness.https.any.worker-expected.txt": [
-     "183b4c4359f187d3540444509a38c1f07ea9e5e0",
+     "71decbd4994b277ba12f480e0615383385e12d8f",
      []
     ],
     "leaky_relu.https.any-expected.txt": [
@@ -394595,7 +394712,7 @@
      []
     ],
     "supported-stats.https-expected.txt": [
-     "6920be4920c99d495662d3ba320351bd7e553ad0",
+     "5006c482344955c1feb842b137ba768dccf05f0c",
      []
     ],
     "supported-stats.https.html.ini": [
@@ -630787,7 +630904,7 @@
      ]
     ],
     "RTCPeerConnection-relay-canvas.https.html": [
-     "7c3c92bc8de40f608417663844329ed19f61cea0",
+     "78df2ee82d623403f2a627b99c43051a99c96edb",
      [
       null,
       {
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-connection.window.js b/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-connection.window.js
index 397eada..10c8482 100644
--- a/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-connection.window.js
+++ b/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-connection.window.js
@@ -26,6 +26,9 @@
   // Create an IndexedDB database with higher version.
   await createIndexedDBForTesting(rc2, 'test_idb_2', 2);
   await rc2.historyBack();
-  // The previous page receiving versionchange event should be evicted.
-  await assert_not_bfcached(rc1);
+  // The previous page receiving versionchange event should be evicted with the
+  // correct reason.
+  // `kIgnoreEventAndEvict` will be reported as "Internal error".
+  // See `NotRestoredReasonToReportString()`.
+  await assert_not_bfcached(rc1, ['Internal error']);
 });
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix-ref.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix-ref.html
index aa32f53..f106e61 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix-ref.html
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <meta charset="UTF-8">
-<title>CSS Reference: symbols function, invalid</title>
+<title>CSS Reference: descriptor prefix</title>
 <link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
 <link rel="stylesheet" href="support/ref-common.css">
 <!-- ol -->
-<div>Appendix -2.&nbsp;</div>
-<div>Appendix -1.&nbsp;</div>
-<div>Appendix 0.&nbsp;</div>
+<div>-2.&nbsp;</div>
+<div>-1.&nbsp;</div>
+<div>0.&nbsp;</div>
 <div>Appendix I.&nbsp;</div>
 <div>Appendix II.&nbsp;</div>
 <!-- section -->
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix.html
index ecf18420..b9cf1b9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix.html
@@ -7,6 +7,8 @@
 <link rel="stylesheet" href="support/test-common.css">
 <style type="text/css">
   @counter-style a {
+    /* Note that upper-roman has a range of (1, 3999), so negative or zero values
+       will use the fallback style. */
     system: extends upper-roman;
     prefix: "Appendix ";
   }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix.html.ini b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix.html.ini
new file mode 100644
index 0000000..00b63bf5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/descriptor-prefix.html.ini
@@ -0,0 +1,2 @@
+[descriptor-prefix.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle-ref.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle-ref.html
new file mode 100644
index 0000000..22bcf8d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle-ref.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CSS Reference: fallback cycle</title>
+<style>
+.decimal {
+    list-style-type: decimal;
+}
+.paren::marker {
+    content: "(" counter(list-item) ")\A0";
+}
+.bracket::marker {
+    content: "[" counter(list-item, lower-roman) "]\A0";
+}
+.brace::marker {
+    content: "{" counter(list-item, lower-alpha) "}\A0";
+}
+</style>
+
+<ol>
+    <li class=decimal>paren > bracket > brace > decimal
+    <li class=paren>paren
+    <li class=paren>paren
+    <li class=paren>paren
+    <li class=bracket>paren > bracket
+    <li class=bracket>paren > bracket
+    <li class=bracket>paren > bracket
+    <li class=brace>paren > bracket > brace
+    <li class=brace>paren > bracket > brace
+    <li class=decimal>paren > bracket > brace > decimal
+</ol>
+
+<ol>
+    <li class=decimal>bracket > brace > paren > decimal
+    <li class=paren>bracket > brace > paren
+    <li class=paren>bracket > brace > paren
+    <li class=bracket>bracket
+    <li class=bracket>bracket
+    <li class=bracket>bracket
+    <li class=bracket>bracket
+    <li class=brace>bracket > brace
+    <li class=brace>bracket > brace
+    <li class=decimal>bracket > brace > paren > decimal
+</ol>
+
+<ol>
+    <li class=decimal>brace > paren > bracket > decimal
+    <li class=paren>brace > paren
+    <li class=paren>brace > paren
+    <li class=paren>brace > paren
+    <li class=bracket>brace > paren > bracket
+    <li class=bracket>brace > paren > bracket
+    <li class=brace>brace
+    <li class=brace>brace
+    <li class=brace>brace
+    <li class=decimal>brace > paren > bracket > decimal
+</ol>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle.html
new file mode 100644
index 0000000..2e63a3f4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CSS Test: fallback cycle</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-counter-styles-3/#counter-style-range">
+<link rel="help" href="https://drafts.csswg.org/css-counter-styles-3/#counter-style-fallback">
+<meta name="assert" content="While following fallbacks to find a counter style that can render the given counter value,
+                             if a loop in the specified fallbacks is detected, the decimal style must be used instead">
+<link rel="match" href="fallback-cycle-ref.html">
+<style>
+/*
+    Three styles with different but overlapping ranges,
+    with fallback to each other in a cycle.
+
+    Depending where in the cycle we start, we expect different results
+    for the overlapping ranges; in all cases we fall back to the default
+    (decimal) style when fallback would loop around.
+*/
+@counter-style paren {
+    system: extends decimal;
+    prefix: "(";
+    suffix: ")\A0";
+    range: 2 4;
+    fallback: bracket;
+}
+
+@counter-style bracket {
+    system: extends lower-roman;
+    prefix: "[";
+    suffix: "]\A0";
+    range: 4 7;
+    fallback: brace;
+}
+
+@counter-style brace {
+    system: extends lower-alpha;
+    prefix: "{";
+    suffix: "}\A0";
+    range: 7 9;
+    fallback: paren;
+}
+
+ol {
+    list-style-type: disc;  /* overridden by the counter-style rules */
+}
+</style>
+
+<ol style="list-style: paren">
+    <li>paren > bracket > brace > decimal
+    <li>paren
+    <li>paren
+    <li>paren
+    <li>paren > bracket
+    <li>paren > bracket
+    <li>paren > bracket
+    <li>paren > bracket > brace
+    <li>paren > bracket > brace
+    <li>paren > bracket > brace > decimal
+</ol>
+
+<ol style="list-style: bracket">
+    <li>bracket > brace > paren > decimal
+    <li>bracket > brace > paren
+    <li>bracket > brace > paren
+    <li>bracket
+    <li>bracket
+    <li>bracket
+    <li>bracket
+    <li>bracket > brace
+    <li>bracket > brace
+    <li>bracket > brace > paren > decimal
+</ol>
+
+<ol style="list-style: brace">
+    <li>brace > paren > bracket > decimal
+    <li>brace > paren
+    <li>brace > paren
+    <li>brace > paren
+    <li>brace > paren > bracket
+    <li>brace > paren > bracket
+    <li>brace
+    <li>brace
+    <li>brace
+    <li>brace > paren > bracket > decimal
+</ol>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle.html.ini b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle.html.ini
new file mode 100644
index 0000000..912e1a6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/fallback-cycle.html.ini
@@ -0,0 +1,2 @@
+[fallback-cycle.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback-ref.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback-ref.html
new file mode 100644
index 0000000..15cd54c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback-ref.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CSS Reference: suffix fallback</title>
+<style>
+div div {
+  width: 4em;
+  text-align: right;
+}
+</style>
+
+<div>
+    <div>1st</div>
+    <div>2nd</div>
+    <div>3rd</div>
+    <div>4th</div>
+    <div>5th</div>
+    <div>6th</div>
+    <div>7th</div>
+    <div>8th</div>
+    <div>9th</div>
+    <div>10th</div>
+    <div>11th</div>
+    <div>12th</div>
+    <div>13th</div>
+    <div>14th</div>
+    <div>15th</div>
+    <div>16th</div>
+    <div>17th</div>
+    <div>18th</div>
+    <div>19th</div>
+    <div>20th</div>
+    <div>21st</div>
+    <div>22nd</div>
+    <div>23rd</div>
+    <div>24th</div>
+    <div>25th</div>
+    <div>26th</div>
+    <div>27th</div>
+    <div>28th</div>
+    <div>29th</div>
+    <div>30th</div>
+    <div>31st</div>
+    <div>32nd</div>
+    <div>33rd</div>
+    <div>34th</div>
+    <div>35th</div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback.html
new file mode 100644
index 0000000..7684c9a1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CSS Test: suffix fallback</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-counter-styles-3/#counter-style-range">
+<link rel="help" href="https://drafts.csswg.org/css-counter-styles-3/#counter-style-fallback">
+<link rel="match" href="suffix-fallback-ref.html">
+<style>
+/* A set of rules that rely on range limits and fallback to vary the suffix. */
+@counter-style ordinal-default {
+    system: numeric;
+    symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
+    suffix: "th";
+    range: 1 infinite;
+}
+
+@counter-style ordinal {
+    system: extends ordinal-default;
+    suffix: "st";
+    fallback: ordinal-twos;
+    range: 1 1, 21 21, 31 31, 41 41, 51 51, 61 61, 71 71, 81 81, 91 91;
+}
+
+@counter-style ordinal-twos {
+    system: extends ordinal-default;
+    suffix: "nd";
+    fallback: ordinal-threes;
+    range: 2 2, 22 22, 32 32, 42 42, 52 52, 62 62, 72 72, 82 82, 92 92;
+}
+
+@counter-style ordinal-threes {
+    system: extends ordinal-default;
+    suffix: "rd";
+    fallback: ordinal-default;
+    range: 3 3, 23 23, 33 33, 43 43, 53 53, 63 63, 73 73, 83 83, 93 93;
+}
+
+ol.ordinal {
+    margin: 0;
+    padding: 0;
+    list-style: ordinal;
+}
+li {
+    margin-left: 4em;
+}
+</style>
+
+<ol class="ordinal">
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+    <li></li>
+</ol>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback.html.ini b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback.html.ini
new file mode 100644
index 0000000..fdd848b1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/suffix-fallback.html.ini
@@ -0,0 +1,2 @@
+[suffix-fallback.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive-ref.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive-ref.html
index b45ab5f..9933713 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive-ref.html
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <meta charset="UTF-8">
-<title>CSS Reference: symbols function, invalid</title>
+<title>CSS Reference: system additive</title>
 <link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
 <link rel="stylesheet" href="support/ref-common.css">
 <!-- list-style-type: a -->
-<div>-2</div>
-<div>-1</div>
-<div>0</div>
+<div>-2.&nbsp;</div>
+<div>-1.&nbsp;</div>
+<div>0.&nbsp;</div>
 <div>&#x2680;</div>
 <div>&#x2681;</div>
 <div>&#x2682;</div>
@@ -22,8 +22,8 @@
   document.write(Array(61).join('&#x2685;'));
 </script></div>
 <!-- list-style-type: b -->
-<div>-2</div>
-<div>-1</div>
+<div>-2.&nbsp;</div>
+<div>-1.&nbsp;</div>
 <div>&#x2637;</div>
 <div>&#x2636;</div>
 <div>&#x2635;</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive.html
index 74568bc..415f00a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive.html
@@ -7,11 +7,13 @@
 <link rel="stylesheet" href="support/test-common.css">
 <style type="text/css">
   @counter-style a {
+    /* Negative and zero values cannot be represented, and will use fallback style (decimal). */
     system: additive;
     additive-symbols: 6 \2685, 5 \2684, 4 \2683, 3 \2682, 2 \2681, 1 \2680;
     suffix: "";
   }
   @counter-style b {
+    /* Negative values cannot be represented, and will use fallback style (decimal). */
     system: additive;
     additive-symbols: 7 \2630, 6 \2631, 5 \2632, 4 \2633, 3 \2634, 2 \2635, 1 \2636, 0 \2637;
     suffix: "";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive.html.ini b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive.html.ini
new file mode 100644
index 0000000..5c48264
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-additive.html.ini
@@ -0,0 +1,2 @@
+[system-additive.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic-ref.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic-ref.html
index 331d96e..b4a534b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic-ref.html
@@ -3,9 +3,9 @@
 <title>CSS Reference: symbols function, invalid</title>
 <link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
 <link rel="stylesheet" href="support/ref-common.css">
-<div>-2</div>
-<div>-1</div>
-<div>0</div>
+<div>-2.&nbsp;</div>
+<div>-1.&nbsp;</div>
+<div>0.&nbsp;</div>
 <div>&#x26AA;</div>
 <div>&#x26AB;</div>
 <div>&#x26AA;&#x26AA;</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic.html
index 9447eaf9..a986c54 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic.html
@@ -7,6 +7,8 @@
 <link rel="stylesheet" href="support/test-common.css">
 <style type="text/css">
   @counter-style a {
+    /* alphabetic has a range that starts from 1, so negative/zero values will
+       fall back to decimal */
     system: alphabetic;
     symbols: \26AA  \26AB;
     suffix: '';
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic.html.ini b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic.html.ini
new file mode 100644
index 0000000..51d376ea
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-alphabetic.html.ini
@@ -0,0 +1,2 @@
+[system-alphabetic.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends-ref.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends-ref.html
index c988310..8105956 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends-ref.html
@@ -4,24 +4,24 @@
 <link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
 <link rel="stylesheet" href="support/ref-common.css">
 <!-- list-style-type: a -->
-<div>Chapter -2.&nbsp;</div>
-<div>Chapter -1.&nbsp;</div>
-<div>Chapter 0.&nbsp;</div>
+<div>-2.&nbsp;</div>
+<div>-1.&nbsp;</div>
+<div>0.&nbsp;</div>
 <div>Chapter I.&nbsp;</div>
 <div>Chapter II.&nbsp;</div>
 <div>Chapter III.&nbsp;</div>
 <div>Chapter IV.&nbsp;</div>
 <div>Chapter V.&nbsp;</div>
-<div>Chapter 6.&nbsp;</div>
-<div>Chapter 7.&nbsp;</div>
+<div>6.&nbsp;</div>
+<div>7.&nbsp;</div>
 <!-- list-style-type: b -->
-<div>Section -2.&nbsp;</div>
-<div>Section -1.&nbsp;</div>
-<div>Section 0.&nbsp;</div>
+<div>-2.&nbsp;</div>
+<div>-1.&nbsp;</div>
+<div>0.&nbsp;</div>
 <div>Section I.&nbsp;</div>
 <div>Section II.&nbsp;</div>
 <div>Section III.&nbsp;</div>
 <div>Section IV.&nbsp;</div>
 <div>Section V.&nbsp;</div>
 <div>Section VI.&nbsp;</div>
-<div>Section 7.&nbsp;</div>
+<div>7.&nbsp;</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends.html
index 287930d..a8f9532 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends.html
@@ -7,11 +7,13 @@
 <link rel="stylesheet" href="support/test-common.css">
 <style type="text/css">
   @counter-style a {
+    /* Values outside the range will fall back to decimal (and hence have no prefix) */
     system: extends upper-roman;
     prefix: "Chapter ";
     range: 1 5;
   }
   @counter-style b {
+    /* Values outside the range will fall back to decimal (and hence have no prefix) */
     system: extends a;
     prefix: "Section ";
     range: 1 6;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends.html.ini b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends.html.ini
index 5e1da0ed..cce2bed8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-extends.html.ini
@@ -1,3 +1,3 @@
 [system-extends.html]
   expected:
-    if flag_specific == "disable-layout-ng": FAIL
+    if (os == "linux") and (version == "Ubuntu 18.04"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic-ref.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic-ref.html
index 7229c89..61b743f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic-ref.html
@@ -4,9 +4,9 @@
 <link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
 <link rel="stylesheet" href="support/ref-common.css">
 <!-- list-style-type: a -->
-<div>-2</div>
-<div>-1</div>
-<div>0</div>
+<div>-2.&nbsp;</div>
+<div>-1.&nbsp;</div>
+<div>0.&nbsp;</div>
 <div>*</div>
 <div>&#x2051;</div>
 <div>&#x2020;</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic.html
index a3ab8b1a..99c1188 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic.html
@@ -8,6 +8,8 @@
 <style type="text/css">
   @counter-style a {
     /* system: symbolic; */
+    /* symbolic does not support negative or zero values, so they will fall back
+       to decimal */
     symbols: '*' \2051  \2020  \2021;
     suffix: '';
   }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic.html.ini b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic.html.ini
new file mode 100644
index 0000000..e0e2984c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-style-at-rule/system-symbolic.html.ini
@@ -0,0 +1,2 @@
+[system-symbolic.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-line-height-003c.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-line-height-003c.html.ini
index 7f1d539..4ffc870 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-line-height-003c.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-line-height-003c.html.ini
@@ -1,3 +1,4 @@
 [text-emphasis-line-height-003c.html]
   expected:
-    if product == "content_shell": FAIL
+    if product == "chrome": [FAIL, PASS]
+    FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-position-property-003a.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-position-property-003a.html.ini
index f5dc766b..3ccfeb1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-position-property-003a.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-position-property-003a.html.ini
@@ -1,3 +1,4 @@
 [text-emphasis-position-property-003a.html]
   expected:
-    if product == "content_shell": FAIL
+    if product == "chrome": [FAIL, PASS]
+    FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-position-property-004e.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-position-property-004e.html.ini
index 5f80160..584a2427 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-position-property-004e.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-position-property-004e.html.ini
@@ -1,3 +1,4 @@
 [text-emphasis-position-property-004e.html]
   expected:
-    if product == "content_shell": FAIL
+    if product == "chrome": [FAIL, PASS]
+    FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-024.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-024.html.ini
new file mode 100644
index 0000000..d3c4f135
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-024.html.ini
@@ -0,0 +1,2 @@
+[text-transform-capitalize-024.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-image-source-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-image-source-001.html.ini
new file mode 100644
index 0000000..a911df1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-image-source-001.html.ini
@@ -0,0 +1,2 @@
+[kind-of-widget-fallback-input-reset-border-image-source-001.html]
+  expected: 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-bottom-style-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-bottom-style-001.html.ini
new file mode 100644
index 0000000..7f0c55c5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-bottom-style-001.html.ini
@@ -0,0 +1,2 @@
+[kind-of-widget-fallback-input-search-border-bottom-style-001.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-background-attachment-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-background-attachment-001.html.ini
new file mode 100644
index 0000000..1d37ff8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-background-attachment-001.html.ini
@@ -0,0 +1,2 @@
+[kind-of-widget-fallback-textarea-background-attachment-001.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-right-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-right-style-001.html.ini
new file mode 100644
index 0000000..cbd5a9a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-right-style-001.html.ini
@@ -0,0 +1,2 @@
+[kind-of-widget-fallback-textarea-border-right-style-001.html]
+  expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/outline-025.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/outline-025.html.ini
index cc571ab0..c5515ab0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ui/outline-025.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/outline-025.html.ini
@@ -1,3 +1,3 @@
 [outline-025.html]
   expected:
-    if (os == "win") and (processor == "x86_64"): FAIL
+    if (os == "linux") and (version == "Ubuntu 18.04"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/outline-026.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/outline-026.html.ini
index cdedc10f..771fe91 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ui/outline-026.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/outline-026.html.ini
@@ -1,3 +1,3 @@
 [outline-026.html]
   expected:
-    if flag_specific == "disable-layout-ng": FAIL
+    if (os == "linux") and (version == "Ubuntu 18.04"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-fetch.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-fetch.https.window.js.ini
new file mode 100644
index 0000000..dd7d9e4d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-fetch.https.window.js.ini
@@ -0,0 +1,15 @@
+[service-worker-fetch.https.window.html]
+  [private to local: failed preflight.]
+    expected: FAIL
+
+  [public to local: failed preflight.]
+    expected: FAIL
+
+  [public to private: failed preflight.]
+    expected: FAIL
+
+  [treat-as-public to local: failed preflight.]
+    expected: FAIL
+
+  [treat-as-public to private: failed preflight.]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-update.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-update.https.window.js.ini
new file mode 100644
index 0000000..169f174
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-update.https.window.js.ini
@@ -0,0 +1,6 @@
+[service-worker-update.https.window.html]
+  [update public to local: failed preflight.]
+    expected: FAIL
+
+  [update public to private: failed preflight.]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker.https.window.js.ini
new file mode 100644
index 0000000..2dbdad5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker.https.window.js.ini
@@ -0,0 +1,6 @@
+[service-worker.https.window.html]
+  [treat-as-public to local: failed preflight.]
+    expected: FAIL
+
+  [treat-as-public to private: failed preflight.]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-fetch.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-fetch.https.window.js.ini
new file mode 100644
index 0000000..4009bb2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-fetch.https.window.js.ini
@@ -0,0 +1,15 @@
+[shared-worker-fetch.https.window.html]
+  [private to local: failure.]
+    expected: FAIL
+
+  [public to local: failed preflight.]
+    expected: FAIL
+
+  [public to private: failed preflight.]
+    expected: FAIL
+
+  [treat-as-public to local: failed preflight.]
+    expected: FAIL
+
+  [treat-as-public to private: failed preflight.]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-fetch.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-fetch.window.js.ini
new file mode 100644
index 0000000..2ec78f3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-fetch.window.js.ini
@@ -0,0 +1,3 @@
+[shared-worker-fetch.window.html]
+  [treat-as-public to local: failure.]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker.https.window.js.ini
new file mode 100644
index 0000000..fbe8d78
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker.https.window.js.ini
@@ -0,0 +1,6 @@
+[shared-worker.https.window.html]
+  [treat-as-public to local: failed preflight.]
+    expected: FAIL
+
+  [treat-as-public to private: failed preflight.]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker.window.js.ini
index afa6f4c..4983f98 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker.window.js.ini
@@ -1,3 +1,8 @@
 [shared-worker.window.html]
   [treat-as-public to local: failure.]
-    expected: [PASS, FAIL]
+    expected:
+      if (processor == "x86_64") and (os == "linux") and (version == "Ubuntu 18.04"): FAIL
+      if (processor == "x86_64") and (os == "win"): FAIL
+
+  [treat-as-public to private: failure.]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js
index ef0da2d..7b9e83a1 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js
@@ -25,12 +25,62 @@
   assert_implements_optional(beforeBFCache == true, 'BFCache not supported.');
 }
 
-// If the value in window is undefined, this means that the page was reloaded,
-// i.e., the page was not restored from BFCache.
+// A helper function to assert that the page is not restored from BFCache by
+// checking whether the `beforeBFCache` value from `window` is undefined
+// due to page reload.
+// This function also takes an optional `notRestoredReasons` list which
+// indicates the set of expected reasons that make the page not restored.
+// If the reasons list is undefined, the check will be skipped. Otherwise
+// this check will use the `notRestoredReasons` API, to obtain the reasons
+// in a tree structure, and flatten the reasons before making the order-
+// insensitive comparison.
+// If the API is not available, the function will terminate instead of marking
+// the assertion failed.
 // Call `prepareForBFCache()` before navigating away to call this function.
-async function assert_not_bfcached(remoteContextHelper) {
+async function assert_not_bfcached(
+    remoteContextHelper, notRestoredReasons) {
   var beforeBFCache = await getBeforeBFCache(remoteContextHelper);
   assert_equals(beforeBFCache, undefined);
+
+  // The reason is optional, so skip the remaining test if the
+  // `notRestoredReasons` is not set.
+  if (notRestoredReasons === undefined) {
+    return;
+  }
+
+  let isFeatureEnabled = await remoteContextHelper.executeScript(() => {
+    return 'notRestoredReasons' in performance.getEntriesByType('navigation')[0];
+  });
+
+  // Return if the `notRestoredReasons` API is not available.
+  if (!isFeatureEnabled) {
+    return;
+  }
+
+  let result = await remoteContextHelper.executeScript(() => {
+    return performance.getEntriesByType('navigation')[0].notRestoredReasons;
+  });
+
+  let expectedNotRestoredReasonsSet = new Set(notRestoredReasons);
+  let notRestoredReasonsSet = new Set();
+
+  // Flatten the reasons from the main frame and all the child frames.
+  const collectReason = (node) => {
+    for (let reason of node.reasons) {
+      notRestoredReasonsSet.add(reason);
+    }
+    for (let child of node.children) {
+      collectReason(child);
+    }
+  }
+  collectReason(result);
+
+  assert_equals(notRestoredReasonsSet.length,
+      expectedNotRestoredReasonsSet.length);
+
+  for (let reason of expectedNotRestoredReasonsSet) {
+    assert_true(notRestoredReasonsSet.has(reason));
+  }
 }
 
 // A helper function that combines the steps of setting window property,
diff --git a/third_party/blink/web_tests/external/wpt/html/infrastructure/urls/terminology-0/document-base-url-changes-after-nav-about-srcdoc.https.window.js.ini b/third_party/blink/web_tests/external/wpt/html/infrastructure/urls/terminology-0/document-base-url-changes-after-nav-about-srcdoc.https.window.js.ini
new file mode 100644
index 0000000..394af9a1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/infrastructure/urls/terminology-0/document-base-url-changes-after-nav-about-srcdoc.https.window.js.ini
@@ -0,0 +1,6 @@
+[document-base-url-changes-after-nav-about-srcdoc.https.window.html]
+  [non-sandboxed srcdoc - parent changes baseURI]
+    expected: FAIL
+
+  [sandboxed srcdoc - parent changes baseURI]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js.ini
index 7ce20ab..805f623 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js.ini
@@ -1,3 +1,4 @@
 [sandbox-top-navigation-child.tentative.sub.window.html]
   expected:
-    if (os == "linux") and (product == "chrome"): ERROR
+    if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [TIMEOUT, OK]
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-textarea-element/textarea-splittext-with-range-crash.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-textarea-element/textarea-splittext-with-range-crash.html
new file mode 100644
index 0000000..9d66a4a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-textarea-element/textarea-splittext-with-range-crash.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<script>
+addEventListener("load", () => {
+  const textarea = document.querySelector("textarea");
+  const ul = document.createElement('ul');
+
+  const textNodeInTextarea = document.createTextNode("");
+  textarea.appendChild(textNodeInTextarea);
+  document.documentElement.getBoundingClientRect();
+
+  textarea.appendChild(ul);
+  const range = document.createRange();
+  range.selectNode(ul);
+
+  textNodeInTextarea.data = "ab";
+  textNodeInTextarea.splitText(1);
+});
+</script>
+</head>
+<body><textarea></textarea></body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/compute-pressure.idl b/third_party/blink/web_tests/external/wpt/interfaces/compute-pressure.idl
index 2a11b84..42ff4f20 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/compute-pressure.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/compute-pressure.idl
@@ -32,6 +32,7 @@
   readonly attribute PressureState state;
   readonly attribute FrozenArray<PressureFactor> factors;
   readonly attribute DOMHighResTimeStamp time;
+  [Default] object toJSON();
 };
 
 dictionary PressureObserverOptions {
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/css-view-transitions.idl b/third_party/blink/web_tests/external/wpt/interfaces/css-view-transitions.idl
index c7ac9f3..cf9cb89 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/css-view-transitions.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/css-view-transitions.idl
@@ -4,15 +4,15 @@
 // Source: CSS View Transitions Module Level 1 (https://drafts.csswg.org/css-view-transitions-1/)
 
 partial interface Document {
-  ViewTransition startViewTransition(optional UpdateDOMCallback? callback = null);
+  ViewTransition startViewTransition(optional UpdateCallback? callback = null);
 };
 
-callback UpdateDOMCallback = Promise<any> ();
+callback UpdateCallback = Promise<any> ();
 
 [Exposed=Window]
 interface ViewTransition {
   undefined skipTransition();
   readonly attribute Promise<undefined> finished;
   readonly attribute Promise<undefined> ready;
-  readonly attribute Promise<undefined> domUpdated;
+  readonly attribute Promise<undefined> updateCallbackDone;
 };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/cssom-view.idl b/third_party/blink/web_tests/external/wpt/interfaces/cssom-view.idl
index 2046b38..4e531a268 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/cssom-view.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/cssom-view.idl
@@ -3,7 +3,7 @@
 // (https://github.com/w3c/webref)
 // Source: CSSOM View Module (https://drafts.csswg.org/cssom-view-1/)
 
-enum ScrollBehavior { "auto", "smooth" };
+enum ScrollBehavior { "auto", "instant", "smooth" };
 
 dictionary ScrollOptions {
     ScrollBehavior behavior = "auto";
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/payment-handler.idl b/third_party/blink/web_tests/external/wpt/interfaces/payment-handler.idl
index 65b64bd..91c01297 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/payment-handler.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/payment-handler.idl
@@ -7,7 +7,7 @@
   [SameObject] readonly attribute PaymentManager paymentManager;
 };
 
-[SecureContext, Exposed=(Window,Worker)]
+[SecureContext, Exposed=(Window)]
 interface PaymentManager {
   attribute DOMString userHint;
   Promise<undefined> enableDelegations(sequence<PaymentDelegation> delegations);
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/scroll-animations.idl b/third_party/blink/web_tests/external/wpt/interfaces/scroll-animations.idl
index 30ecbd8..1fd52de 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/scroll-animations.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/scroll-animations.idl
@@ -1,7 +1,7 @@
 // GENERATED CONTENT - DO NOT EDIT
 // Content was automatically extracted by Reffy into webref
 // (https://github.com/w3c/webref)
-// Source: Scroll-linked Animations (https://drafts.csswg.org/scroll-animations-1/)
+// Source: Scroll-driven Animations (https://drafts.csswg.org/scroll-animations-1/)
 
 enum ScrollAxis {
   "block",
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webnn.idl b/third_party/blink/web_tests/external/wpt/interfaces/webnn.idl
index 1bb9563c..820c79e 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/webnn.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/webnn.idl
@@ -36,30 +36,8 @@
   MLContext createContextSync(GPUDevice gpuDevice);
 };
 
-typedef record<DOMString, ArrayBufferView> MLNamedArrayBufferViews;
-
 [SecureContext, Exposed=(Window, DedicatedWorker)]
-interface MLContext {};
-
-partial interface MLContext {
-  [Exposed=(DedicatedWorker)]
-  undefined computeSync(
-      MLGraph graph, MLNamedArrayBufferViews inputs, MLNamedArrayBufferViews outputs);
-};
-
-dictionary MLComputeResult {
-  MLNamedArrayBufferViews inputs;
-  MLNamedArrayBufferViews outputs;
-};
-
-partial interface MLContext {
-  Promise<MLComputeResult> compute(
-      MLGraph graph, MLNamedArrayBufferViews inputs, MLNamedArrayBufferViews outputs);
-};
-
-partial interface MLContext {
-  MLCommandEncoder createCommandEncoder();
-};
+interface MLGraph {};
 
 enum MLInputOperandLayout {
   "nchw",
@@ -89,6 +67,50 @@
 [SecureContext, Exposed=(Window, DedicatedWorker)]
 interface MLActivation {};
 
+typedef record<DOMString, ArrayBufferView> MLNamedArrayBufferViews;
+
+[SecureContext, Exposed=(Window, DedicatedWorker)]
+interface MLContext {};
+
+partial interface MLContext {
+  [Exposed=(DedicatedWorker)]
+  undefined computeSync(
+      MLGraph graph, MLNamedArrayBufferViews inputs, MLNamedArrayBufferViews outputs);
+};
+
+dictionary MLComputeResult {
+  MLNamedArrayBufferViews inputs;
+  MLNamedArrayBufferViews outputs;
+};
+
+partial interface MLContext {
+  Promise<MLComputeResult> compute(
+      MLGraph graph, MLNamedArrayBufferViews inputs, MLNamedArrayBufferViews outputs);
+};
+
+partial interface MLContext {
+  MLCommandEncoder createCommandEncoder();
+};
+
+typedef (GPUBuffer or GPUTexture) MLGPUResource;
+
+typedef record<DOMString, MLGPUResource> MLNamedGPUResources;
+
+[SecureContext, Exposed=(Window, DedicatedWorker)]
+interface MLCommandEncoder {};
+
+partial interface MLCommandEncoder {
+  undefined initializeGraph(MLGraph graph);
+};
+
+partial interface MLCommandEncoder {
+  undefined dispatch(MLGraph graph, MLNamedGPUResources inputs, MLNamedGPUResources outputs);
+};
+
+partial interface MLCommandEncoder {
+  GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {});
+};
+
 typedef record<DOMString, MLOperand> MLNamedOperands;
 
 dictionary MLBufferResourceView {
@@ -269,9 +291,7 @@
 
 partial interface MLGraphBuilder {
   sequence<MLOperand> gru(MLOperand input, MLOperand weight, MLOperand recurrentWeight,
-
                           unsigned long steps, unsigned long hiddenSize,
-
                           optional MLGruOptions options = {});
 };
 
@@ -286,7 +306,6 @@
 partial interface MLGraphBuilder {
   MLOperand gruCell(MLOperand input, MLOperand weight, MLOperand recurrentWeight,
                     MLOperand hiddenState, unsigned long hiddenSize,
-
                     optional MLGruCellOptions options = {});
 };
 
@@ -355,9 +374,7 @@
 
 partial interface MLGraphBuilder {
   sequence<MLOperand> lstm(MLOperand input, MLOperand weight, MLOperand recurrentWeight,
-
                            unsigned long steps, unsigned long hiddenSize,
-
                            optional MLLstmOptions options = {});
 };
 
@@ -372,7 +389,6 @@
 partial interface MLGraphBuilder {
   sequence<MLOperand> lstmCell(MLOperand input, MLOperand weight, MLOperand recurrentWeight,
                                MLOperand hiddenState, MLOperand cellState, unsigned long hiddenSize,
-
                                optional MLLstmCellOptions options = {});
 };
 
@@ -524,25 +540,3 @@
 partial interface MLGraphBuilder {
   MLOperand transpose(MLOperand input, optional MLTransposeOptions options = {});
 };
-
-[SecureContext, Exposed=(Window, DedicatedWorker)]
-interface MLGraph {};
-
-typedef (GPUBuffer or GPUTexture) MLGPUResource;
-
-typedef record<DOMString, MLGPUResource> MLNamedGPUResources;
-
-[SecureContext, Exposed=(Window, DedicatedWorker)]
-interface MLCommandEncoder {};
-
-partial interface MLCommandEncoder {
-  undefined initializeGraph(MLGraph graph);
-};
-
-partial interface MLCommandEncoder {
-  undefined dispatch(MLGraph graph, MLNamedGPUResources inputs, MLNamedGPUResources outputs);
-};
-
-partial interface MLCommandEncoder {
-  GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {});
-};
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl b/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl
index 397d783..f1dca4a 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl
@@ -182,6 +182,7 @@
 };
 
 dictionary RTCAudioPlayoutStats : RTCStats {
+             required DOMString kind;
              double             synthesizedSamplesDuration;
              unsigned long      synthesizedSamplesEvents;
              double             totalSamplesDuration;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webrtc-svc.idl b/third_party/blink/web_tests/external/wpt/interfaces/webrtc-svc.idl
index e42efe0..e67ed70 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/webrtc-svc.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/webrtc-svc.idl
@@ -6,7 +6,3 @@
 partial dictionary RTCRtpEncodingParameters {
              DOMString scalabilityMode;
 };
-
-partial dictionary RTCRtpCodecCapability {
-             sequence<DOMString> scalabilityModes;
-};
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webxrlayers.idl b/third_party/blink/web_tests/external/wpt/interfaces/webxrlayers.idl
index 785a742e..e182f47 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/webxrlayers.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/webxrlayers.idl
@@ -15,7 +15,6 @@
   readonly attribute XRLayerLayout layout;
 
   attribute boolean blendTextureSourceAlpha;
-  attribute boolean? chromaticAberrationCorrection;
   attribute boolean forceMonoPresentation;
   attribute float opacity;
   readonly attribute unsigned long mipLevels;
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-fetch.h2.window.js b/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-fetch.h2.window.js
new file mode 100644
index 0000000..121913ed
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-fetch.h2.window.js
@@ -0,0 +1,10 @@
+// META: script=resources/early-hints-helpers.sub.js
+
+test(() => {
+    const preloads = [{
+        "url": "empty.json?" + Date.now(),
+        "as_attr": "fetch",
+        "crossorigin_attr": "",
+    }];
+    navigateToTestWithEarlyHints("resources/preload-fetch.html", preloads);
+});
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/early-hints-helpers.sub.js b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/early-hints-helpers.sub.js
index 3991e8f..faf6119c 100644
--- a/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/early-hints-helpers.sub.js
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/early-hints-helpers.sub.js
@@ -14,6 +14,8 @@
  * @property {string} url - A URL to preload. Note: This is relative to the
  *     `test_url` parameter of `navigateToTestWithEarlyHints()`.
  * @property {string} as_attr - `as` attribute of this preload.
+ * @property {string} [crossorigin_attr] - `crossorigin` attribute of this
+ *     preload.
  *
  * @param {string} test_url - URL of a test after the Early Hints response.
  * @param {Array<Preload>} preloads  - Preloads included in the Early Hints response.
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/early-hints-test-loader.h2.py b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/early-hints-test-loader.h2.py
index aa9188c6d..bb98720 100644
--- a/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/early-hints-test-loader.h2.py
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/early-hints-test-loader.h2.py
@@ -18,6 +18,12 @@
     for encoded_preload in request.GET.get_list(b"preloads"):
         preload = json.loads(encoded_preload.decode("utf-8"))
         header = "<{}>; rel=preload; as={}".format(preload["url"], preload["as_attr"])
+        if "crossorigin_attr" in preload:
+            crossorigin = preload["crossorigin_attr"]
+            if crossorigin:
+                header += "; crossorigin={}".format(crossorigin)
+            else:
+                header += "; crossorigin"
         preload_headers.append(header.encode())
 
     # Send a 103 response.
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/empty.json b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/empty.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/empty.json
@@ -0,0 +1 @@
+{}
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/empty.json.headers b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/empty.json.headers
new file mode 100644
index 0000000..1738466b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/empty.json.headers
@@ -0,0 +1,4 @@
+cache-control: max-age=600
+access-control-allow-origin: *
+timing-allow-origin: *
+cross-origin-resource-policy: cross-origin
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/preload-fetch.html b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/preload-fetch.html
new file mode 100644
index 0000000..2e90f76
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/resources/preload-fetch.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="early-hints-helpers.sub.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+    const preloads = getPreloadsFromSearchParams();
+    assert_equals(preloads.length, 1);
+    const preload = preloads[0];
+
+    await fetch(preload.url).then((response) => response.json());
+    const name = new URL(preload.url, window.location);
+    assert_true(isPreloadedByEarlyHints(name));
+}, "Ensure early hints preload works for fetch()");
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-axis-height-1.html.ini b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-axis-height-1.html.ini
index 35bdfeb..59bfab0 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-axis-height-1.html.ini
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-axis-height-1.html.ini
@@ -2,3 +2,6 @@
   [AxisHeight (size variant)]
     expected:
       if os == "win": FAIL
+
+  [AxisHeight (glyph assembly)]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js.ini b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js.ini
index dc57fd5..6891dad 100644
--- a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js.ini
@@ -107,7 +107,10 @@
     expected: FAIL
 
   [PaymentManager interface: existence and properties of interface object]
-    expected: FAIL
+    expected:
+      if (processor == "x86_64") and (os == "linux") and (version == "Ubuntu 18.04"): PASS
+      if (processor == "x86_64") and (os == "win"): PASS
+      FAIL
 
   [PaymentRequestEvent interface: new PaymentRequestEvent("type") must inherit property "changeShippingAddress(optional AddressInit)" with the proper type]
     expected: FAIL
@@ -133,6 +136,12 @@
   [PaymentRequestEvent interface: calling changeShippingAddress(optional AddressInit) on new PaymentRequestEvent("type") with too few arguments must throw TypeError]
     expected: FAIL
 
+  [PaymentManager interface: paymentManager must not have property "userHint"]
+    expected: FAIL
+
+  [PaymentManager interface: paymentManager must not have property "enableDelegations"]
+    expected: FAIL
+
 
 [idlharness.https.any.sharedworker.html]
   [PaymentManager interface: attribute userHint]
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.serviceworker-expected.txt
index 90e3142f..a70b18b7 100644
--- a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.serviceworker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.serviceworker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 78 tests; 42 PASS, 36 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 70 tests; 40 PASS, 30 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS Partial interface ServiceWorkerRegistration: original interface defined
@@ -9,19 +9,11 @@
 PASS Partial interface ServiceWorkerGlobalScope[2]: original interface defined
 PASS Partial interface ServiceWorkerGlobalScope[2]: member names are unique
 PASS WorkerGlobalScope includes WindowOrWorkerGlobalScope: member names are unique
-FAIL PaymentManager interface: existence and properties of interface object assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface object length assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface object name assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: attribute userHint assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: operation enableDelegations(sequence<PaymentDelegation>) assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
+PASS PaymentManager interface: existence and properties of interface object
 FAIL PaymentManager must be primary interface of paymentManager assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 PASS Stringification of paymentManager
-PASS PaymentManager interface: paymentManager must inherit property "userHint" with the proper type
-PASS PaymentManager interface: paymentManager must inherit property "enableDelegations(sequence<PaymentDelegation>)" with the proper type
-PASS PaymentManager interface: calling enableDelegations(sequence<PaymentDelegation>) on paymentManager with too few arguments must throw TypeError
+FAIL PaymentManager interface: paymentManager must not have property "userHint" assert_false: expected false got true
+FAIL PaymentManager interface: paymentManager must not have property "enableDelegations" assert_false: expected false got true
 PASS CanMakePaymentEvent interface: existence and properties of interface object
 FAIL CanMakePaymentEvent interface object length assert_equals: wrong value for CanMakePaymentEvent.length expected 1 but got 2
 PASS CanMakePaymentEvent interface object name
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.sharedworker-expected.txt
deleted file mode 100644
index 28845dfb..0000000
--- a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.sharedworker-expected.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS idl_test validation
-PASS Partial interface ServiceWorkerRegistration: original interface defined
-PASS Partial interface ServiceWorkerRegistration: member names are unique
-PASS Partial interface ServiceWorkerGlobalScope: original interface defined
-PASS Partial interface ServiceWorkerGlobalScope: member names are unique
-PASS Partial interface ServiceWorkerGlobalScope[2]: original interface defined
-PASS Partial interface ServiceWorkerGlobalScope[2]: member names are unique
-PASS WorkerGlobalScope includes WindowOrWorkerGlobalScope: member names are unique
-FAIL PaymentManager interface: existence and properties of interface object assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface object length assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface object name assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: attribute userHint assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: operation enableDelegations(sequence<PaymentDelegation>) assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-PASS CanMakePaymentEvent interface: existence and properties of interface object
-PASS PaymentRequestEvent interface: existence and properties of interface object
-PASS ServiceWorkerRegistration interface: attribute paymentManager
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.worker-expected.txt
deleted file mode 100644
index 28845dfb..0000000
--- a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.worker-expected.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS idl_test validation
-PASS Partial interface ServiceWorkerRegistration: original interface defined
-PASS Partial interface ServiceWorkerRegistration: member names are unique
-PASS Partial interface ServiceWorkerGlobalScope: original interface defined
-PASS Partial interface ServiceWorkerGlobalScope: member names are unique
-PASS Partial interface ServiceWorkerGlobalScope[2]: original interface defined
-PASS Partial interface ServiceWorkerGlobalScope[2]: member names are unique
-PASS WorkerGlobalScope includes WindowOrWorkerGlobalScope: member names are unique
-FAIL PaymentManager interface: existence and properties of interface object assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface object length assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface object name assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: attribute userHint assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: operation enableDelegations(sequence<PaymentDelegation>) assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-PASS CanMakePaymentEvent interface: existence and properties of interface object
-PASS PaymentRequestEvent interface: existence and properties of interface object
-PASS ServiceWorkerRegistration interface: attribute paymentManager
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any-expected.txt b/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any-expected.txt
index a5169a6..f86850a 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any-expected.txt
@@ -8,6 +8,12 @@
 PASS Partial interface MLContext[2]: member names are unique
 PASS Partial interface MLContext[3]: original interface defined
 PASS Partial interface MLContext[3]: member names are unique
+PASS Partial interface MLCommandEncoder: original interface defined
+PASS Partial interface MLCommandEncoder: member names are unique
+PASS Partial interface MLCommandEncoder[2]: original interface defined
+PASS Partial interface MLCommandEncoder[2]: member names are unique
+PASS Partial interface MLCommandEncoder[3]: original interface defined
+PASS Partial interface MLCommandEncoder[3]: member names are unique
 PASS Partial interface MLGraphBuilder: original interface defined
 PASS Partial interface MLGraphBuilder: member names are unique
 PASS Partial interface MLGraphBuilder[2]: original interface defined
@@ -76,12 +82,6 @@
 PASS Partial interface MLGraphBuilder[33]: member names are unique
 PASS Partial interface MLGraphBuilder[34]: original interface defined
 PASS Partial interface MLGraphBuilder[34]: member names are unique
-PASS Partial interface MLCommandEncoder: original interface defined
-PASS Partial interface MLCommandEncoder: member names are unique
-PASS Partial interface MLCommandEncoder[2]: original interface defined
-PASS Partial interface MLCommandEncoder[2]: member names are unique
-PASS Partial interface MLCommandEncoder[3]: original interface defined
-PASS Partial interface MLCommandEncoder[3]: member names are unique
 PASS Partial interface Navigator: member names are unique
 PASS Partial interface mixin NavigatorID: member names are unique
 PASS Navigator includes NavigatorML: member names are unique
@@ -120,21 +120,14 @@
 PASS ML interface: navigator.ml must inherit property "createContext(GPUDevice)" with the proper type
 PASS ML interface: calling createContext(GPUDevice) on navigator.ml with too few arguments must throw TypeError
 PASS ML interface: navigator.ml must not have property "createContextSync"
-PASS MLContext interface: existence and properties of interface object
-PASS MLContext interface object length
-PASS MLContext interface object name
-PASS MLContext interface: existence and properties of interface prototype object
-PASS MLContext interface: existence and properties of interface prototype object's "constructor" property
-PASS MLContext interface: existence and properties of interface prototype object's @@unscopables property
-PASS MLContext interface: member computeSync
-FAIL MLContext interface: operation compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) assert_own_property: interface prototype object missing non-static operation expected property "compute" missing
-FAIL MLContext interface: operation createCommandEncoder() assert_own_property: interface prototype object missing non-static operation expected property "createCommandEncoder" missing
-PASS MLContext must be primary interface of context
-PASS Stringification of context
-PASS MLContext interface: context must not have property "computeSync"
-FAIL MLContext interface: context must inherit property "compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)" with the proper type assert_inherits: property "compute" not found in prototype chain
-FAIL MLContext interface: calling compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) on context with too few arguments must throw TypeError assert_inherits: property "compute" not found in prototype chain
-FAIL MLContext interface: context must inherit property "createCommandEncoder()" with the proper type assert_inherits: property "createCommandEncoder" not found in prototype chain
+PASS MLGraph interface: existence and properties of interface object
+PASS MLGraph interface object length
+PASS MLGraph interface object name
+PASS MLGraph interface: existence and properties of interface prototype object
+PASS MLGraph interface: existence and properties of interface prototype object's "constructor" property
+PASS MLGraph interface: existence and properties of interface prototype object's @@unscopables property
+FAIL MLGraph must be primary interface of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
+FAIL Stringification of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
 PASS MLOperand interface: existence and properties of interface object
 PASS MLOperand interface object length
 PASS MLOperand interface object name
@@ -153,6 +146,30 @@
 FAIL MLActivation interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
 FAIL MLActivation interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
 FAIL MLActivation interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
+PASS MLContext interface: existence and properties of interface object
+PASS MLContext interface object length
+PASS MLContext interface object name
+PASS MLContext interface: existence and properties of interface prototype object
+PASS MLContext interface: existence and properties of interface prototype object's "constructor" property
+PASS MLContext interface: existence and properties of interface prototype object's @@unscopables property
+PASS MLContext interface: member computeSync
+FAIL MLContext interface: operation compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) assert_own_property: interface prototype object missing non-static operation expected property "compute" missing
+FAIL MLContext interface: operation createCommandEncoder() assert_own_property: interface prototype object missing non-static operation expected property "createCommandEncoder" missing
+PASS MLContext must be primary interface of context
+PASS Stringification of context
+PASS MLContext interface: context must not have property "computeSync"
+FAIL MLContext interface: context must inherit property "compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)" with the proper type assert_inherits: property "compute" not found in prototype chain
+FAIL MLContext interface: calling compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) on context with too few arguments must throw TypeError assert_inherits: property "compute" not found in prototype chain
+FAIL MLContext interface: context must inherit property "createCommandEncoder()" with the proper type assert_inherits: property "createCommandEncoder" not found in prototype chain
+FAIL MLCommandEncoder interface: existence and properties of interface object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface object length assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface object name assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: operation initializeGraph(MLGraph) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: operation dispatch(MLGraph, MLNamedGPUResources, MLNamedGPUResources) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: operation finish(optional GPUCommandBufferDescriptor) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
 PASS MLGraphBuilder interface: existence and properties of interface object
 PASS MLGraphBuilder interface object length
 PASS MLGraphBuilder interface object name
@@ -382,23 +399,6 @@
 FAIL MLGraphBuilder interface: builder must inherit property "tanh()" with the proper type assert_inherits: property "tanh" not found in prototype chain
 FAIL MLGraphBuilder interface: builder must inherit property "transpose(MLOperand, optional MLTransposeOptions)" with the proper type assert_inherits: property "transpose" not found in prototype chain
 FAIL MLGraphBuilder interface: calling transpose(MLOperand, optional MLTransposeOptions) on builder with too few arguments must throw TypeError assert_inherits: property "transpose" not found in prototype chain
-PASS MLGraph interface: existence and properties of interface object
-PASS MLGraph interface object length
-PASS MLGraph interface object name
-PASS MLGraph interface: existence and properties of interface prototype object
-PASS MLGraph interface: existence and properties of interface prototype object's "constructor" property
-PASS MLGraph interface: existence and properties of interface prototype object's @@unscopables property
-FAIL MLGraph must be primary interface of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
-FAIL Stringification of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
-FAIL MLCommandEncoder interface: existence and properties of interface object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface object length assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface object name assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation initializeGraph(MLGraph) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation dispatch(MLGraph, MLNamedGPUResources, MLNamedGPUResources) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation finish(optional GPUCommandBufferDescriptor) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
 PASS Navigator interface: attribute ml
 PASS Navigator interface: navigator must inherit property "ml" with the proper type
 Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any.worker-expected.txt
index 183b4c4..71decbd4 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any.worker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any.worker-expected.txt
@@ -8,6 +8,12 @@
 PASS Partial interface MLContext[2]: member names are unique
 PASS Partial interface MLContext[3]: original interface defined
 PASS Partial interface MLContext[3]: member names are unique
+PASS Partial interface MLCommandEncoder: original interface defined
+PASS Partial interface MLCommandEncoder: member names are unique
+PASS Partial interface MLCommandEncoder[2]: original interface defined
+PASS Partial interface MLCommandEncoder[2]: member names are unique
+PASS Partial interface MLCommandEncoder[3]: original interface defined
+PASS Partial interface MLCommandEncoder[3]: member names are unique
 PASS Partial interface MLGraphBuilder: original interface defined
 PASS Partial interface MLGraphBuilder: member names are unique
 PASS Partial interface MLGraphBuilder[2]: original interface defined
@@ -76,12 +82,6 @@
 PASS Partial interface MLGraphBuilder[33]: member names are unique
 PASS Partial interface MLGraphBuilder[34]: original interface defined
 PASS Partial interface MLGraphBuilder[34]: member names are unique
-PASS Partial interface MLCommandEncoder: original interface defined
-PASS Partial interface MLCommandEncoder: member names are unique
-PASS Partial interface MLCommandEncoder[2]: original interface defined
-PASS Partial interface MLCommandEncoder[2]: member names are unique
-PASS Partial interface MLCommandEncoder[3]: original interface defined
-PASS Partial interface MLCommandEncoder[3]: member names are unique
 PASS Partial interface Navigator: member names are unique
 PASS Partial interface mixin NavigatorID: member names are unique
 PASS Navigator includes NavigatorML: member names are unique
@@ -124,22 +124,14 @@
 PASS ML interface: calling createContextSync(optional MLContextOptions) on navigator.ml with too few arguments must throw TypeError
 PASS ML interface: navigator.ml must inherit property "createContextSync(GPUDevice)" with the proper type
 PASS ML interface: calling createContextSync(GPUDevice) on navigator.ml with too few arguments must throw TypeError
-PASS MLContext interface: existence and properties of interface object
-PASS MLContext interface object length
-PASS MLContext interface object name
-PASS MLContext interface: existence and properties of interface prototype object
-PASS MLContext interface: existence and properties of interface prototype object's "constructor" property
-PASS MLContext interface: existence and properties of interface prototype object's @@unscopables property
-FAIL MLContext interface: operation computeSync(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) assert_own_property: interface prototype object missing non-static operation expected property "computeSync" missing
-FAIL MLContext interface: operation compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) assert_own_property: interface prototype object missing non-static operation expected property "compute" missing
-FAIL MLContext interface: operation createCommandEncoder() assert_own_property: interface prototype object missing non-static operation expected property "createCommandEncoder" missing
-PASS MLContext must be primary interface of context
-PASS Stringification of context
-FAIL MLContext interface: context must inherit property "computeSync(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)" with the proper type assert_inherits: property "computeSync" not found in prototype chain
-FAIL MLContext interface: calling computeSync(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) on context with too few arguments must throw TypeError assert_inherits: property "computeSync" not found in prototype chain
-FAIL MLContext interface: context must inherit property "compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)" with the proper type assert_inherits: property "compute" not found in prototype chain
-FAIL MLContext interface: calling compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) on context with too few arguments must throw TypeError assert_inherits: property "compute" not found in prototype chain
-FAIL MLContext interface: context must inherit property "createCommandEncoder()" with the proper type assert_inherits: property "createCommandEncoder" not found in prototype chain
+PASS MLGraph interface: existence and properties of interface object
+PASS MLGraph interface object length
+PASS MLGraph interface object name
+PASS MLGraph interface: existence and properties of interface prototype object
+PASS MLGraph interface: existence and properties of interface prototype object's "constructor" property
+PASS MLGraph interface: existence and properties of interface prototype object's @@unscopables property
+FAIL MLGraph must be primary interface of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
+FAIL Stringification of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
 PASS MLOperand interface: existence and properties of interface object
 PASS MLOperand interface object length
 PASS MLOperand interface object name
@@ -158,6 +150,31 @@
 FAIL MLActivation interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
 FAIL MLActivation interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
 FAIL MLActivation interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
+PASS MLContext interface: existence and properties of interface object
+PASS MLContext interface object length
+PASS MLContext interface object name
+PASS MLContext interface: existence and properties of interface prototype object
+PASS MLContext interface: existence and properties of interface prototype object's "constructor" property
+PASS MLContext interface: existence and properties of interface prototype object's @@unscopables property
+FAIL MLContext interface: operation computeSync(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) assert_own_property: interface prototype object missing non-static operation expected property "computeSync" missing
+FAIL MLContext interface: operation compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) assert_own_property: interface prototype object missing non-static operation expected property "compute" missing
+FAIL MLContext interface: operation createCommandEncoder() assert_own_property: interface prototype object missing non-static operation expected property "createCommandEncoder" missing
+PASS MLContext must be primary interface of context
+PASS Stringification of context
+FAIL MLContext interface: context must inherit property "computeSync(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)" with the proper type assert_inherits: property "computeSync" not found in prototype chain
+FAIL MLContext interface: calling computeSync(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) on context with too few arguments must throw TypeError assert_inherits: property "computeSync" not found in prototype chain
+FAIL MLContext interface: context must inherit property "compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)" with the proper type assert_inherits: property "compute" not found in prototype chain
+FAIL MLContext interface: calling compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) on context with too few arguments must throw TypeError assert_inherits: property "compute" not found in prototype chain
+FAIL MLContext interface: context must inherit property "createCommandEncoder()" with the proper type assert_inherits: property "createCommandEncoder" not found in prototype chain
+FAIL MLCommandEncoder interface: existence and properties of interface object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface object length assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface object name assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: operation initializeGraph(MLGraph) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: operation dispatch(MLGraph, MLNamedGPUResources, MLNamedGPUResources) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
+FAIL MLCommandEncoder interface: operation finish(optional GPUCommandBufferDescriptor) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
 PASS MLGraphBuilder interface: existence and properties of interface object
 PASS MLGraphBuilder interface object length
 PASS MLGraphBuilder interface object name
@@ -388,23 +405,6 @@
 FAIL MLGraphBuilder interface: builder must inherit property "tanh()" with the proper type assert_inherits: property "tanh" not found in prototype chain
 FAIL MLGraphBuilder interface: builder must inherit property "transpose(MLOperand, optional MLTransposeOptions)" with the proper type assert_inherits: property "transpose" not found in prototype chain
 FAIL MLGraphBuilder interface: calling transpose(MLOperand, optional MLTransposeOptions) on builder with too few arguments must throw TypeError assert_inherits: property "transpose" not found in prototype chain
-PASS MLGraph interface: existence and properties of interface object
-PASS MLGraph interface object length
-PASS MLGraph interface object name
-PASS MLGraph interface: existence and properties of interface prototype object
-PASS MLGraph interface: existence and properties of interface prototype object's "constructor" property
-PASS MLGraph interface: existence and properties of interface prototype object's @@unscopables property
-FAIL MLGraph must be primary interface of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
-FAIL Stringification of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
-FAIL MLCommandEncoder interface: existence and properties of interface object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface object length assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface object name assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation initializeGraph(MLGraph) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation dispatch(MLGraph, MLNamedGPUResources, MLNamedGPUResources) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation finish(optional GPUCommandBufferDescriptor) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
 PASS WorkerNavigator interface: attribute ml
 PASS WorkerNavigator interface: navigator must inherit property "ml" with the proper type
 Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https-expected.txt
index 6920be49..5006c48 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 248 tests; 240 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 249 tests; 241 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS getStats succeeds
 PASS Validating stats
 PASS codec's payloadType
@@ -171,6 +171,7 @@
 PASS media-source's timestamp
 PASS media-source's type
 PASS media-source's id
+PASS media-playout's kind
 PASS media-playout's synthesizedSamplesDuration
 PASS media-playout's synthesizedSamplesEvents
 PASS media-playout's totalSamplesDuration
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-relay-canvas.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-relay-canvas.https.html
index 7c3c92b..78df2ee 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-relay-canvas.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-relay-canvas.https.html
@@ -14,7 +14,7 @@
   const canvas =
       Object.assign(document.createElement('canvas'), {width, height});
   const ctx = canvas.getContext('webgl');
-  if (ctx === null) return;
+  assert_not_equals(ctx, null, "webgl is a prerequisite for this test");
   requestAnimationFrame(function draw () {
     ctx.clearColor(0.0, 1.0, 0.0, 1.0);
     ctx.clear(ctx.COLOR_BUFFER_BIT);
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/transforms/transformed-document-element-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/transforms/transformed-document-element-expected.png
new file mode 100644
index 0000000..970e7c2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/transforms/transformed-document-element-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/transforms/transformed-document-element-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/transforms/transformed-document-element-expected.png
index a6feb428..970e7c2 100644
--- a/third_party/blink/web_tests/platform/mac-mac12-arm64/transforms/transformed-document-element-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/transforms/transformed-document-element-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/wpt_internal/html/rendering/non-replaced-elements/flow-content-3/dialog-top-layer.html b/third_party/blink/web_tests/wpt_internal/html/rendering/non-replaced-elements/flow-content-3/dialog-top-layer.html
new file mode 100644
index 0000000..7d404b6
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/html/rendering/non-replaced-elements/flow-content-3/dialog-top-layer.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<title>dialog: top-layer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<dialog id="dialog"></dialog>
+<script>
+  const dialog = document.getElementById("dialog");
+
+  test(() => {
+    assert_equals(getComputedStyle(dialog).topLayer, "none",
+                  "Computed top-layer");
+    // dialog::backdrop {} UA rule always sets top-layer to 'browser' even if
+    // ::backdrop pseudo is not generated. ::backdrop is only generated when the
+    // dialog is in the top layer.
+    assert_equals(getComputedStyle(dialog, "::backdrop").topLayer, "browser",
+                  "Computed top-layer for ::backdrop");
+  }, "dialog computed top-layer initially 'none'");
+
+  test(() => {
+    dialog.showModal();
+
+    assert_equals(getComputedStyle(dialog).topLayer, "browser",
+                  "Computed top-layer on open dialog");
+    assert_equals(getComputedStyle(dialog, "::backdrop").topLayer, "browser",
+                  "Computed top-layer for ::backdrop");
+
+    dialog.close();
+
+    assert_equals(getComputedStyle(dialog).topLayer, "none",
+                  "Computed top-layer on closed dialog");
+    // ::backdrop is always top-layer:browser. See comment above.
+    assert_equals(getComputedStyle(dialog, "::backdrop").topLayer, "browser",
+                  "Computed top-layer for ::backdrop");
+  }, "Opening and closing a modal dialog changes computed top-layer to 'browser' and back to 'none'");
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/html/rendering/non-replaced-elements/flow-content-3/popover-top-layer.html b/third_party/blink/web_tests/wpt_internal/html/rendering/non-replaced-elements/flow-content-3/popover-top-layer.html
new file mode 100644
index 0000000..d5c7c218d
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/html/rendering/non-replaced-elements/flow-content-3/popover-top-layer.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<title>popover: top-layer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<dialog popover id="popover-show-dialog"></dialog>
+<dialog popover id="popover-show-modal-dialog"></dialog>
+<dialog popover id="popover-dialog"></dialog>
+<div popover id="popover-div"></div>
+<script>
+  test(() => {
+    const popover_show_dialog = document.getElementById("popover-show-dialog");
+    assert_equals(getComputedStyle(popover_show_dialog).topLayer, "none",
+                  "Computed top-layer");
+    popover_show_dialog.show();
+    assert_equals(getComputedStyle(popover_show_dialog).topLayer, "none",
+                  "Computed top-layer after show()");
+    popover_show_dialog.close();
+  }, "dialog.show() should not put popover dialog in top layer");
+
+  test(() => {
+    const popover_show_modal_dialog = document.getElementById("popover-show-modal-dialog");
+    assert_equals(getComputedStyle(popover_show_modal_dialog).topLayer, "none",
+                  "Computed top-layer");
+    popover_show_modal_dialog.showModal();
+    assert_equals(getComputedStyle(popover_show_modal_dialog).topLayer, "browser",
+                  "Computed top-layer after showModal()");
+    popover_show_modal_dialog.close();
+  }, "dialog.showModal() should put popover dialog in top layer");
+
+  test(() => {
+    const popover_dialog = document.getElementById("popover-dialog");
+    assert_equals(getComputedStyle(popover_dialog).topLayer, "none",
+                  "Computed top-layer");
+    popover_dialog.showPopover();
+    assert_equals(getComputedStyle(popover_dialog).topLayer, "browser",
+                  "Computed top-layer after showPopover()");
+    popover_dialog.hidePopover();
+  }, "dialog.showPopover() should put popover dialog in top layer");
+
+  test(() => {
+    const popover_div = document.getElementById("popover-div");
+    assert_equals(getComputedStyle(popover_div).topLayer, "none",
+                  "Computed top-layer");
+    popover_div.showPopover();
+    assert_equals(getComputedStyle(popover_div).topLayer, "browser",
+                  "Computed top-layer after showPopover()");
+    popover_div.hidePopover();
+  }, "div.showPopover() should put popover div in top layer");
+</script>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 4aa1474..12e3f6f 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -63834,6 +63834,7 @@
   <int value="1474433736" label="NtpRealboxTailSuggest:enabled"/>
   <int value="1474861626" label="disable-multi-mirroring"/>
   <int value="1475210901" label="AvatarToolbarButton:disabled"/>
+  <int value="1475771788" label="BackgroundResourceFetch:enabled"/>
   <int value="1478075250" label="QuickAnswersTextAnnotator:disabled"/>
   <int value="1478461926" label="GlobalMediaControlsPictureInPicture:enabled"/>
   <int value="1479248574" label="disable-voice-input"/>
@@ -64521,6 +64522,7 @@
   <int value="1870973833" label="AssistantEnableStereoAudioInput:enabled"/>
   <int value="1871938175" label="FontSrcLocalMatching:disabled"/>
   <int value="1872185826" label="LocationHardReload:enabled"/>
+  <int value="1872768755" label="BackgroundResourceFetch:disabled"/>
   <int value="1873688130"
       label="ExperimentalAccessibilityDictationMoreCommands:disabled"/>
   <int value="1874050287" label="UploadOfficeToCloud:enabled"/>
@@ -83786,6 +83788,20 @@
   <int value="3" label="Prerender hit finished"/>
 </enum>
 
+<enum name="PrerenderProcessTerminationStatus">
+  <int value="0" label="kNormalTermination"/>
+  <int value="1" label="kAbnormalTermination"/>
+  <int value="2" label="kProcessWasKilled"/>
+  <int value="3" label="kProcessCrashed"/>
+  <int value="4" label="kStillRunning"/>
+  <int value="5" label="kProcessWasKilledByOom"/>
+  <int value="6" label="kOomProtected"/>
+  <int value="7" label="kLaunchFailed"/>
+  <int value="8" label="kOom"/>
+  <int value="9" label="kIntegrityFailure"/>
+  <int value="10" label="kInvalid"/>
+</enum>
+
 <enum name="PrerenderRelTypes">
   <int value="0" label="PRERENDER_REL_TYPE_NONE"/>
   <int value="1" label="PRERENDER_REL_TYPE_PRERENDER"/>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml
index 1c9cc04..aec9639 100644
--- a/tools/metrics/histograms/metadata/chromeos/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -1381,7 +1381,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Intents.IntentPickerAction.From{LaunchSource}"
-    enum="IntentPickerDialogAction" expires_after="2023-02-19">
+    enum="IntentPickerDialogAction" expires_after="2023-05-19">
   <owner>tsergeant@chromium.org</owner>
   <owner>chromeos-apps-foundation-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index 099b85c..bf6dd8cf 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -1653,6 +1653,20 @@
   </summary>
 </histogram>
 
+<histogram
+    name="Prerender.Experimental.KilledPrerenderProcessTerminationStatus{PrerenderTriggerType}"
+    enum="PrerenderProcessTerminationStatus" expires_after="2023-06-05">
+  <owner>lingqi@chromium.org</owner>
+  <owner>nhiroki@chromium.org</owner>
+  <summary>
+    This is a breakdown metric for
+    PrerenderHostFinalStatus::kRendererProcessKilled. Recorded by
+    PrerenderCancellationReason to track the detailed termination status when a
+    prerender is cancelled with this final status.
+  </summary>
+  <token key="PrerenderTriggerType" variants="PrerenderTriggerType"/>
+</histogram>
+
 <histogram name="Prerender.Experimental.PredictionStatus.DefaultSearchEngine"
     enum="PrerenderPredictionStatus" expires_after="2023-06-18">
   <owner>asamidoi@chromium.org</owner>
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index d9ce2b5..90473a4 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -47,6 +47,10 @@
 crbug.com/966613 [ android-pixel-2 ] blink_perf.parser/query-selector-all-class-deep.html [ Skip ]
 crbug.com/966613 [ android-pixel-2 ] blink_perf.parser/query-selector-all-deep.html [ Skip ]
 crbug.com/966613 [ android-pixel-2 ] blink_perf.parser/query-selector-all-id-deep.html [ Skip ]
+crbug.com/1411124 [ android ] blink_perf.parser/simple-url.html [ Skip ]
+crbug.com/1411124 [ android ] blink_perf.parser/url-parser.html [ Skip ]
+crbug.com/1411124 [ linux ] blink_perf.parser/simple-url.html [ Skip ]
+crbug.com/1411124 [ linux ] blink_perf.parser/url-parser.html [ Skip ]
 
 # Benchmark: blink_perf.svg
 crbug.com/846061 [ win ] blink_perf.svg/SierpinskiCarpet.html [ Skip ]
diff --git a/ui/file_manager/file_manager/BUILD.gn b/ui/file_manager/file_manager/BUILD.gn
index 9adb3a0..7745e041 100644
--- a/ui/file_manager/file_manager/BUILD.gn
+++ b/ui/file_manager/file_manager/BUILD.gn
@@ -74,7 +74,6 @@
     "foreground/images/files/ui/ms365.svg",
     "foreground/images/files/ui/nudge_star_icon.svg",
     "foreground/images/files/ui/offline.svg",
-    "foreground/images/files/ui/offline_outlined.svg",
     "foreground/images/files/ui/refresh.svg",
     "foreground/images/files/ui/restore.svg",
     "foreground/images/files/ui/search.svg",
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css
index dc2b0dd8..1001fd1 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -1319,17 +1319,7 @@
   position: relative;
 }
 
-#list-container.thumbnail-view .inline-status {
-  align-items: center;
-  display: none;
-  height: 16px;
-  justify-content: center;
-  position: absolute;
-  right: 4px;
-  top: 4px;
-  width: 16px;
-}
-
+#list-container.thumbnail-view .inline-status,
 #list-container.thumbnail-view .inline-status .progress,
 #list-container.thumbnail-view .inline-status xf-icon {
   display: none;
@@ -1337,8 +1327,12 @@
   width: 16px;
 }
 
-#list-container.thumbnail-view .inline-status xf-icon[type^=offline] {
-  --xf-icon-color: var(--cros-icon-color-secondary);
+#list-container.thumbnail-view .inline-status {
+  align-items: center;
+  justify-content: center;
+  position: absolute;
+  right: 4px;
+  top: 4px;
 }
 
 #list-container.thumbnail-view li.directory .inline-status {
@@ -1346,12 +1340,23 @@
   top: 0;
 }
 
-#list-container.thumbnail-view li:not([renaming]):not(.dim-offline) .inline-status:has(xf-icon[type^=offline]),
-#list-container.thumbnail-view li:not([renaming]):not(.dim-offline) .inline-status xf-icon[type^=offline],
+#list-container.thumbnail-view li.pinned:not([renaming]):not(.dim-offline) .inline-status,
+#list-container.thumbnail-view li.pinned:not([renaming]):not(.dim-offline) .inline-status xf-icon,
 #list-container.thumbnail-view li:not([renaming]):is([data-sync-status=in_progress], [data-sync-status=queued]) .inline-status,
 #list-container.thumbnail-view li:not([renaming]):is([data-sync-status=in_progress], [data-sync-status=queued]) .inline-status .progress {
   display: flex;
 }
+
+#list-container.thumbnail-view li.pinned .inline-status xf-icon[type=offline] {
+  --xf-icon-color: var(--cros-icon-color-secondary);
+}
+
+/* Only display outlines for entries with thumbnails. */
+#list-container.thumbnail-view li.pinned:has(.thumbnail) .inline-status .progress,
+#list-container.thumbnail-view li.pinned:has(.thumbnail) .inline-status xf-icon[type=offline] {
+  --xf-icon-color-outline: var(--cros-bg-color);
+}
+
 html:not(.pointer-active) body[type='full-page'] .thumbnail-frame > .img-container,
 body[type='full-page'] .thumbnail-frame > .img-container:active,
 html:not(.pointer-active) body[type='full-page'] .detail-name .detail-icon,
@@ -2253,14 +2258,7 @@
   width: 32px;
 }
 
-#list-container .list .inline-status {
-  align-items: center;
-  display: none;
-  height: 16px;
-  justify-content: center;
-  width: 16px;
-}
-
+#list-container .list .inline-status,
 #list-container .list .inline-status .progress,
 #list-container .list .inline-status xf-icon {
   display: none;
@@ -2268,17 +2266,22 @@
   width: 16px;
 }
 
-#list-container .list .inline-status xf-icon:is([type=offline]) {
-  --xf-icon-color: var(--cros-icon-color-secondary);
+#list-container .list .inline-status {
+  align-items: center;
+  justify-content: center;
 }
 
-#list-container .list li:not([renaming]):not(.dim-offline) .inline-status:has(xf-icon[type=offline]),
-#list-container .list li:not([renaming]):not(.dim-offline) .inline-status xf-icon[type=offline],
+#list-container .list li.pinned:not([renaming]):not(.dim-offline) .inline-status,
+#list-container .list li.pinned:not([renaming]):not(.dim-offline) .inline-status xf-icon,
 #list-container .list li:not([renaming]):is([data-sync-status=in_progress], [data-sync-status=queued]) .inline-status,
 #list-container .list li:not([renaming]):is([data-sync-status=in_progress], [data-sync-status=queued]) .inline-status .progress {
   display: flex;
 }
 
+#list-container .list li.pinned .inline-status xf-icon[type=offline] {
+  --xf-icon-color: var(--cros-icon-color-secondary);
+}
+
 #new-folder-button {
   flex: none;
 }
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css b/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
index 7395283..1d6281b 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
@@ -1272,17 +1272,7 @@
   position: relative;
 }
 
-#list-container.thumbnail-view .inline-status {
-  align-items: center;
-  display: none;
-  height: 16px;
-  justify-content: center;
-  position: absolute;
-  right: 4px;
-  top: 4px;
-  width: 16px;
-}
-
+#list-container.thumbnail-view .inline-status,
 #list-container.thumbnail-view .inline-status .progress,
 #list-container.thumbnail-view .inline-status xf-icon {
   display: none;
@@ -1290,8 +1280,12 @@
   width: 16px;
 }
 
-#list-container.thumbnail-view .inline-status xf-icon[type^=offline] {
-  --xf-icon-color: var(--cros-icon-color-secondary);
+#list-container.thumbnail-view .inline-status {
+  align-items: center;
+  justify-content: center;
+  position: absolute;
+  right: 4px;
+  top: 4px;
 }
 
 #list-container.thumbnail-view li.directory .inline-status {
@@ -1299,13 +1293,23 @@
   top: 0;
 }
 
-#list-container.thumbnail-view li:not([renaming]):not(.dim-offline) .inline-status:has(xf-icon[type^=offline]),
-#list-container.thumbnail-view li:not([renaming]):not(.dim-offline) .inline-status xf-icon[type^=offline],
+#list-container.thumbnail-view li.pinned:not([renaming]):not(.dim-offline) .inline-status,
+#list-container.thumbnail-view li.pinned:not([renaming]):not(.dim-offline) .inline-status xf-icon,
 #list-container.thumbnail-view li:not([renaming]):is([data-sync-status=in_progress], [data-sync-status=queued]) .inline-status,
 #list-container.thumbnail-view li:not([renaming]):is([data-sync-status=in_progress], [data-sync-status=queued]) .inline-status .progress {
   display: flex;
 }
 
+#list-container.thumbnail-view li.pinned .inline-status xf-icon[type=offline] {
+  --xf-icon-color: var(--cros-icon-color-secondary);
+}
+
+/* Only display outlines for entries with thumbnails. */
+#list-container.thumbnail-view li.pinned:has(.thumbnail) .inline-status .progress,
+#list-container.thumbnail-view li.pinned:has(.thumbnail) .inline-status xf-icon[type=offline] {
+  --xf-icon-color-outline: var(--cros-bg-color);
+}
+
 html:not(.pointer-active) body[type='full-page'] .thumbnail-frame > .img-container,
 body[type='full-page'] .thumbnail-frame > .img-container:active,
 html:not(.pointer-active) body[type='full-page'] .detail-name .detail-icon,
@@ -2181,14 +2185,7 @@
   width: 32px;
 }
 
-#list-container .list .inline-status {
-  align-items: center;
-  display: none;
-  height: 16px;
-  justify-content: center;
-  width: 16px;
-}
-
+#list-container .list .inline-status,
 #list-container .list .inline-status .progress,
 #list-container .list .inline-status xf-icon {
   display: none;
@@ -2196,17 +2193,22 @@
   width: 16px;
 }
 
-#list-container .list .inline-status xf-icon[type=offline] {
-  --xf-icon-color: var(--cros-icon-color-secondary);
+#list-container .list .inline-status {
+  align-items: center;
+  justify-content: center;
 }
 
-#list-container .list li:not([renaming]):not(.dim-offline) .inline-status:has(xf-icon[type=offline]),
-#list-container .list li:not([renaming]):not(.dim-offline) .inline-status xf-icon[type=offline],
+#list-container .list li.pinned:not([renaming]):not(.dim-offline) .inline-status,
+#list-container .list li.pinned:not([renaming]):not(.dim-offline) .inline-status xf-icon,
 #list-container .list li:not([renaming]):is([data-sync-status=in_progress], [data-sync-status=queued]) .inline-status,
 #list-container .list li:not([renaming]):is([data-sync-status=in_progress], [data-sync-status=queued]) .inline-status .progress {
   display: flex;
 }
 
+#list-container .list li.pinned .inline-status xf-icon[type=offline] {
+  --xf-icon-color: var(--cros-icon-color-secondary);
+}
+
 #new-folder-button {
   flex: none;
 }
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/offline.svg b/ui/file_manager/file_manager/foreground/images/files/ui/offline.svg
index c78803a..57098ab 100644
--- a/ui/file_manager/file_manager/foreground/images/files/ui/offline.svg
+++ b/ui/file_manager/file_manager/foreground/images/files/ui/offline.svg
@@ -1,5 +1,6 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" fill="none">
-  <g fill="black">
+<svg id="offline" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" fill="none">
+  <circle cx="8" cy="8" r="6.9" fill="#fff" stroke="#fff" />
+  <g fill="var(--xf-icon-color)">
     <path
       d="M9.529 4.995a.667.667 0 11.942.943L7.805 8.605a.667.667 0 01-.943 0L5.529 7.27a.667.667 0 11.942-.942l.862.862L9.53 4.995zM5.4 9.6a.6.6 0 000 1.2h5.2a.6.6 0 000-1.2H5.4z" />
     <path fill-rule="evenodd" clip-rule="evenodd"
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/offline_outlined.svg b/ui/file_manager/file_manager/foreground/images/files/ui/offline_outlined.svg
deleted file mode 100644
index a7f37e6f..0000000
--- a/ui/file_manager/file_manager/foreground/images/files/ui/offline_outlined.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<svg id="offline_outlined" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" fill="none">
-  <circle cx="8" cy="8" r="6.9" fill="#fff" stroke="#fff" />
-  <g fill="var(--xf-icon-color)">
-    <path
-      d="M9.529 4.995a.667.667 0 11.942.943L7.805 8.605a.667.667 0 01-.943 0L5.529 7.27a.667.667 0 11.942-.942l.862.862L9.53 4.995zM5.4 9.6a.6.6 0 000 1.2h5.2a.6.6 0 000-1.2H5.4z" />
-    <path fill-rule="evenodd" clip-rule="evenodd"
-      d="M14.4 8A6.4 6.4 0 111.6 8a6.4 6.4 0 0112.8 0zm-1.6 0a4.8 4.8 0 11-9.6 0 4.8 4.8 0 019.6 0z" />
-  </g>
-</svg>
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_grid.js b/ui/file_manager/file_manager/foreground/js/ui/file_grid.js
index 2972650..32bca8b 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_grid.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_grid.js
@@ -265,8 +265,6 @@
           this.setGenericThumbnail_(
               assertInstanceof(box, HTMLDivElement), entry, mimeType);
         } else {
-          listItem.querySelector('xf-icon').type =
-              this.getOfflineIconForEntry(entry, true);
           FileGrid.setThumbnailImage_(
               assertInstanceof(box, HTMLDivElement), entry,
               assert(event.dataUrl), assert(event.width), assert(event.height),
@@ -745,14 +743,12 @@
       this.decorateThumbnailBox_(listItem, entry);
       this.updateSharedStatus_(listItem, entry);
       this.updateInlineSyncStatus_(listItem, entry);
-      const metadata =
-          this.metadataModel_.getCache([entry], ['availableOffline'])[0];
-      if (metadata) {
-        const {availableOffline} = metadata;
-        listItem.classList.toggle('dim-offline', availableOffline === false);
-        listItem.querySelector('xf-icon').type =
-            this.getOfflineIconForEntry(entry);
-      }
+      const {availableOffline, pinned} =
+          this.metadataModel_.getCache(
+              [entry], ['availableOffline', 'pinned'])[0] ||
+          {};
+      listItem.classList.toggle('dim-offline', availableOffline === false);
+      listItem.classList.toggle('pinned', pinned);
       listItem.toggleAttribute(
           'disabled',
           filelist.isDlpBlocked(
@@ -804,12 +800,15 @@
 
     const bottom = li.ownerDocument.createElement('div');
     bottom.className = 'thumbnail-bottom';
-    const mimeType =
-        this.metadataModel_.getCache([entry], ['contentMimeType'])[0]
-            .contentMimeType;
+
+    const {contentMimeType, availableOffline, pinned} =
+        this.metadataModel_.getCache(
+            [entry], ['contentMimeType', 'availableOffline', 'pinned'])[0] ||
+        {};
+
     const locationInfo = this.volumeManager_.getLocationInfo(entry);
     const detailIcon = filelist.renderFileTypeIcon(
-        li.ownerDocument, entry, locationInfo, mimeType);
+        li.ownerDocument, entry, locationInfo, contentMimeType);
 
     // For FilesNg we add the checkmark in the same location.
     const checkmark = li.ownerDocument.createElement('div');
@@ -821,30 +820,26 @@
     frame.appendChild(bottom);
     li.setAttribute('file-name', util.getEntryLabel(locationInfo, entry));
 
-    const syncStatus = li.ownerDocument.createElement('div');
-    syncStatus.className = 'inline-status';
+    // The inline status box contains both sync status indicators and available
+    // offline indicators.
+    const inlineStatus = li.ownerDocument.createElement('div');
+    inlineStatus.className = 'inline-status';
 
     const inlineStatusIcon = li.ownerDocument.createElement('xf-icon');
     inlineStatusIcon.size = 'extra_small';
-    inlineStatusIcon.type = '';
-    syncStatus.appendChild(inlineStatusIcon);
+    inlineStatusIcon.type = 'offline';
+    inlineStatus.appendChild(inlineStatusIcon);
 
     if (util.isInlineSyncStatusEnabled()) {
       const syncProgress = li.ownerDocument.createElement('xf-pie-progress');
-      syncProgress.drawBackground = true;
       syncProgress.className = 'progress';
-      syncStatus.appendChild(syncProgress);
+      inlineStatus.appendChild(syncProgress);
     }
 
-    frame.appendChild(syncStatus);
+    frame.appendChild(inlineStatus);
 
-    const metadata =
-        this.metadataModel_.getCache([entry], ['availableOffline'])[0];
-    if (metadata) {
-      const {availableOffline} = metadata;
-      li.classList.toggle('dim-offline', availableOffline === false);
-      inlineStatusIcon.type = this.getOfflineIconForEntry(entry);
-    }
+    li.classList.toggle('dim-offline', availableOffline === false);
+    li.classList.toggle('pinned', pinned);
 
     if (entry) {
       this.decorateThumbnailBox_(assertInstanceof(li, HTMLLIElement), entry);
@@ -854,23 +849,6 @@
   }
 
   /**
-   * @param {Entry} entry
-   * @param {boolean} useOutline Whether the icon whose identifier is returned
-   *     should have an outline around it.
-   * @returns string
-   */
-  getOfflineIconForEntry(entry, useOutline = false) {
-    const metadata = this.metadataModel_.getCache([entry], ['pinned'])[0];
-    if (!metadata) {
-      return;
-    }
-    return metadata.pinned ?
-        // TODO: use "XfIcon.types.OFFLINE*" instead when converting to TS.
-        useOutline ? 'offline_outlined' : 'offline' :
-        '';
-  }
-
-  /**
    * Decorates the box containing a centered thumbnail image.
    *
    * @param {!HTMLLIElement} li List item which contains the box to be
@@ -896,8 +874,6 @@
         this.metadataModel_.getCache([entry], ['contentMimeType'])[0]
             .contentMimeType;
     if (thumbnailData && thumbnailData.dataUrl) {
-      li.querySelector('xf-icon').type =
-          this.getOfflineIconForEntry(entry, true);
       FileGrid.setThumbnailImage_(
           box, entry, thumbnailData.dataUrl, (thumbnailData.width || 0),
           (thumbnailData.height || 0), mimeType);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js
index 92d41da..216de29a9 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js
@@ -473,26 +473,26 @@
 };
 
 /**
- * Renders the inline status in the detail table.
+ * Renders the drive inline status in the detail table.
  * @return {!HTMLDivElement} Created element.
  */
 filelist.renderInlineStatus = (doc) => {
-  const icon = /** @type {!HTMLDivElement} */ (doc.createElement('div'));
-  icon.className = 'inline-status';
-  icon.setAttribute('aria-label', str('OFFLINE_COLUMN_LABEL'));
+  const iconDiv = /** @type {!HTMLDivElement} */ (doc.createElement('div'));
+  iconDiv.className = 'inline-status';
+  iconDiv.setAttribute('aria-label', str('OFFLINE_COLUMN_LABEL'));
 
   const inlineStatusIcon = doc.createElement('xf-icon');
   inlineStatusIcon.size = 'extra_small';
-  inlineStatusIcon.type = '';
-  icon.appendChild(inlineStatusIcon);
+  inlineStatusIcon.type = 'offline';
+  iconDiv.appendChild(inlineStatusIcon);
 
   if (util.isInlineSyncStatusEnabled()) {
     const syncProgress = doc.createElement('xf-pie-progress');
     syncProgress.className = 'progress';
-    icon.appendChild(syncProgress);
+    iconDiv.appendChild(syncProgress);
   }
 
-  return icon;
+  return iconDiv;
 };
 
 /**
@@ -513,11 +513,7 @@
     }
   }
 
-  const inlineStatusIcon = li.querySelector('.inline-status xf-icon');
-  if (inlineStatusIcon) {
-    // TODO: use "XfIcon.types.OFFLINE*" instead when converting to TS.
-    inlineStatusIcon.type = externalProps.pinned ? 'offline' : '';
-  }
+  li.classList.toggle('pinned', externalProps.pinned);
 
   const iconDiv = li.querySelector('.detail-icon');
   if (!iconDiv) {
diff --git a/ui/file_manager/file_manager/widgets/xf_icon.ts b/ui/file_manager/file_manager/widgets/xf_icon.ts
index 6374df6..d418aab 100644
--- a/ui/file_manager/file_manager/widgets/xf_icon.ts
+++ b/ui/file_manager/file_manager/widgets/xf_icon.ts
@@ -8,7 +8,10 @@
 
 @customElement('xf-icon')
 export class XfIcon extends XfBase {
-  /** The icon size, can be "small" or "large" (from `XfIcon.size`). */
+  /**
+   * The icon size, can be "extra-small", "small" or "large" (from
+   * `XfIcon.size`).
+   */
   @property({type: String, reflect: true}) size: string = XfIcon.sizes.SMALL;
 
   /**
@@ -88,14 +91,13 @@
       VIDEO: 'video',
       WORD: 'word',
       OFFLINE: 'offline',
-      OFFLINE_OUTLINED: 'offline_outlined',
     };
   }
 
   static get multiColor() {
     return {
-      [XfIcon.types.OFFLINE_OUTLINED]:
-          svg`<use xlink:href="foreground/images/files/ui/offline_outlined.svg#offline_outlined"></use>`,
+      [XfIcon.types.OFFLINE]:
+          svg`<use xlink:href="foreground/images/files/ui/offline.svg#offline"></use>`,
     };
   }
 
diff --git a/ui/file_manager/file_manager/widgets/xf_pie_progress.ts b/ui/file_manager/file_manager/widgets/xf_pie_progress.ts
index 09856e5..715eff5d 100644
--- a/ui/file_manager/file_manager/widgets/xf_pie_progress.ts
+++ b/ui/file_manager/file_manager/widgets/xf_pie_progress.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {css, customElement, html, nothing, property, svg, XfBase} from './xf_base.js';
+import {css, customElement, html, property, svg, XfBase} from './xf_base.js';
 
 const TWO_PI = 2.0 * Math.PI;
 const HALF_PI = 0.5 * Math.PI;
@@ -16,20 +16,15 @@
   // This should be a number between 0 and 1.
   @property({type: Number, reflect: true}) progress = 0;
 
-  // Whether a background should be drawn around the indicator
-  // (currently used to draw it over images).
-  @property({type: Boolean, attribute: 'draw-background', reflect: true})
-  drawBackground = 0;
-
   private size = 16;  // Size of the SVG square measured by its side length.
   private center = this.size / 2.0;  // Center of the pie circle (both X and Y).
   private radius = 5.4;              // Radius of the pie circle.
 
-  private backgroundShape = svg`<circle
+  private outlineShape = svg`<circle
+    class="outline"
     cx="${this.center}"
     cy="${this.center}"
     r="${this.center}"
-    fill="#fff"
   />`;
   private queuedShape = svg`<circle
       class="queued"
@@ -99,7 +94,7 @@
 
     return html`
       <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}">
-        ${this.drawBackground ? this.backgroundShape : nothing} ${contents}
+        ${this.outlineShape} ${contents}
       </svg>
     `;
   }
@@ -129,5 +124,9 @@
       fill: var(--cros-icon-color-prominent);
       stroke: none;
     }
+
+    .outline {
+      fill: var(--xf-icon-color-outline, transparent);
+    }
   `;
 }
diff --git a/ui/file_manager/integration_tests/file_manager/drive_specific.js b/ui/file_manager/integration_tests/file_manager/drive_specific.js
index 573e3d6..bac8e36 100644
--- a/ui/file_manager/integration_tests/file_manager/drive_specific.js
+++ b/ui/file_manager/integration_tests/file_manager/drive_specific.js
@@ -339,11 +339,11 @@
   await remoteCall.waitForElement(appId, '#file-context-menu[hidden]');
 
   // Wait for the pinned action to finish, it's flagged in the file list by
-  // removing CSS class "dim-offline" and displaying the offline icon.
+  // removing CSS class "dim-offline" and adding class "pinned".
   await remoteCall.waitForElementLost(
       appId, '#file-list .dim-offline[file-name="world.ogv"]');
   await remoteCall.waitForElement(
-      appId, '#file-list [file-name="world.ogv"] xf-icon[type=offline]');
+      appId, '#file-list .pinned[file-name="world.ogv"] .inline-status');
 
   // Select world.ogv by itself.
   await remoteCall.waitAndClickElement(
@@ -407,16 +407,15 @@
   await remoteCall.waitForElement(appId, '#file-context-menu[hidden]');
 
   // Wait for the pinned action to finish, it's flagged in the file list by
-  // removing CSS class "dim-offline" and displaying the offline icon.
+  // removing CSS class "dim-offline" and adding class "pinned".
   await remoteCall.waitForElementLost(
       appId, '#file-list .dim-offline[file-name="hello.txt"]');
   await remoteCall.waitForElement(
-      appId, '#file-list [file-name="hello.txt"] xf-icon[type=offline]');
+      appId, '#file-list .pinned[file-name="hello.txt"] .inline-status');
 
   // Test Document.gdoc should not be pinned however.
   await remoteCall.waitForElement(
-      appId,
-      '#file-list [file-name="Test Document.gdoc"] xf-icon:not([type=offline])');
+      appId, '#file-list [file-name="Test Document.gdoc"]:not(.pinned)');
 
 
   // Open the context menu with both files selected.
@@ -469,7 +468,7 @@
   // Check: File is pinned.
   await remoteCall.waitForElement(appId, '[command="#toggle-pinned"][checked]');
   await remoteCall.waitForElement(
-      appId, '#file-list [file-name="hello.txt"] xf-icon[type=offline]');
+      appId, '#file-list .pinned[file-name="hello.txt"] .inline-status');
   await waitForNotification('disabled-mobile-sync');
   await sendTestMessage({
     name: 'clickNotificationButton',
@@ -681,7 +680,7 @@
 
   // Wait for the file to be pinned.
   await remoteCall.waitForElement(
-      appId, '#file-list [file-name="hello.txt"] xf-icon[type=offline]');
+      appId, '#file-list .pinned[file-name="hello.txt"]');
 
   // Check the "Available Offline" toggle is enabled and checked.
   await remoteCall.waitForElement(
@@ -1266,3 +1265,36 @@
   chrome.test.assertEq(1, await getUserActionCount(userActionDismiss));
   await remoteCall.waitForElement(appId, 'google-one-offer-banner[hidden]');
 };
+
+/**
+ * Test that when files get deleted locally, they get unpinned prior to being
+ * deleted.
+ */
+testcase.driveLocalDeleteUnpinsItem = async () => {
+  const appId = await setupAndWaitUntilReady(RootPath.DRIVE);
+
+  // Select test.txt which is already pinned.
+  await remoteCall.waitAndClickElement(
+      appId, '#file-list [file-name="test.txt"]');
+  await remoteCall.waitForElement(
+      appId, '[file-name="test.txt"][selected] xf-icon[type=offline]');
+
+  // Ensure the metadata for the file is set to pinned.
+  await remoteCall.expectDriveItemPinnedStatus(appId, '/root/test.txt', true);
+
+  // Delete the file and ensure it disappears from the file list.
+  await remoteCall.waitAndClickElement(
+      appId, '#delete-button:not([hidden]):not([disabled])');
+  // Check: the delete confirm dialog should appear.
+  await remoteCall.waitForElement(appId, '.cr-dialog-container.shown');
+
+  // Click the delete confirm dialog 'Delete' button.
+  const dialogDeleteButton =
+      await remoteCall.waitAndClickElement(appId, '.cr-dialog-ok');
+
+  await remoteCall.waitForElementLost(
+      appId, '#file-list [file-name="test.txt"]');
+
+  // Ensure the file was unpinned prior to deleting.
+  await remoteCall.expectDriveItemPinnedStatus(appId, '/root/test.txt', false);
+};
diff --git a/ui/file_manager/integration_tests/remote_call.js b/ui/file_manager/integration_tests/remote_call.js
index a924691..4199ec8 100644
--- a/ui/file_manager/integration_tests/remote_call.js
+++ b/ui/file_manager/integration_tests/remote_call.js
@@ -981,4 +981,21 @@
     // Wait the OPEN button to have multiple tasks.
     await this.waitAndClickElement(appId, '#tasks[multiple]');
   }
+
+  /**
+   * Check if an item is pinned on drive or not.
+   * @param {string} appId app window ID.
+   * @param {string} path Path from the drive mount point, e.g. /root/test.txt
+   * @param {boolean} status Pinned status to expect drive item to be.
+   */
+  async expectDriveItemPinnedStatus(appId, path, status) {
+    await this.waitFor('isFileManagerLoaded', appId, true);
+    chrome.test.assertEq(
+        await sendTestMessage({
+          appId,
+          name: 'isItemPinned',
+          path,
+        }),
+        String(status));
+  }
 }