diff --git a/DEPS b/DEPS
index 1c0ca03..e33635c 100644
--- a/DEPS
+++ b/DEPS
@@ -280,15 +280,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '8b21825fa22f1eaf90210d75040b0709f19c6a4b',
+  'skia_revision': '1aea90338109cdc5735ffef278ffb3385ef8a70b',
   # 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': 'a55b91fbdb006f991fa7cae31bec25636025bdb0',
+  'v8_revision': 'fe995cabdb32c7e8e281587e975a3a0efacac57a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '0bc70e96e465bd194163a15ca2f52e2cacb91e4a',
+  'angle_revision': '878bbfaac0b3e96256b5dd30ba25b36f732b1223',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -331,7 +331,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': 'd9b8a69e9a8ba5ac999e721d50c231fe2e01d0bd',
+  'freetype_revision': 'f7daf9d293c00cbb80c9f7bf4dc93717464a80e8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -359,7 +359,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '591021cc31e57e105e9e8e8d2335874d0e8d5bcc',
+  'devtools_frontend_revision': 'e56829e016c746b98dbf0b493be39caadb7caae5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -395,7 +395,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.
-  'dawn_revision': 'e6882752cedd0b0b6445341f1e2d8c5b71ec1a9a',
+  'dawn_revision': '35199a30ae9294dd446f5ae64dbec894c48d3061',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -756,7 +756,7 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + '43b7efb5acffcb3435068a132f4256bdc4b66319',
+    'url': Var('chromium_git') + '/website.git' + '@' + '4d915d5194f841f7dc7c59ef79999cdfa5850994',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -850,7 +850,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/linux-amd64',
-          'version': 'Ny0rLrb6U7JOdlkpb6FfHYN_rhOyV5Csa1DrN51H4QwC',
+          'version': 'kIhGWkaoZm4VXnUb3a3ZepgEY5u6q3km9g7qppKR-KsC',
         },
       ],
       'dep_type': 'cipd',
@@ -861,7 +861,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': '6MJ-RoCrC50D9MFO9ZufcwSi7rqv-meRWsaHUj4XsEoC',
+          'version': 'CoTzix2BjelVe-VqJIPykiTNxIFMxUWQM_jGDNgAtZUC',
         },
       ],
       'dep_type': 'cipd',
@@ -872,7 +872,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/windows-amd64',
-          'version': 'ilvn4YJmvz8JirE6os-hFzIzU9lgURt9ZtnDWhQmL0YC',
+          'version': '9YP7Brw6SgiYG2ienUS8m74N0Yx06INKKHMVA0DuM_wC',
         },
       ],
       'dep_type': 'cipd',
@@ -1673,7 +1673,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@4ede36c4734b36032b0b0c64c7f4cb63c9d35293',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@45c701a7067deb732a58783239ed11fbc81cc3c7',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1712,7 +1712,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'f8000b0ea82de00b3cc7d337e7521d1e94fed587',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '74fca5ae3a2a4911328d569a12cc95389340ce59',
+    Var('webrtc_git') + '/src.git' + '@' + '130f2fd5c32aaf75626d45a738b2eb5e4f0402bf',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1785,7 +1785,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0cab979b6c47c39b30d5b95a55e00b774f9c8690',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8eceb6be10b12833a0ed5f543082b86da8b6edac',
     'condition': 'checkout_src_internal',
   },
 
@@ -1815,7 +1815,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'MC_bL-72xk0MmdqHhce_Zh8jLeDXjezLfxaeiuCVw1AC',
+        'version': 'F_Jjap09rFgtT7FmPn1Qs2cg4r9oVX24250dOUdWL8UC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1826,7 +1826,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': '-c1ZVHE8qPcsdQA_jkOnS6KUPrGX_Er0M0sRIIUGB-AC',
+        'version': 'mlV9qV8KTBiR2jTWlE3qXzl7Tfxtz3t6bGGWidVHcfgC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1837,7 +1837,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'ZNsS18Te1rjnFbIwAz4lN4c8uzSUbI-2t8JwBdb2rjQC',
+        'version': 'ZDP7ceZCjt1GrkBWuLQDQXByndtITogTIcyY3_FqKB8C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/strings/ash_strings_am.xtb b/ash/strings/ash_strings_am.xtb
index 027cc98..df27fb5 100644
--- a/ash/strings/ash_strings_am.xtb
+++ b/ash/strings/ash_strings_am.xtb
@@ -102,6 +102,7 @@
 <translation id="1480845547124508962"><ph name="CURRENT_TIME" />፣ የቀን መቁጠሪያ እይታን ለመክፈት የአስገባ ቁልፍን ይጫኑ</translation>
 <translation id="1484102317210609525"><ph name="DEVICE_NAME" /> (HDMI/DP)</translation>
 <translation id="1487931858675166540"><ph name="FIRST_ITEM_TITLE" /> ከ<ph name="SECOND_ITEM_TITLE" /> ጋር ተቀያይሯል</translation>
+<translation id="1500926532737552529">ሁሉንም የአስተያየት ጥቆማዎች አሳይ</translation>
 <translation id="1503394326855300303">ይህ የባለቤት መለያ በበርካታ መለያ በሚገባበት ክፍለ-ጊዜ ውስጥ የመጀመሪያው የገባ መለያ መሆን አለበት።</translation>
 <translation id="1510238584712386396">ማስጀመሪያ</translation>
 <translation id="1516740043221086139">አትረብሽ በርቷል።</translation>
diff --git a/ash/strings/ash_strings_de.xtb b/ash/strings/ash_strings_de.xtb
index 445505d..496ccc2 100644
--- a/ash/strings/ash_strings_de.xtb
+++ b/ash/strings/ash_strings_de.xtb
@@ -102,6 +102,7 @@
 <translation id="1480845547124508962"><ph name="CURRENT_TIME" /> – Drücke die Eingabetaste, um die Kalenderansicht zu öffnen</translation>
 <translation id="1484102317210609525"><ph name="DEVICE_NAME" /> (HDMI/DP)</translation>
 <translation id="1487931858675166540"><ph name="FIRST_ITEM_TITLE" /> und <ph name="SECOND_ITEM_TITLE" /> haben die Plätze getauscht</translation>
+<translation id="1500926532737552529">Alle Vorschläge anzeigen</translation>
 <translation id="1503394326855300303">Dieses Inhaberkonto muss in einer Sitzung mit Mehrfachanmeldung das erste angemeldete Konto sein.</translation>
 <translation id="1510238584712386396">Launcher</translation>
 <translation id="1516740043221086139">„Bitte nicht stören“ ist aktiviert.</translation>
diff --git a/ash/strings/ash_strings_es.xtb b/ash/strings/ash_strings_es.xtb
index 3d09624..5f71145 100644
--- a/ash/strings/ash_strings_es.xtb
+++ b/ash/strings/ash_strings_es.xtb
@@ -102,6 +102,7 @@
 <translation id="1480845547124508962"><ph name="CURRENT_TIME" />. Pulsa la tecla Intro para abrir la vista de Calendar.</translation>
 <translation id="1484102317210609525"><ph name="DEVICE_NAME" /> (HDMI/DP)</translation>
 <translation id="1487931858675166540"><ph name="FIRST_ITEM_TITLE" /> y <ph name="SECOND_ITEM_TITLE" /> se han intercambiado</translation>
+<translation id="1500926532737552529">Mostrar todas las sugerencias</translation>
 <translation id="1503394326855300303">La cuenta de este propietario debe ser la primera cuenta que ha iniciado sesión en un inicio de sesión múltiple.</translation>
 <translation id="1510238584712386396">Menú de aplicaciones</translation>
 <translation id="1516740043221086139">El modo No molestar está activado.</translation>
diff --git a/ash/strings/ash_strings_lt.xtb b/ash/strings/ash_strings_lt.xtb
index 5ddf1e1..0664187 100644
--- a/ash/strings/ash_strings_lt.xtb
+++ b/ash/strings/ash_strings_lt.xtb
@@ -102,6 +102,7 @@
 <translation id="1480845547124508962"><ph name="CURRENT_TIME" />, spustelėkite klavišą „Enter“, kad atidarytumėte Kalendoriaus rodinį</translation>
 <translation id="1484102317210609525"><ph name="DEVICE_NAME" /> (HDMI / DP)</translation>
 <translation id="1487931858675166540">„<ph name="FIRST_ITEM_TITLE" />“ sukeistas su „<ph name="SECOND_ITEM_TITLE" />“</translation>
+<translation id="1500926532737552529">Rodyti visus pasiūlymus</translation>
 <translation id="1503394326855300303">Kelių paskyrų sesijoje pirmiausia turi būti prisijungta naudojant šią savininko paskyrą.</translation>
 <translation id="1510238584712386396">Paleidimo priemonė</translation>
 <translation id="1516740043221086139">Netrukdymo režimas įjungtas.</translation>
diff --git a/ash/strings/ash_strings_ms.xtb b/ash/strings/ash_strings_ms.xtb
index 35522aec..2a3517a 100644
--- a/ash/strings/ash_strings_ms.xtb
+++ b/ash/strings/ash_strings_ms.xtb
@@ -102,6 +102,7 @@
 <translation id="1480845547124508962"><ph name="CURRENT_TIME" />, Tekan kekunci enter untuk membuka paparan Calendar</translation>
 <translation id="1484102317210609525"><ph name="DEVICE_NAME" /> (HDMI/DP)</translation>
 <translation id="1487931858675166540"><ph name="FIRST_ITEM_TITLE" /> Ditukar dengan <ph name="SECOND_ITEM_TITLE" /></translation>
+<translation id="1500926532737552529">Tunjukkan semua cadangan</translation>
 <translation id="1503394326855300303">Akaun pemilik ini perlu menjadi akaun dilog masuk yang pertama dalam sesi berbilang log masuk.</translation>
 <translation id="1510238584712386396">Pelancar</translation>
 <translation id="1516740043221086139">Jangan ganggu dihidupkan.</translation>
diff --git a/ash/strings/ash_strings_my.xtb b/ash/strings/ash_strings_my.xtb
index 8dfd2318..bf712a5 100644
--- a/ash/strings/ash_strings_my.xtb
+++ b/ash/strings/ash_strings_my.xtb
@@ -102,6 +102,7 @@
 <translation id="1480845547124508962"><ph name="CURRENT_TIME" />၊ Calendar ပြသမှုဖွင့်ရန် Enter ခလုတ် နှိပ်ပါ</translation>
 <translation id="1484102317210609525"><ph name="DEVICE_NAME" /> (HDMI/DP)</translation>
 <translation id="1487931858675166540"><ph name="FIRST_ITEM_TITLE" /> ကို <ph name="SECOND_ITEM_TITLE" /> ဖြင့် လှဲလှယ်ထားသည်</translation>
+<translation id="1500926532737552529">အကြံပြုချက်အားလုံး ပြရန်</translation>
 <translation id="1503394326855300303">ဒီပိုင်ရှင် အကောင့်မှာ အကြိမ်ကြိမ် လက်မှတ်ထိုးရမည့် အစီအစဉ် ထဲက ပထမဦးဆုံး လက်မှတ်ထိုး ဝင်သည့် အကောင့် ဖြစ်ပါသည်။</translation>
 <translation id="1510238584712386396">Launcher</translation>
 <translation id="1516740043221086139">'မနှောင့်ယှက်ရ' ဖွင့်ထားသည်။</translation>
diff --git a/ash/strings/ash_strings_ne.xtb b/ash/strings/ash_strings_ne.xtb
index 2acb2e5..6dfc368 100644
--- a/ash/strings/ash_strings_ne.xtb
+++ b/ash/strings/ash_strings_ne.xtb
@@ -102,6 +102,7 @@
 <translation id="1480845547124508962"><ph name="CURRENT_TIME" />, पात्रोको भ्यू खोल्न इन्टर थिच्नुहोस्</translation>
 <translation id="1484102317210609525"><ph name="DEVICE_NAME" /> (HDMI/DP)</translation>
 <translation id="1487931858675166540"><ph name="FIRST_ITEM_TITLE" /> लाई <ph name="SECOND_ITEM_TITLE" /> सँग साटियो</translation>
+<translation id="1500926532737552529">सबै सुझावहरू देखाइयोस्</translation>
 <translation id="1503394326855300303">यो मालिक खाता मल्टिपल साइन-इन सत्रमा पहिलो पटक साइन-इन गरिएको खाता हुनुपर्दछ।</translation>
 <translation id="1510238584712386396">लन्चर</translation>
 <translation id="1516740043221086139">बाधा नपुर्‍याउनुहोस् नामक मोड सक्रिय छ।</translation>
diff --git a/ash/strings/ash_strings_or.xtb b/ash/strings/ash_strings_or.xtb
index 5b99928..0e49ac7c 100644
--- a/ash/strings/ash_strings_or.xtb
+++ b/ash/strings/ash_strings_or.xtb
@@ -102,6 +102,7 @@
 <translation id="1480845547124508962"><ph name="CURRENT_TIME" />, Calendar ଭ୍ୟୁ ଖୋଲିବାକୁ Enter କୀ ଦବାନ୍ତୁ</translation>
 <translation id="1484102317210609525"><ph name="DEVICE_NAME" /> (HDMI/DP)</translation>
 <translation id="1487931858675166540"><ph name="FIRST_ITEM_TITLE" />କୁ <ph name="SECOND_ITEM_TITLE" /> ସହିତ ସ୍ୱାପ୍ କରାଯାଇଛି</translation>
+<translation id="1500926532737552529">ସମସ୍ତ ପରାମର୍ଶ ଦେଖାନ୍ତୁ</translation>
 <translation id="1503394326855300303">ଏହି ମାଲିକଙ୍କ ଆକାଉଣ୍ଟଟିକୁ ସର୍ବପ୍ରଥମେ ସାଇନ୍ ଇନ୍ କରିଥିବା ଆକାଉଣ୍ଟ ଭାବରେ ରଖିବା ଆବଶ୍ୟକ ଅଟେ৷</translation>
 <translation id="1510238584712386396">ଲଞ୍ଚର୍</translation>
 <translation id="1516740043221086139">'ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ' ଚାଲୁ ଅଛି।</translation>
diff --git a/base/message_loop/message_pump_mac.h b/base/message_loop/message_pump_mac.h
index 96881f96..0233b0a 100644
--- a/base/message_loop/message_pump_mac.h
+++ b/base/message_loop/message_pump_mac.h
@@ -134,8 +134,10 @@
   int run_nesting_level() const { return run_nesting_level_; }
   bool keep_running() const { return keep_running_; }
 
+#if BUILDFLAG(IS_IOS)
   void OnAttach();
   void OnDetach();
+#endif
 
   // Sets this pump's delegate.  Signals the appropriate sources if
   // |delegateless_work_| is true.  |delegate| can be NULL.
diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm
index 1cf2edf..9c955aa 100644
--- a/base/message_loop/message_pump_mac.mm
+++ b/base/message_loop/message_pump_mac.mm
@@ -331,6 +331,7 @@
       std::memory_order_relaxed);
 }
 
+#if BUILDFLAG(IS_IOS)
 void MessagePumpCFRunLoopBase::OnAttach() {
   CHECK_EQ(nesting_level_, 0);
   // On iOS: the MessagePump is attached while it's already running.
@@ -342,8 +343,18 @@
 }
 
 void MessagePumpCFRunLoopBase::OnDetach() {
-  CHECK_EQ(nesting_level_, 0);
+  // This function is called on shutdown. This can happen at either
+  // `nesting_level` 1 or 0:
+  //   `nesting_level_ == 0`: When this is detached as part of tear down outside
+  //   of a run loop (e.g. ~TaskEnvironment). `nesting_level_ == 1`: When this
+  //   is detached as part of a native shutdown notification ran from the
+  //   message pump itself.
+  // Additional nesting would be surprising as it would imply that unwinding the
+  // nested loop has to go through the detached MessagePump again...
+  CHECK_GE(nesting_level_, 0);
+  CHECK_LE(nesting_level_, 1);
 }
+#endif  // BUILDFLAG(IS_IOS)
 
 void MessagePumpCFRunLoopBase::SetDelegate(Delegate* delegate) {
   delegate_ = delegate;
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index fc50bdd..a77d469 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-8.20220617.3.1
+8.20220618.3.1
diff --git a/chrome/VERSION b/chrome/VERSION
index 59a9c95..aed366e3 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=105
 MINOR=0
-BUILD=5127
+BUILD=5130
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index a2669bb..80b0442e 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -339,7 +339,6 @@
     "$google_play_services_package:google_play_services_tasks_java",
     "$google_play_services_package:google_play_services_vision_common_java",
     "$google_play_services_package:google_play_services_vision_java",
-    "//base:jni_java",
     "//cc:cc_java",
     "//chrome/android/features/keyboard_accessory:public_java",
     "//chrome/android/features/start_surface:java_resources",
@@ -370,7 +369,7 @@
     "//chrome/browser/commerce/price_tracking/android:java",
     "//chrome/browser/commerce/price_tracking/proto:proto_java",
     "//chrome/browser/commerce/shopping_list/android:java",
-    "//chrome/browser/commerce/subscriptions/android:subscriptions_java",
+    "//chrome/browser/commerce/subscriptions/android:java",
     "//chrome/browser/consent_auditor/android:java",
     "//chrome/browser/contextmenu:java",
     "//chrome/browser/dependency_injection:java",
@@ -746,7 +745,6 @@
   # TODO(crbug/1186003): Instead of adding source files, add it as a separate
   # dependency when circular deps is resolved.
   sources += price_tracking_java_sources
-  deps += price_tracking_java_deps
 
   # TODO(crbug/1210158): Instead of adding source files, add it as a separate
   # dependency when circular deps is resolved.
@@ -995,7 +993,7 @@
     "//chrome/browser/commerce/merchant_viewer/android:junit",
     "//chrome/browser/commerce/price_tracking/android:java",
     "//chrome/browser/commerce/price_tracking/proto:proto_java",
-    "//chrome/browser/commerce/subscriptions/android:subscriptions_java",
+    "//chrome/browser/commerce/subscriptions/android:java",
     "//chrome/browser/contextmenu:java",
     "//chrome/browser/dependency_injection:java",
     "//chrome/browser/device:java",
@@ -1362,7 +1360,6 @@
     "//chrome/browser/android/browserservices/intents:java",
     "//chrome/browser/android/browserservices/verification:java",
     "//chrome/browser/android/crypto:java",
-    "//chrome/browser/commerce/subscriptions/android:subscriptions_java",
     "//chrome/browser/contextmenu:java",
     "//chrome/browser/download/android:download_java_tests",
     "//chrome/browser/feature_engagement:java",
@@ -1476,7 +1473,6 @@
     "//chrome/browser/commerce/merchant_viewer/android:java",
     "//chrome/browser/commerce/merchant_viewer/android:javatests",
     "//chrome/browser/commerce/price_tracking/android:java",
-    "//chrome/browser/commerce/subscriptions/android:subscriptions_java",
     "//chrome/browser/content_creation/notes/internal/android:java",
     "//chrome/browser/content_creation/notes/internal/android:javatests",
     "//chrome/browser/contextmenu:java",
diff --git a/chrome/android/expectations/monochrome_public_bundle__base.AndroidManifest.expected b/chrome/android/expectations/monochrome_public_bundle__base.AndroidManifest.expected
index 15995e5..0929e60 100644
--- a/chrome/android/expectations/monochrome_public_bundle__base.AndroidManifest.expected
+++ b/chrome/android/expectations/monochrome_public_bundle__base.AndroidManifest.expected
@@ -436,24 +436,24 @@
         android:noHistory="true"
         android:theme="@style/Theme.BrowserUI.NoDisplay">
     </activity>  # DIFF-ANCHOR: e86e2b49
-    <activity  # DIFF-ANCHOR: 7ff74272
-        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl$DismissNotificationChromeActivity"
+    <activity  # DIFF-ANCHOR: 01e92ad4
+        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager$DismissNotificationChromeActivity"
         android:autoRemoveFromRecents="true"
         android:documentLaunchMode="always"
         android:excludeFromRecents="true"
         android:exported="false"
         android:noHistory="true"
         android:theme="@style/Theme.BrowserUI.NoDisplay">
-    </activity>  # DIFF-ANCHOR: 7ff74272
-    <activity  # DIFF-ANCHOR: 71702606
-        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl$TrampolineActivity"
+    </activity>  # DIFF-ANCHOR: 01e92ad4
+    <activity  # DIFF-ANCHOR: 24aedc77
+        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager$TrampolineActivity"
         android:autoRemoveFromRecents="true"
         android:documentLaunchMode="always"
         android:excludeFromRecents="true"
         android:exported="false"
         android:noHistory="true"
         android:theme="@style/Theme.BrowserUI.NoDisplay">
-    </activity>  # DIFF-ANCHOR: 71702606
+    </activity>  # DIFF-ANCHOR: 24aedc77
     <activity  # DIFF-ANCHOR: 7468a722
         android:name="org.chromium.chrome.browser.searchwidget.SearchActivity"
         android:clearTaskOnLaunch="true"
diff --git a/chrome/android/expectations/monochrome_public_bundle__chrome.AndroidManifest.expected b/chrome/android/expectations/monochrome_public_bundle__chrome.AndroidManifest.expected
index 6f214c1..6712c46 100644
--- a/chrome/android/expectations/monochrome_public_bundle__chrome.AndroidManifest.expected
+++ b/chrome/android/expectations/monochrome_public_bundle__chrome.AndroidManifest.expected
@@ -309,24 +309,24 @@
         android:noHistory="true"
         android:theme="@style/Theme.BrowserUI.NoDisplay">
     </activity>  # DIFF-ANCHOR: e86e2b49
-    <activity  # DIFF-ANCHOR: 7ff74272
-        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl$DismissNotificationChromeActivity"
+    <activity  # DIFF-ANCHOR: 01e92ad4
+        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager$DismissNotificationChromeActivity"
         android:autoRemoveFromRecents="true"
         android:documentLaunchMode="always"
         android:excludeFromRecents="true"
         android:exported="false"
         android:noHistory="true"
         android:theme="@style/Theme.BrowserUI.NoDisplay">
-    </activity>  # DIFF-ANCHOR: 7ff74272
-    <activity  # DIFF-ANCHOR: 71702606
-        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl$TrampolineActivity"
+    </activity>  # DIFF-ANCHOR: 01e92ad4
+    <activity  # DIFF-ANCHOR: 24aedc77
+        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager$TrampolineActivity"
         android:autoRemoveFromRecents="true"
         android:documentLaunchMode="always"
         android:excludeFromRecents="true"
         android:exported="false"
         android:noHistory="true"
         android:theme="@style/Theme.BrowserUI.NoDisplay">
-    </activity>  # DIFF-ANCHOR: 71702606
+    </activity>  # DIFF-ANCHOR: 24aedc77
     <activity  # DIFF-ANCHOR: 7468a722
         android:name="org.chromium.chrome.browser.searchwidget.SearchActivity"
         android:clearTaskOnLaunch="true"
diff --git a/chrome/android/expectations/trichrome_chrome_bundle__base.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_bundle__base.AndroidManifest.expected
index ab99d4064..8c415e3 100644
--- a/chrome/android/expectations/trichrome_chrome_bundle__base.AndroidManifest.expected
+++ b/chrome/android/expectations/trichrome_chrome_bundle__base.AndroidManifest.expected
@@ -409,24 +409,24 @@
         android:noHistory="true"
         android:theme="@style/Theme.BrowserUI.NoDisplay">
     </activity>  # DIFF-ANCHOR: e86e2b49
-    <activity  # DIFF-ANCHOR: 7ff74272
-        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl$DismissNotificationChromeActivity"
+    <activity  # DIFF-ANCHOR: 01e92ad4
+        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager$DismissNotificationChromeActivity"
         android:autoRemoveFromRecents="true"
         android:documentLaunchMode="always"
         android:excludeFromRecents="true"
         android:exported="false"
         android:noHistory="true"
         android:theme="@style/Theme.BrowserUI.NoDisplay">
-    </activity>  # DIFF-ANCHOR: 7ff74272
-    <activity  # DIFF-ANCHOR: 71702606
-        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl$TrampolineActivity"
+    </activity>  # DIFF-ANCHOR: 01e92ad4
+    <activity  # DIFF-ANCHOR: 24aedc77
+        android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager$TrampolineActivity"
         android:autoRemoveFromRecents="true"
         android:documentLaunchMode="always"
         android:excludeFromRecents="true"
         android:exported="false"
         android:noHistory="true"
         android:theme="@style/Theme.BrowserUI.NoDisplay">
-    </activity>  # DIFF-ANCHOR: 71702606
+    </activity>  # DIFF-ANCHOR: 24aedc77
     <activity  # DIFF-ANCHOR: 7468a722
         android:name="org.chromium.chrome.browser.searchwidget.SearchActivity"
         android:clearTaskOnLaunch="true"
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index 222234e..2face667 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -243,6 +243,7 @@
     "javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java",
     "javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java",
     "javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceCardViewTest.java",
+    "javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java",
     "javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java",
     "javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java",
     "javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java",
@@ -262,6 +263,7 @@
     "//chrome/browser/optimization_guide/android:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/tab:java",
+    "//chrome/browser/ui/android/theme:java",
     "//chrome/test/android:chrome_java_integration_only_test_support",
     "//chrome/test/android:chrome_java_test_support_common",
     "//components/browser_ui/styles/android:java",
@@ -273,12 +275,15 @@
     "//content/public/android:content_full_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_deps:espresso_java",
+    "//third_party/android_deps:material_design_java",
     "//third_party/android_deps:protobuf_lite_runtime_java",
     "//third_party/android_sdk:android_test_base_java",
     "//third_party/androidx:androidx_appcompat_appcompat_resources_java",
+    "//third_party/androidx:androidx_core_core_java",
     "//third_party/androidx:androidx_recyclerview_recyclerview_java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/hamcrest:hamcrest_core_java",
+    "//third_party/hamcrest:hamcrest_library_java",
     "//third_party/junit:junit",
     "//third_party/mockito:mockito_java",
     "//ui/android:ui_java_test_support",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceMessageCardViewModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceMessageCardViewModel.java
index bbeb8d9..12431e7d 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceMessageCardViewModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceMessageCardViewModel.java
@@ -107,4 +107,4 @@
         }
         return null;
     }
-}
+}
\ No newline at end of file
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceAlertsMessageCardTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceAlertsMessageCardTest.java
index 8ec44e8..4a19fb22 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceAlertsMessageCardTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceAlertsMessageCardTest.java
@@ -57,7 +57,6 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager;
 import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerFactory;
-import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingFeatures;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingUtilities;
 import org.chromium.chrome.browser.tasks.tab_management.MessageService.MessageDisableReason;
@@ -108,7 +107,7 @@
         Intents.init();
         PriceTrackingFeatures.setIsSignedInAndSyncEnabledForTesting(true);
         mMockNotificationManager = new MockNotificationManagerProxy();
-        PriceDropNotificationManagerImpl.setNotificationManagerForTesting(mMockNotificationManager);
+        PriceDropNotificationManager.setNotificationManagerForTesting(mMockNotificationManager);
         mPriceDropNotificationManager = PriceDropNotificationManagerFactory.create();
 
         mActivityTestRule.startMainActivityOnBlankPage();
@@ -122,7 +121,7 @@
             mPriceDropNotificationManager.deleteChannelForTesting();
         }
         PriceTrackingFeatures.setIsSignedInAndSyncEnabledForTesting(null);
-        PriceDropNotificationManagerImpl.setNotificationManagerForTesting(null);
+        PriceDropNotificationManager.setNotificationManagerForTesting(null);
         ActivityTestUtils.clearActivityOrientation(mActivityTestRule.getActivity());
         Intents.release();
     }
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni
index 96f0046..5ae8b00 100644
--- a/chrome/android/features/tab_ui/tab_management_java_sources.gni
+++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -30,7 +30,6 @@
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java",
-  "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java",
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 2dfc889a..3bcbcdb5 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -1129,7 +1129,7 @@
             android:noHistory="true"/>
 
         <activity
-            android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl$TrampolineActivity"
+            android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager$TrampolineActivity"
             android:theme="@style/Theme.BrowserUI.NoDisplay"
             android:exported="false"
             android:autoRemoveFromRecents="true"
@@ -1138,7 +1138,7 @@
             android:noHistory="true"/>
 
         <activity
-            android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl$DismissNotificationChromeActivity"
+            android:name="org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager$DismissNotificationChromeActivity"
             android:theme="@style/Theme.BrowserUI.NoDisplay"
             android:exported="false"
             android:autoRemoveFromRecents="true"
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java
index daed5c4..a61f7cf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java
@@ -24,7 +24,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
-import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState;
@@ -176,7 +175,6 @@
     @Feature({"ContextualSearch"})
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
     @ParameterAnnotations.UseMethodParameter(FeatureParamProvider.class)
-    @DisableIf.Build(supported_abis_includes = "arm64-v8a", message = "crbug.com/596533")
     public void testAppMenuSuppressedWhenExpanded(@EnabledFeature int enabledFeature)
             throws Exception {
         triggerPanelPeek();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
index ae5a2e6a..c811951 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
@@ -9,7 +9,6 @@
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 
-import static org.hamcrest.Matchers.is;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.when;
@@ -72,6 +71,7 @@
 import org.chromium.chrome.browser.enterprise.util.EnterpriseInfo;
 import org.chromium.chrome.browser.enterprise.util.FakeEnterpriseInfo;
 import org.chromium.chrome.browser.firstrun.FirstRunActivityTestObserver.ScopedObserverData;
+import org.chromium.chrome.browser.firstrun.ToSAndUMAFirstRunFragment.Observer;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.locale.LocaleManagerDelegate;
@@ -270,6 +270,15 @@
         EnterpriseInfo.setInstanceForTest(fakeEnterpriseInfo);
     }
 
+    private void setTosAccepted(boolean allowCrashUpload) {
+        FirstRunStatus.setSkipWelcomePage(true);
+        SharedPreferencesManager sharedPreferencesManager = SharedPreferencesManager.getInstance();
+        sharedPreferencesManager.writeBoolean(
+                ChromePreferenceKeys.FIRST_RUN_CACHED_TOS_ACCEPTED, true);
+        sharedPreferencesManager.writeBoolean(
+                ChromePreferenceKeys.PRIVACY_METRICS_REPORTING_PERMITTED_BY_USER, allowCrashUpload);
+    }
+
     private void enableCloudManagementViaPolicy() {
         setHasAppRestrictionForMock(true);
         Bundle restrictions = new Bundle();
@@ -573,6 +582,7 @@
 
     private void initializePreferences(FirstRunPagesTestCase testCase) throws Exception {
         if (testCase.cctTosDisabled()) skipTosDialogViaPolicy();
+        if (testCase.isTosAccepted()) setTosAccepted(testCase.isUmaUploadAccepted());
 
         mDelegate = new TestFirstRunFlowSequencerDelegate(testCase);
         FirstRunFlowSequencer.setDelegateForTesting(mDelegate);
@@ -746,14 +756,12 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1197556")
     public void testResetOnBackPress() throws Exception {
         testResetOnBackPressImpl(true);
     }
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1197556")
     public void testResetOnBackPress_NoUmaAccepted() throws Exception {
         testResetOnBackPressImpl(false);
     }
@@ -763,28 +771,36 @@
         // When the policy initialization is finishing after ToS accepted, the small loading circle
         // will be shown on the screen. If user decide to go back with backpress, the UI should be
         // reset with ToS UI visible.
-        FirstRunStatus.setSkipWelcomePage(true);
-        SharedPreferencesManager sharedPreferencesManager = SharedPreferencesManager.getInstance();
-        sharedPreferencesManager.writeBoolean(
-                ChromePreferenceKeys.FIRST_RUN_CACHED_TOS_ACCEPTED, true);
-        sharedPreferencesManager.writeBoolean(
-                ChromePreferenceKeys.PRIVACY_METRICS_REPORTING_PERMITTED_BY_USER,
-                allowedCrashUpLoad);
-        setHasAppRestrictionForMock(false);
+        FirstRunPagesTestCase testCase = new FirstRunPagesTestCase()
+                                                 .withSigninPromo()
+                                                 .withTosAlreadyAccepted()
+                                                 .setUmaUploadAccepted(allowedCrashUpLoad);
+        initializePreferences(testCase);
+
+        // In this specific setup the policy loading call will be notified before ToS fragment is
+        // finishing initialization, as FRE might attach to the PolicyLoaderListener first. To make
+        // sure no race condition happen, use TosAndUmaObserver to make sure the call is invoked.
+        CallbackHelper tosPagePolicyLoadingListener = new CallbackHelper();
+        ToSAndUMAFirstRunFragment.setObserverForTesting(new Observer() {
+            @Override
+            public void onNativeInitialized() {}
+
+            @Override
+            public void onPolicyServiceInitialized() {
+                tosPagePolicyLoadingListener.notifyCalled();
+            }
+
+            @Override
+            public void onHideLoadingUIComplete() {}
+        });
+
         FirstRunActivity freActivity = launchFirstRunActivity();
 
-        // ToS page should be skipped and jumped to the next page, since ToS is marked accepted in
-        // shared preference.
-        ScopedObserverData scopedObserverData = getObserverData(freActivity);
-        scopedObserverData.createPostNativeAndPoliciesPageSequenceCallback.waitForCallback(
-                "Failed to finalize the flow.", 0);
-        CriteriaHelper.pollUiThread(
-                () -> Criteria.checkThat(freActivity.isNativeSideIsInitializedForTest(), is(true)));
-        scopedObserverData.jumpToPageCallback.waitForCallback(
-                "ToS should be skipped after native initialized.", 0);
-
-        // Press back button.
-        TestThreadUtils.runOnUiThreadBlocking(() -> mLastActivity.onBackPressed());
+        FirstRunNavigationHelper navHelper = new FirstRunNavigationHelper(freActivity)
+                                                     .ensurePagesCreationSucceeded()
+                                                     .ensureSigninPromoIsCurrentPage();
+        tosPagePolicyLoadingListener.waitForFirst();
+        navHelper.goBackToPreviousPage().ensureTermsOfServiceIsCurrentPage();
 
         View tosAndPrivacy = mLastActivity.findViewById(R.id.tos_and_privacy);
         CheckBox umaCheckbox = mLastActivity.findViewById(R.id.send_report_checkbox);
@@ -1228,6 +1244,9 @@
         private @SearchEnginePromoType int mSearchPromoType = SearchEnginePromoType.DONT_SHOW;
         private boolean mShowSigninPromo;
 
+        private boolean mIsTosAccepted;
+        private boolean mIsUmaUploadAccepted;
+
         boolean cctTosDisabled() {
             return mCctTosDisabled;
         }
@@ -1246,6 +1265,14 @@
             return mShowSigninPromo;
         }
 
+        boolean isTosAccepted() {
+            return mIsTosAccepted;
+        }
+
+        boolean isUmaUploadAccepted() {
+            return mIsUmaUploadAccepted;
+        }
+
         FirstRunPagesTestCase setCctTosDisabled(boolean cctTosDisabled) {
             mCctTosDisabled = cctTosDisabled;
             return this;
@@ -1261,6 +1288,16 @@
             return this;
         }
 
+        FirstRunPagesTestCase setTosAccepted(boolean tosAccepted) {
+            mIsTosAccepted = tosAccepted;
+            return this;
+        }
+
+        FirstRunPagesTestCase setUmaUploadAccepted(boolean umaUploadAccepted) {
+            mIsUmaUploadAccepted = umaUploadAccepted;
+            return this;
+        }
+
         FirstRunPagesTestCase withCctTosDisabled() {
             return setCctTosDisabled(true);
         }
@@ -1273,6 +1310,15 @@
             return setSigninPromo(true);
         }
 
+        // Used assuming user has previously accepted ToS and move to the following pages.
+        FirstRunPagesTestCase withTosAlreadyAccepted() {
+            return setTosAccepted(true);
+        }
+
+        FirstRunPagesTestCase withUmaUploadAccepted() {
+            return setUmaUploadAccepted(true);
+        }
+
         static FirstRunPagesTestCase createWithShowAllPromos() {
             return new FirstRunPagesTestCase().withSearchPromo().withSigninPromo();
         }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 23c8b81..ed5f425d 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-104.0.5112.12_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-104.0.5112.15_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index 5e3d164..a28f9361 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -3928,6 +3928,7 @@
 <translation id="4768332406694066911">እርስዎን የሚለዩ ከእነዚህ ድርጅቶች የመጡ የዕውቅና ማረጋገጫዎች አለዎት</translation>
 <translation id="4770119228883592393">ፍቃድ ተጠይቋል፣ መልስ ለመስጠት ⌘ + አማራጭ + የታች ቀስት ይጫኑ</translation>
 <translation id="4773112038801431077">Linuxን አልቅ</translation>
+<translation id="4774337692467964393">Smart Lock በርቶ ከሆነ ፒን ወይም የይለፍ ቃል ማስገባት አያስፈልግዎትም</translation>
 <translation id="4775142426314270551">የስንክል ሪፖርቶችንና እንዲሁም የምርመራ እና የአጠቃቀም ውሂብን በራስ-ሰር ወደ Google በመላክ የChromeOS ባህሪያትን እና አፈጻጸምን እንዲሻሻል ያግዙ። አንዳንድ ውሑድ ውሂብ እንዲሁም የAndroid መተግበሪያዎችን እና የGoogle አጋሮችን ያግዛል። የልጅዎ የGoogle መለያ የድር እና የመተግበሪያ ቅንብሩ እንቅስቃሴ በርቶ ከሆነ የልጅዎ የAndroid ውሂብ በልጅዎ የGoogle መለያ ላይ ሊቀመጥ ይችላል።</translation>
 <translation id="477647109558161443">የዴስክቶፕ አቋራጭ ይፍጠሩ</translation>
 <translation id="4776594120007763294">በኋላ የሚነበብ ገጽን ለማከል አዝራሩን ጠቅ ያድርጉ</translation>
@@ -3977,6 +3978,7 @@
 <translation id="4820236583224459650">እንደ ገቢር ቲኬት አቀናብር</translation>
 <translation id="4821935166599369261">&amp;መገለጫ መስራት ነቅቷል</translation>
 <translation id="4823484602432206655">የተጠቃሚ እና የመሣሪያ ቅንብሮችን ያንብቡ እና ይለውጡ</translation>
+<translation id="4823894915586516138">ይህ ፒን ወይም የይለፍ ቃል ከስልክዎ የሚደርሱት ማንኛውም መረጃን አካትቶ በዚህ <ph name="DEVICE_TYPE" /> ላይ ውሂብዎን ይጠብቃል</translation>
 <translation id="4824037980212326045">የLinux ምትኬ እና ወደነበረበት መመለስ</translation>
 <translation id="4824958205181053313">ስምረት ይሰረዝ?</translation>
 <translation id="4827675678516992122">መገናኘት አልተቻለም</translation>
@@ -5634,6 +5636,7 @@
 <translation id="648927581764831596">ምንም አይገኝም</translation>
 <translation id="6490471652906364588">USB-C መሣሪያ (የቀኝ ወደብ)</translation>
 <translation id="6491376743066338510">ፈቀዳ አልተሳካም</translation>
+<translation id="6492396476180293140">የውስጣዊ ካሜራ በሃርድዌር መቀያየሪያ ቦዝኗል</translation>
 <translation id="6494327278868541139">የበለጸጉ የጥበቃ ዝርዝሮችን አሳይ</translation>
 <translation id="6494445798847293442">የእውቅና ማረጋገጫ ባለሥልጣን አይደለም</translation>
 <translation id="6494974875566443634">ማበጀት</translation>
diff --git a/chrome/app/resources/generated_resources_as.xtb b/chrome/app/resources/generated_resources_as.xtb
index 918802d20..46fbaf0 100644
--- a/chrome/app/resources/generated_resources_as.xtb
+++ b/chrome/app/resources/generated_resources_as.xtb
@@ -2585,6 +2585,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" />এ <ph name="FILENAME" /> চাব পাৰিব</translation>
 <translation id="3445047461171030979">Google Assistantৰ দ্ৰুত উত্তৰসমূহ</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> মিনিট</translation>
+<translation id="344537926140058498">এই ফাইলটোত সংবেদনশীল অথবা বিপজ্জনক সমল থকাৰ বাবে আপোনাৰ প্ৰতিষ্ঠানে ইয়াক অৱৰোধ কৰিছে। এইটোৰ গৰাকীক সমাধান কৰিবলৈ কওক।</translation>
 <translation id="3445925074670675829">ইউএছবি চি ডিভাইচ</translation>
 <translation id="3446274660183028131">Windows ইনষ্টল কৰিবলৈ অনুগ্ৰহ কৰি Parallels Desktop লঞ্চ কৰক।</translation>
 <translation id="344630545793878684">আপোনাৰ ডেটা ৱেবছাইটসমূহত পঢ়ে</translation>
@@ -3142,6 +3143,7 @@
 <translation id="397105322502079400">গণনা কৰি থকা হৈছে…</translation>
 <translation id="3971764089670057203">এই সুৰক্ষা চাবিটোত থকা ফিংগাৰপ্ৰিণ্টসমূহ</translation>
 <translation id="3973005893595042880">ব্যৱহাৰকাৰীক অনুমতি দিয়া হোৱা নাই</translation>
+<translation id="3973062011568994448">পাছৱর্ড আমদানি কৰিবলৈ, এটা CSV ফাইল বাছনি কৰক।</translation>
 <translation id="3973660817924297510">পাছৱর্ডসমূহ পৰীক্ষা কৰি থকা হৈছে (<ph name="TOTAL_PASSWORDS" /> টাৰ ভিতৰত <ph name="CHECKED_PASSWORDS" /> টা)…</translation>
 <translation id="3974514184580396500">স্ক্ৰীনখনত আপোনাৰ ফ’কাছ আগলৈ নিবলৈ “পৰৱৰ্তী” ছুইচটো ব্যৱহাৰ কৰক</translation>
 <translation id="3975201861340929143">ব্যাখ্যা</translation>
@@ -4611,6 +4613,7 @@
 <translation id="5466374726908360271">পে&amp;ষ্ট কৰি “<ph name="SEARCH_TERMS" />”ৰ সন্ধান কৰক</translation>
 <translation id="5467207440419968613"><ph name="PERMISSION_1" />, <ph name="PERMISSION_2" />ক অৱৰোধ কৰা আছে</translation>
 <translation id="5468173180030470402">ফাইলৰ শ্বেয়াৰসমূহ বিচাৰি থকা হৈছে</translation>
+<translation id="5468881191994555667">ফাইল বাছনি কৰক</translation>
 <translation id="5469852975082458401">আপুনি পাঠৰ এটা কাৰ্ছৰৰ জৰিয়তে পৃষ্ঠাসমূহ নেভিগে’ট কৰিব পাৰে। অফ কৰিবলৈ F7 টিপক।</translation>
 <translation id="5470735824776589490">পাৱাৰৱাশ্বৰ জৰিয়তে আপোনাৰ ডিভাইচটো ৰিছেট কৰিব পৰাৰ পূর্বে এবাৰ ৰিষ্টার্ট কৰাৰ আৱশ্যক। <ph name="LINK_BEGIN" />অধিক জানক<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">নমস্কাৰ! মই আপোনাৰ পাঠৰপৰা কথনৰ ভইচ।</translation>
@@ -6343,6 +6346,7 @@
 <translation id="7191159667348037">অজ্ঞাত প্ৰিণ্টাৰ (ইউএছবি)</translation>
 <translation id="7193051357671784796">এই এপ্‌টো আপোনাৰ প্ৰতিষ্ঠানে যোগ কৰিছে। এপ্‌টোৰ ইনষ্টল কৰা প্ৰক্ৰিয়া সম্পূর্ণ কৰিবলৈ এপ্‌টো ৰিষ্টার্ট কৰক।</translation>
 <translation id="7193374945610105795"><ph name="ORIGIN" />ৰ কাৰণে কোনো পাছৱৰ্ড ছেভ কৰা হোৱা নাই</translation>
+<translation id="7194873994243265344">এই ফাইলটো এনক্ৰিপ্ট কৰা বাবে আপোনাৰ প্ৰতিষ্ঠানে ইয়াক অৱৰোধ কৰিছে। এইটোৰ গৰাকীক ডিক্ৰিপ্ট কৰিবলৈ কওক।</translation>
 <translation id="7196913789568937443">Google Driveত বেক আপ লওক৷ আপোনাৰ ডেটা সহজে পুনঃস্থাপন কৰক বা যিকোনো সময়তে ডিভাইচ সলনি কৰক। আপোনাৰ বেকআপত এপ্ ডেটাও আছে। আপোনাৰ বেক আপসমূহ Googleত আপল’ড কৰা হয় আৰু আপোনাৰ Google একাউণ্টৰ পাছৱৰ্ড ব্যৱহাৰ কৰি সেইবোৰ এনক্ৰিপ্ট কৰা হয়৷ <ph name="BEGIN_LINK1" />অধিক জানক<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">আপুনি প্ৰতিবাৰে ব্ৰাউজ কৰোঁতে Google Search আৰু Google স্মাৰ্টৰ সহায় পাওক</translation>
 <translation id="719791532916917144">কীব’ৰ্ডৰ শ্বৰ্টকাট</translation>
@@ -6361,6 +6365,7 @@
 <translation id="7211783048245131419">এই পৰ্যন্ত কোনো ছুইচ আবণ্টন কৰা হোৱা নাই</translation>
 <translation id="7212097698621322584">আপোনাৰ বৰ্তমানৰ পিনটো সলনি কৰিবলৈ সেইটো দিয়ক। আপুনি যদি নিজৰ পিনটো নাজানে, আপুনি সুৰক্ষা চাবিটো ৰিছেট কৰি এটা নতুন পিন সৃষ্টি কৰিব লাগিব।</translation>
 <translation id="7213903639823314449">ঠিকনাৰ বাৰত ব্যৱহাৰ কৰা সন্ধান ইঞ্জিন</translation>
+<translation id="721490496276866468">পাছৱৰ্ড আমদানি কৰক</translation>
 <translation id="7216595297012131718">নিজৰ অগ্ৰাধিকাৰৰ ভিত্তিত ভাষাসমূহ ক্ৰমত সজাওক</translation>
 <translation id="7219473482981809164">ডাউনল’ড কৰিবলৈ আমি বহুকেইটা প্ৰ’ফাইল বিচাৰি পাইছোঁ। আগবঢ়াৰ আগতে আপুনি ডাউনল’ড কৰিবলৈ বিচৰাকেইটা বাছনি কৰক।</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{কোনো দুৰ্বল পাছৱৰ্ড নাই}=1{১ টা দুৰ্বল পাছৱৰ্ড}one{{NUM_WEAK} টা দুৰ্বল পাছৱৰ্ড}other{{NUM_WEAK} টা দুৰ্বল পাছৱৰ্ড}}</translation>
@@ -6994,6 +6999,7 @@
 <translation id="7826190688224781865">খুচুৰা বিক্ৰেতা-ষ্ট’ৰৰ আইৰ ক’ড</translation>
 <translation id="7826249772873145665">ADB ডিবাগিং অক্ষম কৰা হৈছে</translation>
 <translation id="7826254698725248775">বিৰোধ ঘটা ডিভাইচ চিনাক্তকাৰী।</translation>
+<translation id="7828642077514646543">আসোঁৱাহ: প্ৰমাণপত্ৰ ডিক’ড কৰিবলৈ সক্ষম নহ’ল</translation>
 <translation id="7828731929332799387">এইটোৱে তৃতীয় পক্ষৰ প্ৰসংগত উপলব্ধ সকলো কুকি আৰু ছাইটৰ ডেটা মচিব। আপুনি অব্যাহত ৰাখিবলৈ বিচাৰেনে?</translation>
 <translation id="7829877209233347340">বিদ্যালয়ৰ এটা একাউণ্ট যোগ দিয়াৰ অনুমতি দিবলৈ এগৰাকী অভিভাৱকক ছাইন ইন কৰিবলৈ কওক</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7955,6 +7961,7 @@
 <ph name="DOMAIN" />ৰ বাবে আপুনি নিজৰ স্মাৰ্ট কাৰ্ডখন ভৰাই ৰখাৰ আৱশ্যক।}one{আপোনাৰ <ph name="DEVICE_TYPE" /> # ছেকেণ্ডত স্বয়ংক্ৰিয়ভাৱে অৱৰোধ কৰা হ'ব।
 <ph name="DOMAIN" />ৰ বাবে আপুনি নিজৰ স্মাৰ্ট কাৰ্ডখন ভৰাই ৰখাৰ আৱশ্যক।}other{আপোনাৰ <ph name="DEVICE_TYPE" /> # ছেকেণ্ডত স্বয়ংক্ৰিয়ভাৱে অৱৰোধ কৰা হ'ব।
 <ph name="DOMAIN" />ৰ বাবে আপুনি নিজৰ স্মাৰ্ট কাৰ্ডখন ভৰাই ৰখাৰ আৱশ্যক।}}</translation>
+<translation id="8776294611668764629">সুৰক্ষা পৰীক্ষা কৰিবলৈ এই ফাইলটোৰ আকাৰ অতি বেছি ডাঙৰ হোৱাৰ বাবে আপোনাৰ প্ৰতিষ্ঠানে ইয়াক অৱৰোধ কৰিছে। আপুনি ৫০ এমবি পৰ্যন্ত ফাইলসমূহ খুলিব পাৰে।</translation>
 <translation id="8777628254805677039">ৰুট পাছৱৰ্ড</translation>
 <translation id="8779944680596936487">ছাইটে কেৱল নিজৰ ছাইটত আপোনাৰ ব্ৰাউজিঙৰ কাৰ্যকলাপ চাবলৈ কুকিসমূহ ব্যৱহাৰ কৰিব পাৰে</translation>
 <translation id="8780123805589053431">Googleৰ পৰা প্ৰতিচ্ছবিৰ বিৱৰণ পাওক</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index 313678e..06043376 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -3918,6 +3918,7 @@
 <translation id="4768332406694066911">Deine Zertifikate dieser Organisationen identifizieren dich</translation>
 <translation id="4770119228883592393">Berechtigung angefordert. Drücke „⌘ + Option + Abwärtspfeil“, um zu reagieren.</translation>
 <translation id="4773112038801431077">Linux aktualisieren</translation>
+<translation id="4774337692467964393">Wenn Smart Lock aktiviert ist, musst du weder eine PIN noch ein Passwort eingeben</translation>
 <translation id="4775142426314270551">Lasse Absturzberichte, Diagnose- und Nutzungsdaten automatisch an Google senden, um die Funktionen und die Leistung von Chrome OS zu verbessern. Bestimmte aggregierte Daten sind auch für Android-Apps und Google Partner nützlich. Wenn die Einstellung „Zusätzliche Web- &amp; App-Aktivitäten“ im Google-Konto deines Kindes aktiviert ist, werden die Android-Daten deines Kindes möglicherweise in seinem Google-Konto gespeichert.</translation>
 <translation id="477647109558161443">Desktopverknüpfung erstellen</translation>
 <translation id="4776594120007763294">Wenn du eine Seite zum späteren Lesen hinzufügen möchtest, klicke auf die Schaltfläche</translation>
@@ -3967,6 +3968,7 @@
 <translation id="4820236583224459650">Als aktives Ticket festlegen</translation>
 <translation id="4821935166599369261">&amp;Profilerstellung aktiviert</translation>
 <translation id="4823484602432206655">Nutzer- und Geräteeinstellungen lesen und ändern</translation>
+<translation id="4823894915586516138">Die PIN bzw. das Passwort trägt zum Schutz der Daten auf diesem Gerät (<ph name="DEVICE_TYPE" />) bei, einschließlich der Informationen, auf die du von deinem Smartphone aus zugreifst</translation>
 <translation id="4824037980212326045">Linux-Sicherung und ‑Wiederherstellung</translation>
 <translation id="4824958205181053313">Synchronisierung abbrechen?</translation>
 <translation id="4827675678516992122">Verbindung nicht möglich</translation>
@@ -5621,6 +5623,7 @@
 <translation id="648927581764831596">Keine verfügbar</translation>
 <translation id="6490471652906364588">USB-C-Gerät (Port rechts)</translation>
 <translation id="6491376743066338510">Fehler bei Autorisierung</translation>
+<translation id="6492396476180293140">Interne Kamera wurde per Hardwareschalter deaktiviert</translation>
 <translation id="6494327278868541139">Details zum erweiterten Schutz anzeigen</translation>
 <translation id="6494445798847293442">Keine Zertifizierungsstelle</translation>
 <translation id="6494974875566443634">Anpassung</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index f6b8af5..ec54fb6a 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -1923,6 +1923,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Κατάργηση 1 μη υποστηριζόμενης εφαρμογής}other{Κατάργηση # μη υποστηριζόμενων εφαρμογών}}</translation>
 <translation id="2776560192867872731">Αλλαγή ονόματος συσκευής για τη συσκευή <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Διαγραφή αυτού του κοντέινερ</translation>
+<translation id="2778471504622896352">Προσθήκη απομακρυσμένων εφαρμογών στην εφαρμογή εκκίνησης ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Παρουσιάστηκε σφάλμα κατά την εγκατάσταση της εφαρμογής Linux</translation>
 <translation id="2783298271312924866">Η λήψη ολοκληρώθηκε</translation>
@@ -3558,6 +3559,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> και <ph name="NUMBER_OF_OTHER_SWITCHES" /> ακόμη διακόπτες</translation>
 <translation id="439266289085815679">Η διαμόρφωση Bluetooth ελέγχεται από τον χρήστη <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Επεξεργαστείτε το αρχείο διαμόρφωσης.</translation>
+<translation id="4393713825278446281">Οι συσκευές Γρήγορης σύζευξης αποθηκεύτηκαν στο <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Απενεργοποίηση</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Άνοιγμα όλων}=1{&amp;Άνοιγμα σελιδοδείκτη}other{&amp;Άνοιγμα όλων ({COUNT})}}</translation>
 <translation id="4397372003838952832">Δεν θα χρειάζεται να θυμάστε αυτόν τον κωδικό πρόσβασης. Θα αποθηκευτεί στην υπηρεσία <ph name="GOOGLE_PASSWORD_MANAGER" /> για τον λογαριασμό <ph name="EMAIL" />.</translation>
@@ -3788,6 +3790,7 @@
 <translation id="4615586811063744755">δεν έχουν επιλεγεί cookie</translation>
 <translation id="461661862154729886">Πηγή ενέργειας</translation>
 <translation id="4617001782309103936">Υπερβολικά μικρό</translation>
+<translation id="4617019240346358451">Ανανεώστε τη σελίδα για χρήση της επέκτασης "<ph name="EXTENSION_NAME" />"</translation>
 <translation id="4617270414136722281">Επιλογές επεκτάσεων</translation>
 <translation id="4617880081511131945">Δεν είναι δυνατή η δημιουργία σύνδεσης</translation>
 <translation id="4619564267100705184">Επαλήθευση ταυτότητας</translation>
@@ -4003,6 +4006,7 @@
 <translation id="4833683849865011483">Βρέθηκε ένας εκτυπωτής από τον διακομιστή εκτύπωσης.</translation>
 <translation id="4836504898754963407">Διαχείριση δακτυλικών αποτυπωμάτων</translation>
 <translation id="4837128290434901661">Αλλαγή στην Αναζήτηση Google;</translation>
+<translation id="4837165100461973682">Επαναλάβετε τη φόρτωση της σελίδας για να εφαρμόσετε τις αλλαγές σας</translation>
 <translation id="4837926214103741331">Δεν έχετε εξουσιοδότηση για χρήση αυτής της συσκευής. Για να λάβετε άδεια σύνδεσης, επικοινωνήστε με τον κάτοχο της συσκευής.</translation>
 <translation id="4837952862063191349">Για να ξεκλειδώσετε και να επαναφέρετε τα τοπικά δεδομένα σας, πληκτρολογήστε τον προηγούμενο κωδικό πρόσβασής σας για <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Δείτε τις φωτογραφίες, τα πολυμέσα και τις ειδοποιήσεις του τηλεφώνου σας.</translation>
@@ -4312,6 +4316,7 @@
 <translation id="5150254825601720210">Όνομα διακομιστή SSL πιστοποιητικού Netscape</translation>
 <translation id="5151354047782775295">Απελευθερώστε χώρο στον δίσκο, διαφορετικά τα δεδομένα επιλογής ενδέχεται να διαγραφούν αυτόματα</translation>
 <translation id="5153234146675181447">Θα γίνει παράβλεψη του τηλεφώνου</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Σύνθετες ρυθμίσεις για <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Θέμα</translation>
 <translation id="5155327081870541046">Στη γραμμή διευθύνσεων, εισαγάγετε τη συντόμευση για τον ιστότοπο που θέλετε να αναζητήσετε, όπως "@σελιδοδείκτες". Στη συνέχεια, πατήστε τη συντόμευση πληκτρολογίου που προτιμάτε και εισαγάγετε τον όρο αναζήτησης.</translation>
@@ -5948,6 +5953,7 @@
 <translation id="6790497603648687708">Η επέκταση <ph name="EXTENSION_NAME" /> προστέθηκε απομακρυσμένα</translation>
 <translation id="6790820461102226165">Προσθήκη ατόμου</translation>
 <translation id="6793604637258913070">Επισήμανση του δρομέα κειμένου όταν εμφανίζεται ή κινείται.</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">Με την αυτόματη σάρωση μπορείτε να μετακινήστε αυτόματα στα στοιχεία στην οθόνη. Όταν ένα στοιχείο είναι επισημασμένο, πατήστε Επιλογή για να το ενεργοποιήσετε.</translation>
 <translation id="6795884519221689054">Πάντα</translation>
 <translation id="6797493596609571643">Ωχ, κάτι δεν πήγε καλά.</translation>
@@ -7821,6 +7827,7 @@
 <translation id="8642947597466641025">Μεγέθυνση κειμένου</translation>
 <translation id="8643443571868262066">Το αρχείο <ph name="FILE_NAME" /> ενδέχεται να είναι επικίνδυνο. Αποστολή στη Σύνθετη προστασία Google για σάρωση;</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Κανένα cookie}=1{Αποκλείστηκε 1 cookie.}other{Αποκλείστηκαν # cookie.}}</translation>
+<translation id="864423554496711319">Συσκευές που έχουν αποθηκευτεί στον λογαριασμό σας</translation>
 <translation id="8644655801811752511">Δεν είναι δυνατή η επαναφορά αυτού του κλειδιού ασφαλείας. Δοκιμάστε να επαναφέρετε το κλειδί αμέσως μετά την τοποθέτησή του.</translation>
 <translation id="8645354835496065562">Να εξακολουθήσει να επιτρέπεται η πρόσβαση στους αισθητήρες</translation>
 <translation id="8645920082661222035">Προβλέπει και σας προειδοποιεί για επικίνδυνα συμβάντα προτού αυτά συμβούν.</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index d60d8f3e6..ea5643d 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -2573,6 +2573,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> podrá ver <ph name="FILENAME" /></translation>
 <translation id="3445047461171030979">Respuestas rápidas del Asistente de Google</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
+<translation id="344537926140058498">Tu organización ha bloqueado este archivo porque incluye contenido sensible o peligroso. Pídele al propietario que lo corrija.</translation>
 <translation id="3445925074670675829">Dispositivo USB-C</translation>
 <translation id="3446274660183028131">Abre Parallels Desktop para instalar Windows.</translation>
 <translation id="344630545793878684">Leer tus datos en varios sitios web</translation>
@@ -3130,6 +3131,7 @@
 <translation id="397105322502079400">Calculando...</translation>
 <translation id="3971764089670057203">Huellas digitales de esta llave de seguridad</translation>
 <translation id="3973005893595042880">El usuario no está permitido</translation>
+<translation id="3973062011568994448">Para importar contraseñas, selecciona un archivo CSV.</translation>
 <translation id="3973660817924297510">Comprobando contraseñas (<ph name="CHECKED_PASSWORDS" /> de <ph name="TOTAL_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">Usa Siguiente para avanzar en la pantalla</translation>
 <translation id="3975201861340929143">Explicación</translation>
@@ -3918,6 +3920,7 @@
 <translation id="4768332406694066911">Tienes certificados de estas organizaciones que te identifican</translation>
 <translation id="4770119228883592393">Permiso solicitado, pulsa ⌘ + Opción + flecha hacia abajo para responder</translation>
 <translation id="4773112038801431077">Actualizar Linux</translation>
+<translation id="4774337692467964393">Si Smart Lock está activado, no tendrás que introducir ni un PIN ni una contraseña</translation>
 <translation id="4775142426314270551">Ayuda a mejorar las funciones y el rendimiento de Chrome y Chrome OS enviando automáticamente a Google informes sobre fallos, así como datos de uso y diagnóstico. Algunos datos agregados también ayudarán a las aplicaciones Android y a los partners de Google. Si el ajuste Actividad en la Web y en Aplicaciones está activado en la cuenta de Google de tu hijo/a, es posible que los datos de Android de tu hijo/a se guarden en la cuenta de Google de tu hijo/a.</translation>
 <translation id="477647109558161443">Crear un acceso directo del escritorio</translation>
 <translation id="4776594120007763294">Para añadir una página a la lista y leerla más tarde, haz clic en el botón</translation>
@@ -3967,6 +3970,7 @@
 <translation id="4820236583224459650">Definir como ticket activo</translation>
 <translation id="4821935166599369261">Perfiles &amp;habilitados</translation>
 <translation id="4823484602432206655">Leer y cambiar la configuración del dispositivo y del usuario</translation>
+<translation id="4823894915586516138">El PIN o la contraseña protegerán tus datos en este <ph name="DEVICE_TYPE" />, incluida cualquier información a la accedas desde tu teléfono</translation>
 <translation id="4824037980212326045">Copia de seguridad y restauración de Linux</translation>
 <translation id="4824958205181053313">¿Quieres cancelar la sincronización?</translation>
 <translation id="4827675678516992122">No se ha podido conectar</translation>
@@ -4598,6 +4602,7 @@
 <translation id="5466374726908360271">Pe&amp;gar y buscar "<ph name="SEARCH_TERMS" />"</translation>
 <translation id="5467207440419968613">Con bloqueo: <ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /></translation>
 <translation id="5468173180030470402">Buscando sistemas de archivos compartidos</translation>
+<translation id="5468881191994555667">Seleccionar archivo</translation>
 <translation id="5469852975082458401">Puedes desplazarte por las páginas con un cursor de texto. Pulsa F7 para desactivar esta opción.</translation>
 <translation id="5470735824776589490">Es necesario reiniciar el dispositivo antes de poder restablecerlo con Powerwash. <ph name="LINK_BEGIN" />Más información<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">¡Hola! Soy tu voz de la conversión de texto a voz.</translation>
@@ -5623,6 +5628,7 @@
 <translation id="648927581764831596">Ningún medio disponible</translation>
 <translation id="6490471652906364588">Dispositivo USB-C (puerto derecho)</translation>
 <translation id="6491376743066338510">Error de autorización</translation>
+<translation id="6492396476180293140">Cámara interna desactivada mediante interruptor de hardware</translation>
 <translation id="6494327278868541139">Mostrar detalles de la protección mejorada</translation>
 <translation id="6494445798847293442">No es una entidad emisora de certificados</translation>
 <translation id="6494974875566443634">Personalización</translation>
@@ -6328,6 +6334,7 @@
 <translation id="7191159667348037">Impresora desconocida (USB)</translation>
 <translation id="7193051357671784796">Tu organización ha añadido esta aplicación. Reinicia la aplicación para terminar de instalarla.</translation>
 <translation id="7193374945610105795">No hay contraseñas guardadas de <ph name="ORIGIN" /></translation>
+<translation id="7194873994243265344">Tu organización ha bloqueado este archivo porque está cifrado. Pídele al propietario que lo descifre.</translation>
 <translation id="7196913789568937443">Crear copia de seguridad en Google Drive. Cambia de dispositivo o restaura tus datos fácilmente en cualquier momento. La copia de seguridad incluye datos de las aplicaciones. Tus copias de seguridad se suben a Google y se cifran con la contraseña de tu cuenta de Google. <ph name="BEGIN_LINK1" />Más información<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Disfruta de la Búsqueda de Google y las funciones inteligentes de Google siempre que navegues</translation>
 <translation id="719791532916917144">Acceso directo</translation>
@@ -6346,6 +6353,7 @@
 <translation id="7211783048245131419">Aún no se ha asignado ningún interruptor</translation>
 <translation id="7212097698621322584">Introduce tu PIN actual para cambiarlo. Si no sabes cuál es tu PIN, tendrás que restablecer la llave de seguridad y crear un nuevo PIN.</translation>
 <translation id="7213903639823314449">Buscador utilizado en la barra de direcciones</translation>
+<translation id="721490496276866468">Importar contraseñas</translation>
 <translation id="7216595297012131718">Ordena los idiomas según tus preferencias</translation>
 <translation id="7219473482981809164">Hemos encontrado varios perfiles disponibles para descargar. Selecciona los que quieras descargar antes de continuar.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{No hay contraseñas poco seguras}=1{1 contraseña poco segura}other{{NUM_WEAK} contraseñas poco seguras}}</translation>
@@ -6979,6 +6987,7 @@
 <translation id="7826190688224781865">Código de ID de la tienda</translation>
 <translation id="7826249772873145665">Depuración ADB inhabilitada</translation>
 <translation id="7826254698725248775">Identificador de dispositivo en conflicto.</translation>
+<translation id="7828642077514646543">Error: no se ha podido decodificar el certificado</translation>
 <translation id="7828731929332799387">Se eliminarán todas las cookies y los datos de sitios disponibles en contextos de terceros. ¿Quieres continuar?</translation>
 <translation id="7829877209233347340">Pídele a tu padre o a tu madre que inicie sesión para permitir que se añada una cuenta de centro educativo</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7941,6 +7950,7 @@
 <translation id="8775653927968399786">{0,plural, =1{Tu <ph name="DEVICE_TYPE" /> se bloqueará automáticamente dentro de # segundo.
 <ph name="DOMAIN" /> requiere que mantengas insertada tu tarjeta inteligente.}other{Tu <ph name="DEVICE_TYPE" /> se bloqueará automáticamente dentro de # segundos.
 <ph name="DOMAIN" /> requiere que mantengas insertada tu tarjeta inteligente.}}</translation>
+<translation id="8776294611668764629">Tu organización ha bloqueado este archivo porque es demasiado grande para realizar una comprobación de seguridad. Puedes abrir archivos de hasta 50 MB.</translation>
 <translation id="8777628254805677039">contraseña raíz</translation>
 <translation id="8779944680596936487">Los sitios solo pueden usar las cookies para ver tu actividad de navegación en el propio sitio</translation>
 <translation id="8780123805589053431">Obtener descripciones de imágenes de Google</translation>
diff --git a/chrome/app/resources/generated_resources_fr-CA.xtb b/chrome/app/resources/generated_resources_fr-CA.xtb
index 202906e..b22f183e 100644
--- a/chrome/app/resources/generated_resources_fr-CA.xtb
+++ b/chrome/app/resources/generated_resources_fr-CA.xtb
@@ -2575,6 +2575,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> pourra consulter <ph name="FILENAME" /></translation>
 <translation id="3445047461171030979">Réponses rapides de l'Assistant Google</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
+<translation id="344537926140058498">Votre organisation a bloqué ce fichier parce que son contenu est confidentiel ou dangereux. Demandez à son propriétaire de résoudre ce problème.</translation>
 <translation id="3445925074670675829">Appareil USB-C</translation>
 <translation id="3446274660183028131">Veuillez lancer Parallels Desktop pour installer Windows.</translation>
 <translation id="344630545793878684">Lire vos données sur un nombre défini de sites Web</translation>
@@ -3133,6 +3134,7 @@
 <translation id="397105322502079400">Calcul en cours...</translation>
 <translation id="3971764089670057203">Empreintes digitales sur cette clé de sécurité</translation>
 <translation id="3973005893595042880">L'utilisateur n'est pas autorisé</translation>
+<translation id="3973062011568994448">Pour importer des mots de passe, sélectionnez un fichier CSV.</translation>
 <translation id="3973660817924297510">Vérification des mots de passe en cours… (<ph name="CHECKED_PASSWORDS" /> sur <ph name="TOTAL_PASSWORDS" />)</translation>
 <translation id="3974514184580396500">Utilisez « Suivant » pour déplacer votre point focal vers l'avant sur l'écran</translation>
 <translation id="3975201861340929143">Explication</translation>
@@ -4601,6 +4603,7 @@
 <translation id="5466374726908360271">Coller et rechercher « <ph name="SEARCH_TERMS" /> »</translation>
 <translation id="5467207440419968613">Autorisations bloquées : <ph name="PERMISSION_1" /> et <ph name="PERMISSION_2" /></translation>
 <translation id="5468173180030470402">Recherche de partages de fichiers en cours…</translation>
+<translation id="5468881191994555667">Sélectionner un fichier</translation>
 <translation id="5469852975082458401">Vous pouvez parcourir les pages à l'aide d'un curseur de texte. Appuyez sur F7 pour désactiver ce mode.</translation>
 <translation id="5470735824776589490">Vous devez redémarrer votre appareil avant de pouvoir faire une réinitialisation Powerwash. <ph name="LINK_BEGIN" />En savoir plus<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Bonjour! Je suis votre voix pour la synthèse vocale.</translation>
@@ -6333,6 +6336,7 @@
 <translation id="7191159667348037">Imprimante inconnue (USB)</translation>
 <translation id="7193051357671784796">Cette application a été ajoutée par votre organisation Redémarrez-la pour terminer l'installation.</translation>
 <translation id="7193374945610105795">Aucun mot de passe enregistré pour <ph name="ORIGIN" /></translation>
+<translation id="7194873994243265344">Votre organisation a bloqué ce fichier parce qu'il est chiffré. Demandez à son propriétaire de le déchiffrer.</translation>
 <translation id="7196913789568937443">Sauvegarder sur Google Disque. Restaurez vos données aisément ou changez d'appareil à tout moment. Votre sauvegarde comprend les données des applications. Vos sauvegardes sont téléversées dans les serveurs de Google et sont chiffrées en utilisant le mot de passe de votre compte Google. <ph name="BEGIN_LINK1" />En savoir plus<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Obtenez la recherche Google et les fonctionnalités intelligentes de Google chaque fois que vous naviguez</translation>
 <translation id="719791532916917144">Raccourci-clavier</translation>
@@ -6351,6 +6355,7 @@
 <translation id="7211783048245131419">Aucun commutateur n'a été attribué</translation>
 <translation id="7212097698621322584">Entrez votre NIP actuel pour le modifier. Si vous ne connaissez pas votre NIP, vous devrez réinitialiser la clé de sécurité, puis créer un nouveau NIP.</translation>
 <translation id="7213903639823314449">Moteur de recherche utilisé dans la barre d'adresse</translation>
+<translation id="721490496276866468">Importer des mots de passe</translation>
 <translation id="7216595297012131718">Classer les langues en fonction de vos préférences</translation>
 <translation id="7219473482981809164">Plusieurs profils peuvent être téléchargés. Sélectionnez ceux que vous voulez télécharger avant de continuer.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Aucun mot de passe faible}=1{1 mot de passe faible}one{{NUM_WEAK} mot de passe faible}other{{NUM_WEAK} mots de passe faibles}}</translation>
@@ -6984,6 +6989,7 @@
 <translation id="7826190688224781865">Code d'identification du magasin-détaillant</translation>
 <translation id="7826249772873145665">Le débogage PDA est désactivé</translation>
 <translation id="7826254698725248775">Identifiant d'appareil en conflit.</translation>
+<translation id="7828642077514646543">Erreur : impossible de décoder le certificat</translation>
 <translation id="7828731929332799387">Cela supprimera tous les témoins et les données des sites proposés dans les contextes tiers. Voulez-vous continuer?</translation>
 <translation id="7829877209233347340">Demande à un parent de se connecter afin d'accorder l'autorisation d'ajouter un compte scolaire</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7946,6 +7952,7 @@
 <ph name="DOMAIN" /> vous demande de laisser votre carte à puce insérée.}one{Votre <ph name="DEVICE_TYPE" /> sera automatiquement verrouillé dans # seconde.
 <ph name="DOMAIN" /> vous demande de laisser votre carte à puce insérée.}other{Votre <ph name="DEVICE_TYPE" /> sera automatiquement verrouillé dans # secondes.
 <ph name="DOMAIN" /> vous demande de laisser votre carte à puce insérée.}}</translation>
+<translation id="8776294611668764629">Votre organisation a bloqué ce fichier parce qu'il est trop volumineux pour faire l'objet d'une vérification de sécurité. Vous ne pouvez pas ouvrir de fichiers de plus de 50 Mo.</translation>
 <translation id="8777628254805677039">mot de passe racine</translation>
 <translation id="8779944680596936487">Les sites ont uniquement recours aux témoins pour connaître votre activité de navigation sur leurs propres pages</translation>
 <translation id="8780123805589053431">Obtenir les descriptions d'image de Google</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb
index 0c930491..9a9226f 100644
--- a/chrome/app/resources/generated_resources_fr.xtb
+++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -2574,6 +2574,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> pourra consulter <ph name="FILENAME" /></translation>
 <translation id="3445047461171030979">Réponses rapides sur l'Assistant Google</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
+<translation id="344537926140058498">Votre organisation a bloqué ce fichier en raison de son contenu sensible ou dangereux. Demandez à son propriétaire de résoudre ce problème.</translation>
 <translation id="3445925074670675829">Appareil USB de type C</translation>
 <translation id="3446274660183028131">Veuillez lancer Parallels Desktop pour installer Windows.</translation>
 <translation id="344630545793878684">Lire vos données sur plusieurs sites web</translation>
@@ -3132,6 +3133,7 @@
 <translation id="397105322502079400">Calcul en cours…</translation>
 <translation id="3971764089670057203">Empreintes sur cette clé de sécurité</translation>
 <translation id="3973005893595042880">Utilisateur non autorisé</translation>
+<translation id="3973062011568994448">Pour importer des mots de passe, sélectionnez un fichier CSV.</translation>
 <translation id="3973660817924297510">Vérification des mots de passe (<ph name="CHECKED_PASSWORDS" /> sur <ph name="TOTAL_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">Utilisez "Suivant" pour sélectionner l'élément suivant à l'écran</translation>
 <translation id="3975201861340929143">Explication</translation>
@@ -4600,6 +4602,7 @@
 <translation id="5466374726908360271">Coller et chercher "<ph name="SEARCH_TERMS" />"</translation>
 <translation id="5467207440419968613">Autorisations bloquées : <ph name="PERMISSION_1" /> et <ph name="PERMISSION_2" /></translation>
 <translation id="5468173180030470402">Recherche de partages de fichiers…</translation>
+<translation id="5468881191994555667">Sélectionner un fichier</translation>
 <translation id="5469852975082458401">Vous pouvez parcourir les pages à l'aide d'un curseur de texte. Pour désactiver la navigation au clavier, appuyez sur F7.</translation>
 <translation id="5470735824776589490">Vous devez redémarrer votre appareil avant de pouvoir le réinitialiser avec le Powerwash. <ph name="LINK_BEGIN" />En savoir plus<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Bonjour ! Je suis la voix de votre synthèse vocale.</translation>
@@ -6333,6 +6336,7 @@
 <translation id="7191159667348037">Imprimante inconnue (USB)</translation>
 <translation id="7193051357671784796">Cette application a été ajoutée par votre organisation. Redémarrez-la pour terminer l'installation.</translation>
 <translation id="7193374945610105795">Aucun mot de passe enregistré pour <ph name="ORIGIN" /></translation>
+<translation id="7194873994243265344">Votre organisation a bloqué ce fichier, car il est chiffré. Demandez à son propriétaire de le déchiffrer.</translation>
 <translation id="7196913789568937443">Sauvegarder dans Google Drive. Restaurez vos données ou changez d'appareil facilement et à tout moment. La sauvegarde inclut les données d'applications. Vos sauvegardes sont importées dans Google et chiffrées à l'aide du mot de passe de votre compte Google. <ph name="BEGIN_LINK1" />En savoir plus<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Naviguez sur le Web en bénéficiant des fonctionnalités intelligentes de Google et de la recherche Google</translation>
 <translation id="719791532916917144">Raccourci clavier</translation>
@@ -6351,6 +6355,7 @@
 <translation id="7211783048245131419">Aucune action n'a encore été associée à un contacteur</translation>
 <translation id="7212097698621322584">Saisissez votre code actuel pour pouvoir le modifier. Si vous ne vous en souvenez plus, vous devez réinitialiser la clé de sécurité, puis créer un autre code.</translation>
 <translation id="7213903639823314449">Moteur de recherche utilisé dans la barre d'adresse</translation>
+<translation id="721490496276866468">Importer des mots de passe</translation>
 <translation id="7216595297012131718">Classer les langues selon vos préférences</translation>
 <translation id="7219473482981809164">Plusieurs profils sont disponibles. Sélectionnez ceux que vous voulez télécharger avant de continuer.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Aucun mot de passe peu sécurisé}=1{1 mot de passe peu sécurisé}one{{NUM_WEAK} mot de passe peu sécurisé}other{{NUM_WEAK} mots de passe peu sécurisés}}</translation>
@@ -6984,6 +6989,7 @@
 <translation id="7826190688224781865">Code de l'ID du marchand-magasin</translation>
 <translation id="7826249772873145665">Débogage ADB désactivé</translation>
 <translation id="7826254698725248775">Identifiant de l'appareil en conflit.</translation>
+<translation id="7828642077514646543">Erreur : Impossible de décoder le certificat</translation>
 <translation id="7828731929332799387">Cette action supprimera l'ensemble des cookies et données de sites disponibles dans des contextes tiers. Voulez-vous continuer ?</translation>
 <translation id="7829877209233347340">Demande à un parent de t'autoriser à ajouter un compte scolaire</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7947,6 +7953,7 @@
 <ph name="DOMAIN" /> vous demande de laisser votre carte à puce insérée.}one{Votre appareil (<ph name="DEVICE_TYPE" />) va être automatiquement verrouillé dans # seconde.
 <ph name="DOMAIN" /> vous demande de laisser votre carte à puce insérée.}other{Votre appareil (<ph name="DEVICE_TYPE" />) va être automatiquement verrouillé dans # secondes.
 <ph name="DOMAIN" /> vous demande de laisser votre carte à puce insérée.}}</translation>
+<translation id="8776294611668764629">Votre organisation a bloqué ce fichier, car il est trop volumineux pour un contrôle de sécurité. Vous ne pouvez pas ouvrir de fichiers de plus de 50 Mo.</translation>
 <translation id="8777628254805677039">mot de passe racine</translation>
 <translation id="8779944680596936487">Les sites ne peuvent utiliser les cookies que pour voir votre activité de navigation sur ces sites</translation>
 <translation id="8780123805589053431">Obtenir des descriptions d'images de Google</translation>
diff --git a/chrome/app/resources/generated_resources_gl.xtb b/chrome/app/resources/generated_resources_gl.xtb
index 4e830760..57a3e44 100644
--- a/chrome/app/resources/generated_resources_gl.xtb
+++ b/chrome/app/resources/generated_resources_gl.xtb
@@ -2571,6 +2571,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> poderá ver <ph name="FILENAME" /></translation>
 <translation id="3445047461171030979">Respostas rápidas do Asistente de Google</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
+<translation id="344537926140058498">A túa organización bloqueou este ficheiro porque inclúe contido confidencial ou perigoso. Pídelle ao seu propietario que o corrixa.</translation>
 <translation id="3445925074670675829">Dispositivo USB‑C</translation>
 <translation id="3446274660183028131">Inicia Parallels Desktop para instalar Windows.</translation>
 <translation id="344630545793878684">Lectura dos teus datos nun determinado número de sitios web</translation>
@@ -3129,6 +3130,7 @@
 <translation id="397105322502079400">Calculando...</translation>
 <translation id="3971764089670057203">Impresións dixitais nesta chave de seguranza</translation>
 <translation id="3973005893595042880">O usuario non está permitido</translation>
+<translation id="3973062011568994448">Para importar os contrasinais, selecciona un ficheiro CSV.</translation>
 <translation id="3973660817924297510">Comprobando contrasinais (<ph name="CHECKED_PASSWORDS" /> de <ph name="TOTAL_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">Utiliza Seguinte para mover o enfoque ao seguinte elemento da pantalla</translation>
 <translation id="3975201861340929143">Explicación</translation>
@@ -4597,6 +4599,7 @@
 <translation id="5466374726908360271">Pegar e bu&amp;scar "<ph name="SEARCH_TERMS" />"</translation>
 <translation id="5467207440419968613">Bloqueáronse os seguintes permisos: <ph name="PERMISSION_1" /> e <ph name="PERMISSION_2" /></translation>
 <translation id="5468173180030470402">Buscando ficheiros compartidos</translation>
+<translation id="5468881191994555667">Escoller ficheiro</translation>
 <translation id="5469852975082458401">Podes navegar polas páxinas cun cursor de texto. Preme F7 para desactivar esta función.</translation>
 <translation id="5470735824776589490">É necesario reiniciar o dispositivo para poder restablecelo cun Powerwash. <ph name="LINK_BEGIN" />Máis información<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Ola! Son a túa voz de conversión de texto a voz.</translation>
@@ -6324,6 +6327,7 @@
 <translation id="7191159667348037">Impresora descoñecida (USB)</translation>
 <translation id="7193051357671784796">Esta aplicación engadiuna a túa organización. Reiníciaa para acabar de instalala.</translation>
 <translation id="7193374945610105795">Non se gardou ningún contrasinal para <ph name="ORIGIN" /></translation>
+<translation id="7194873994243265344">A túa organización bloqueou este ficheiro porque está encriptado. Pídelle ao seu propietario que o desencripte.</translation>
 <translation id="7196913789568937443">Crear copia de seguranza en Google Drive. Restaura facilmente os datos ou cambia de dispositivo en calquera momento. A copia de seguranza inclúe os datos das aplicacións. As copias de seguranza cárganse en Google e encríptanse co contrasinal da túa Conta de Google. <ph name="BEGIN_LINK1" />Máis información<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Goza da Busca e da tecnoloxía de Google cada vez que navegues</translation>
 <translation id="719791532916917144">Atallo de teclado</translation>
@@ -6342,6 +6346,7 @@
 <translation id="7211783048245131419">Aínda non se asignou ningún interruptor</translation>
 <translation id="7212097698621322584">Introduce o teu PIN actual para cambialo. Se non sabes cal é, deberás restablecer a chave de seguranza e, despois, crear un novo.</translation>
 <translation id="7213903639823314449">O motor de busca que se utiliza na barra de enderezos</translation>
+<translation id="721490496276866468">Importar contrasinais</translation>
 <translation id="7216595297012131718">Ordena os idiomas en función das túas preferencias</translation>
 <translation id="7219473482981809164">Atopamos varios perfís dispoñibles para a súa descarga. Para continuar, selecciona os que queres descargar.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Non hai contrasinais pouco seguros}=1{1 contrasinal pouco seguro}other{{NUM_WEAK} contrasinais pouco seguros}}</translation>
@@ -6975,6 +6980,7 @@
 <translation id="7826190688224781865">Código de identificación da tenda retallista</translation>
 <translation id="7826249772873145665">Desactivouse a depuración de ADB</translation>
 <translation id="7826254698725248775">Identificador de dispositivos en conflito.</translation>
+<translation id="7828642077514646543">Produciuse un erro: non se puido descodificar o certificado</translation>
 <translation id="7828731929332799387">Ao realizar esta acción, eliminaranse todas as cookies e os datos dos sitios de terceiros. Queres continuar?</translation>
 <translation id="7829877209233347340">Pídelle a teu pai ou a túa nai que inicie sesión e che dea permiso para engadir unha conta de centro educativo</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7935,6 +7941,7 @@
 <translation id="8775653927968399786">{0,plural, =1{O teu dispositivo (<ph name="DEVICE_TYPE" />) bloquearase automaticamente en # segundo.
 <ph name="DOMAIN" /> require que manteñas a tarxeta intelixente inserida.}other{O teu dispositivo (<ph name="DEVICE_TYPE" />) bloquearase automaticamente en # segundos.
 <ph name="DOMAIN" /> require que manteñas a tarxeta intelixente inserida.}}</translation>
+<translation id="8776294611668764629">A túa organización bloqueou este ficheiro porque é demasiado grande para realizar unha comprobación de seguranza. Podes abrir ficheiros de ata 50 MB.</translation>
 <translation id="8777628254805677039">contrasinal raíz</translation>
 <translation id="8779944680596936487">Os distintos sitios só poden utilizar as cookies para consultar a actividade de navegación que levaches a cabo no seu propio sitio</translation>
 <translation id="8780123805589053431">Obter descricións de Google para as imaxes</translation>
diff --git a/chrome/app/resources/generated_resources_hy.xtb b/chrome/app/resources/generated_resources_hy.xtb
index b700102..d545563 100644
--- a/chrome/app/resources/generated_resources_hy.xtb
+++ b/chrome/app/resources/generated_resources_hy.xtb
@@ -2573,6 +2573,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> կայքը կկարողանա դիտել <ph name="FILENAME" /> ֆայլը</translation>
 <translation id="3445047461171030979">Google Օգնականի արագ պատասխաններ</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> րոպե</translation>
+<translation id="344537926140058498">Ձեր կազմակերպությունն արգելափակել է այս ֆայլը, քանի որ այն պարունակում է խիստ անձնական կամ վտանգավոր բովանդակություն։ Խնդրեք սեփականատիրոջը շտկել այդ խնդիրը։</translation>
 <translation id="3445925074670675829">USB-C սարք</translation>
 <translation id="3446274660183028131">Windows-ը տեղադրելու համար գործարկեք Parallels Desktop-ը։</translation>
 <translation id="344630545793878684">Կարդալ ձեր տվյալները մի շարք կայքերում</translation>
@@ -3131,6 +3132,7 @@
 <translation id="397105322502079400">Հաշվարկում…</translation>
 <translation id="3971764089670057203">Այս անվտանգության բանալու մատնահետքերը</translation>
 <translation id="3973005893595042880">Օգտատերն արգելված է</translation>
+<translation id="3973062011568994448">Գաղտնաբառերը ներմուծելու համար ընտրեք CSV ֆայլ։</translation>
 <translation id="3973660817924297510">Գաղտնաբառերը ստուգվում են (<ph name="CHECKED_PASSWORDS" />/<ph name="TOTAL_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">Էկրանին հաջորդ տարրը նշելու համար օգտագործեք «Հաջորդը» փոխանջատիչը</translation>
 <translation id="3975201861340929143">Բացատրություն</translation>
@@ -4601,6 +4603,7 @@
 <translation id="5466374726908360271">Տեղադրել և որոնել «<ph name="SEARCH_TERMS" />»</translation>
 <translation id="5467207440419968613">Արգելափակված թույլտվություններ՝ <ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /></translation>
 <translation id="5468173180030470402">Ընդհանուր ֆայլերի որոնում</translation>
+<translation id="5468881191994555667">Ընտրել ֆայլը</translation>
 <translation id="5469852975082458401">Դուք կարող եք մեկ էջից անցնել մյուսը տեսքտի նշորդի միջոցով։ Սեղմեք F7՝ անջատելու համար։</translation>
 <translation id="5470735824776589490">Պետք է վերագործարկեք սարքը՝ նախքան Powerwash կատարելը։ <ph name="LINK_BEGIN" />Իմանալ ավելին<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Ողջո՛ւյն: Ես տեքստի հնչեցման ձայնն եմ:</translation>
@@ -6330,6 +6333,7 @@
 <translation id="7191159667348037">Անհայտ տպիչ (USB)</translation>
 <translation id="7193051357671784796">Այս հավելվածն ավելացվել է ձեր կազմակերպության կողմից: Վերագործարկեք հավելվածը՝ տեղադրումն ավարտելու համար:</translation>
 <translation id="7193374945610105795"><ph name="ORIGIN" /> կայքի համար գաղտնաբառեր չեն պահվել</translation>
+<translation id="7194873994243265344">Ձեր կազմակերպությունն արգելափակել է այս ֆայլը, քանի որ այն գաղտնագրված է։ Խնդրեք սեփականատիրոջը վերծանել այն։</translation>
 <translation id="7196913789568937443">Կրկնօրինակ Google Drive-ում։ Արագ վերականգնեք ձեր տվյալները կամ տեղափոխեք այլ սարք: Կրկնօրինակները ներառում են հավելվածների տվյալները։ Կրկնօրինակները վերբեռնվում են Google և գաղտնագրվում ձեր Google հաշվի գաղտնաբառի միջոցով։ <ph name="BEGIN_LINK1" />Իմանալ ավելին<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Օգնեք Որոնմանը և Google-ի մյուս ծառայություններին ավելի լավ ճանաչել ձեզ</translation>
 <translation id="719791532916917144">Ստեղնային դյուրանցում</translation>
@@ -6348,6 +6352,7 @@
 <translation id="7211783048245131419">Նշանակված փոխանջատիչներ չկան</translation>
 <translation id="7212097698621322584">Մուտքագրեք ձեր ընթացիկ PIN կոդը՝ այն փոխելու համար: Եթե չգիտեք ձեր PIN կոդը, զրոյացրեք անվտանգության բանալու կարգավորումները և նշեք նոր PIN կոդ։</translation>
 <translation id="7213903639823314449">Հասցեագոտում օգտագործվող որոնողական համակարգը</translation>
+<translation id="721490496276866468">Ներմուծել գաղտնաբառերը</translation>
 <translation id="7216595297012131718">Դասավորեք լեզուներն ըստ ձեր նախընտրության</translation>
 <translation id="7219473482981809164">Մենք գտել ենք մի քանի պրոֆիլ, որոնք հասանելի են ներբեռնման համար։ Շարունակելուց առաջ ընտրեք պրոֆիլները, որոնք ուզում եք ներբեռնել։</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Թույլ գաղտնաբառեր չկան}=1{1 թույլ գաղտնաբառ}one{{NUM_WEAK} թույլ գաղտնաբառ}other{{NUM_WEAK} թույլ գաղտնաբառ}}</translation>
@@ -6980,6 +6985,7 @@
 <translation id="7826190688224781865">Մանրածախ խանութի ID-ի կոդ</translation>
 <translation id="7826249772873145665">ADB վրիպազերծումն անջատված է</translation>
 <translation id="7826254698725248775">Սարքերի նույնացուցիչների ընդհարում</translation>
+<translation id="7828642077514646543">Սխալ․ չհաջողվեց ապակոդավորել հավաստագիրը</translation>
 <translation id="7828731929332799387">Երրորդ կողմի բոլոր քուքիներն ու կայքերի տվյալները կջնջվեն։ Շարունակե՞լ։</translation>
 <translation id="7829877209233347340">Խնդրեք ծնողին մուտք գործել հաշիվ և ուսումնական հաշիվ ավելացնելու թույլտվություն տալ</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7941,6 +7947,7 @@
 Համաձայն <ph name="DOMAIN" /> տիրույթի կանոնների՝ խելացի քարտը պետք է տեղադրված լինի։}one{Ձեր <ph name="DEVICE_TYPE" /> սարքը # վայրկյանից ավտոմատ կկողպվի։
 Համաձայն <ph name="DOMAIN" /> տիրույթի կանոնների՝ խելացի քարտը պետք է տեղադրված լինի։}other{Ձեր <ph name="DEVICE_TYPE" /> սարքը # վայրկյանից ավտոմատ կկողպվի։
 Համաձայն <ph name="DOMAIN" /> տիրույթի կանոնների՝ խելացի քարտը պետք է տեղադրված լինի։}}</translation>
+<translation id="8776294611668764629">Ձեր կազմակերպությունն արգելափակել է այս ֆայլը, քանի որ այն չափազանց մեծ է անվտանգության ստուգման համար։ Դուք կարող եք բացել մինչև 50 ՄԲ չափի ֆայլեր։</translation>
 <translation id="8777628254805677039">արմատային գաղտնաբառ</translation>
 <translation id="8779944680596936487">Կայքերը կարող են օգտագործել քուքիներ՝ միայն իրենց կայքերում ձեր գործողությունները հետագծելու համար։</translation>
 <translation id="8780123805589053431">Ստացեք պատկերների նկարագրությունները Google-ից</translation>
diff --git a/chrome/app/resources/generated_resources_kk.xtb b/chrome/app/resources/generated_resources_kk.xtb
index 05a7fac..f6fecb7 100644
--- a/chrome/app/resources/generated_resources_kk.xtb
+++ b/chrome/app/resources/generated_resources_kk.xtb
@@ -2569,6 +2569,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> домені <ph name="FILENAME" /> файлын көре алады.</translation>
 <translation id="3445047461171030979">Google Assistant жылдам жауаптары</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> минут</translation>
+<translation id="344537926140058498">Бұл файлда құпия немесе қауіпті мазмұн болғандықтан, ұйымыңыз оны бөгеді. Иесінен бұл мәселені шешуін сұраңыз.</translation>
 <translation id="3445925074670675829">USB-C құрылғысы</translation>
 <translation id="3446274660183028131">Windows жүйесін орнату үшін Parallels Desktop-ты іске қосыңыз.</translation>
 <translation id="344630545793878684">Көптеген веб-сайттардағы деректеріңізді оқу</translation>
@@ -3127,6 +3128,7 @@
 <translation id="397105322502079400">Есептелуде…</translation>
 <translation id="3971764089670057203">Осы қауіпсіздік кілтіндегі саусақ іздері</translation>
 <translation id="3973005893595042880">Пайдаланушыға рұқсат берілмеген.</translation>
+<translation id="3973062011568994448">Құпия сөздерді импорттау үшін CSV файлын таңдаңыз.</translation>
 <translation id="3973660817924297510">Құпия сөздерді (<ph name="CHECKED_PASSWORDS" />/<ph name="TOTAL_PASSWORDS" />) тексеру…</translation>
 <translation id="3974514184580396500">Экрандағы назарыңызды келесі элементке ауыстыру үшін "Келесі" түймесін пайдаланыңыз.</translation>
 <translation id="3975201861340929143">Түсіндірме</translation>
@@ -4595,6 +4597,7 @@
 <translation id="5466374726908360271">"<ph name="SEARCH_TERMS" />" сұрауын қою және іздеу</translation>
 <translation id="5467207440419968613"><ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /> бөгелді.</translation>
 <translation id="5468173180030470402">Ортақ каталогтер ізделіп жатыр.</translation>
+<translation id="5468881191994555667">Файлды таңдау</translation>
 <translation id="5469852975082458401">Мәтін курсорымен бір беттен екінші бетке өте аласыз. Оны өшіру үшін F7 пернесін басыңыз.</translation>
 <translation id="5470735824776589490">Powerwash арқылы қалпына келтіру үшін құрылғыңызды қайта іске қосу қажет. <ph name="LINK_BEGIN" />Толығырақ<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Сәлеметсіз бе! Мен сізге мәтінді дыбыстап беремін.</translation>
@@ -6322,6 +6325,7 @@
 <translation id="7191159667348037">Белгісіз принтер (USB)</translation>
 <translation id="7193051357671784796">Бұл қолданбаңызды ұйым енгізді. Қолданбаны орнатуды аяқтау үшін оны қайта қосыңыз.</translation>
 <translation id="7193374945610105795"><ph name="ORIGIN" /> сайты үшін ешқандай құпия сөз сақталмады</translation>
+<translation id="7194873994243265344">Бұл файл шифрланғандықтан, ұйымыңыз оны бөгеді. Иесінен шифрдан шығаруын сұраңыз.</translation>
 <translation id="7196913789568937443">Google Drive дискісіне сақтық көшірме жасау. Деректерді оңай қалпына келтіріп, кез келген уақытта бір құрылғыдан екіншісіне ауыса аласыз. Сақтық көшірмеде қолданба туралы деректер қамтылады. Сақтық көшірмелер Google-ға жүктеп салынады және Google аккаунтыңыздың құпия сөзі арқылы шифрланады. <ph name="BEGIN_LINK1" />Толығырақ<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Браузерді пайдаланған сайын Google Search және Google Smarts қызметтерін көру</translation>
 <translation id="719791532916917144">Перне тіркесімі</translation>
@@ -6340,6 +6344,7 @@
 <translation id="7211783048245131419">Әлі ешқандай ауыстырғыш тағайындалмады.</translation>
 <translation id="7212097698621322584">Қолданыстағы PIN кодын өзгерту үшін оны енгізіңіз. PIN кодыңызды білмесеңіз, оны бастапқы күйге қайтарып, жаңа PIN кодын жасаңыз.</translation>
 <translation id="7213903639823314449">Мекенжай жолағында пайдаланылатын іздеу жүйесі</translation>
+<translation id="721490496276866468">Құпия сөздерді импорттау</translation>
 <translation id="7216595297012131718">Тілдерге қалауыңызға сай тапсырыс беріңіз</translation>
 <translation id="7219473482981809164">Жүктеп алуға болатын бірнеше профиль таптық. Жалғастырмас бұрын, жүктеп алғыңыз келетіндерін таңдаңыз.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Оңай құпия сөздер жоқ.}=1{1 оңай құпия сөз бар.}other{{NUM_WEAK} оңай құпия сөз бар.}}</translation>
@@ -6973,6 +6978,7 @@
 <translation id="7826190688224781865">Бөлшек сатушы дүкенінің идентификатор коды</translation>
 <translation id="7826249772873145665">ADB түзетуі өшірілді</translation>
 <translation id="7826254698725248775">Құрылғы идентификаторы сәйкес келмейді.</translation>
+<translation id="7828642077514646543">Қате: сертификаттың кодын ашу мүмкін емес.</translation>
 <translation id="7828731929332799387">Бөгде сайттардағы cookie файлдары мен сайт деректерінің барлығы жойылады. Жалғастырғыңыз келе ме?</translation>
 <translation id="7829877209233347340">Ата-анаңыздан кіріп, мектеп аккаунтын енгізуге рұқсат беруін сұраңыз.</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7933,6 +7939,7 @@
 <translation id="8775653927968399786">{0,plural, =1{<ph name="DEVICE_TYPE" /> құрылғыңыз # секундтан кейін автоматты түрде құлыпталады.
 <ph name="DOMAIN" /> домені смарт картаңызды салып жүруіңізді талап етеді.}other{<ph name="DEVICE_TYPE" /> құрылғыңыз # секундтан кейін автоматты түрде құлыпталады.
 <ph name="DOMAIN" /> домені смарт картаңызды салып жүруіңізді талап етеді.}}</translation>
+<translation id="8776294611668764629">Бұл файл қауіпсіздік тексерісі үшін тым үлкен болғандықтан, ұйымыңыз оны бөгеді. 50 MБ-қа дейінгі файлдарды аша аласыз.</translation>
 <translation id="8777628254805677039">түбірлік құпия сөз</translation>
 <translation id="8779944680596936487">Сайттар cookie файлдарды тек өз сайттарындағы браузерді қолдану мәліметіңізді көру үшін қолдана алады.</translation>
 <translation id="8780123805589053431">Google-дан кескін сипаттамаларын алу</translation>
diff --git a/chrome/app/resources/generated_resources_km.xtb b/chrome/app/resources/generated_resources_km.xtb
index 534d84fd..529dae2 100644
--- a/chrome/app/resources/generated_resources_km.xtb
+++ b/chrome/app/resources/generated_resources_km.xtb
@@ -1923,6 +1923,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{លុប​កម្មវិធី​ដែល​មិន​អាចប្រើបាន 1 ចេញ}other{លុប​កម្មវិធី​ដែល​មិន​អាចប្រើបាន # ចេញ}}</translation>
 <translation id="2776560192867872731">ប្ដូរ​ឈ្មោះឧបករណ៍​សម្រាប់ <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">លុបទម្រង់ផ្ទុកនេះ</translation>
+<translation id="2778471504622896352">បញ្ចូល​កម្មវិធី​បញ្ជាពីចម្ងាយ​ទៅ​ក្នុង​កម្មវិធី​ចាប់ផ្ដើម ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">មានបញ្ហាក្នុង​ការដំឡើង​កម្មវិធី Linux</translation>
 <translation id="2783298271312924866">ត្រូវបានទាញយក</translation>
@@ -3558,6 +3559,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> និងប៊ូតុងចុច <ph name="NUMBER_OF_OTHER_SWITCHES" /> ទៀត</translation>
 <translation id="439266289085815679">ការ​កំណត់​រចនាសម្ព័ន្ធ​ប៊្លូធូសត្រូវបាន​គ្រប់គ្រង​ដោយ <ph name="USER_EMAIL" /> ។</translation>
 <translation id="4392896746540753732">កែឯកសារកំណត់​រចនាសម្ព័ន្ធ</translation>
+<translation id="4393713825278446281">បានរក្សាទុក​ឧបករណ៍​ដែលផ្គូផ្គង​រហ័ស​ទៅ​ក្នុង <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">បិទដំណើរការ</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;បើកទាំងអស់}=1{&amp;បើកចំណាំ}other{&amp;បើកទាំងអស់ ({COUNT})}}</translation>
 <translation id="4397372003838952832">អ្នកនឹង​មិនចាំបាច់​ចងចាំ​ពាក្យសម្ងាត់​នេះទេ។ ពាក្យសម្ងាត់នេះ​នឹងត្រូវបាន​រក្សាទុកទៅ​ក្នុង <ph name="GOOGLE_PASSWORD_MANAGER" /> សម្រាប់ <ph name="EMAIL" />។</translation>
@@ -3788,6 +3790,7 @@
 <translation id="4615586811063744755">មិនបានជ្រើសរើសខូគីទេ</translation>
 <translation id="461661862154729886">ប្រភព​ថាមពល</translation>
 <translation id="4617001782309103936">ខ្លី​ពេក</translation>
+<translation id="4617019240346358451">ផ្ទុក​ទំព័រ​ឡើងវិញ ដើម្បីប្រើប្រាស់ "<ph name="EXTENSION_NAME" />"</translation>
 <translation id="4617270414136722281">ជម្រើស​កម្មវិធី​បន្ថែម</translation>
 <translation id="4617880081511131945">មិនអាចបង្កើតការ​តភ្ជាប់បានទេ</translation>
 <translation id="4619564267100705184">ផ្ទៀងផ្ទាត់ថា​ជាអ្នក</translation>
@@ -4003,6 +4006,7 @@
 <translation id="4833683849865011483">បានរកឃើញម៉ាស៊ីនបោះពុម្ព 1 ពីម៉ាស៊ីនមេបោះពុម្ព</translation>
 <translation id="4836504898754963407">គ្រប់គ្រងស្នាមម្រាមដៃ</translation>
 <translation id="4837128290434901661">ប្ដូរទៅការស្វែងរកនៅលើ Google វិញឬ?</translation>
+<translation id="4837165100461973682">ផ្ទុក​ទំព័រ​ឡើងវិញ ដើម្បីអនុវត្ត​ការផ្លាស់ប្ដូរ​របស់អ្នក</translation>
 <translation id="4837926214103741331">អ្នកមិនត្រូវបានអនុញ្ញាតឲ្យប្រើឧបករណ៍នេះទេ។ សូមទាក់ទងម្ចាស់ឧបករណ៍សម្រាប់ការអនុញ្ញាតចូល។</translation>
 <translation id="4837952862063191349">ដើម្បីដោះសោ ឬស្តារទិន្នន័យមូលដ្ឋានរបស់អ្នកឡើងវិញ សូមបញ្ចូលពាក្យសម្ងាត់ <ph name="DEVICE_TYPE" /> ចាស់របស់អ្នក។</translation>
 <translation id="4838170306476614339">មើលរូបថត មេឌៀ និងការជូនដំណឹង​របស់ទូរសព្ទអ្នក</translation>
@@ -4312,6 +4316,7 @@
 <translation id="5150254825601720210">ឈ្មោះម៉ាស៊ីនមេ SSL វិញ្ញបនប័ត្រ Netscape</translation>
 <translation id="5151354047782775295">បង្កើនទំហំផ្ទុកក្នុងថាស បើមិនដូច្នោះទេ ទិន្នន័យដែលបានជ្រើសនឹងត្រូវបានលុបដោយស្វ័យប្រវត្តិ</translation>
 <translation id="5153234146675181447">បំភ្លេចទូរសព្ទ</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">ការកំណត់កម្រិតខ្ពស់សម្រាប់ <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">ភាគីវិញ្ញាបនប័ត្រ</translation>
 <translation id="5155327081870541046">បញ្ចូល​ផ្លូវកាត់​សម្រាប់គេហទំព័រ​ដែលអ្នកចង់ស្វែងរក​ដូចជា "@bookmarks" នៅក្នុង​របារអាសយដ្ឋាន។ បន្ទាប់មក ចុច​ផ្លូវកាត់​ក្ដារចុច​ដែលអ្នកចង់ប្រើ រួចបញ្ចូល​ពាក្យ​ស្វែងរក​របស់អ្នក។</translation>
@@ -5948,6 +5953,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> ត្រូវបានបន្ថែមពីចម្ងាយ</translation>
 <translation id="6790820461102226165">បន្ថែមបុគ្គល...</translation>
 <translation id="6793604637258913070">ហាយឡាយ៍សញ្ញាអត្ថបទនៅពេលដែលវាបង្ហាញ ឬផ្លាស់ទី</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">ការស្កេន​ដោយស្វ័យប្រវត្តិ​អនុញ្ញាតឱ្យអ្នកផ្លាស់ទីកាត់​ធាតុនៅលើអេក្រង់​ដោយស្វ័យប្រវត្តិ។ នៅពេល​ធាតុត្រូវបានរំលេច សូមចុច “ជ្រើសរើស” ដើម្បីបើក​ដំណើរការវា។</translation>
 <translation id="6795884519221689054">ខ្លាឃ្មុំ​ផេនដា</translation>
 <translation id="6797493596609571643">អូ មានបញ្ហាអ្វីមួយកើតឡើង។</translation>
@@ -7821,6 +7827,7 @@
 <translation id="8642947597466641025">ធ្វើឲ្យអត្ថបទធំជាងមុន</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> អាច​បង្ក​គ្រោះថ្នាក់​។ ផ្ញើទៅ​កម្មវិធី​ការពារ​កម្រិតខ្ពស់​របស់ Google ដើម្បី​ស្កេន​ឬ?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{មិនមានខូគីទេ}=1{ខូគី 1 ត្រូវបាន​ទប់ស្កាត់}other{ខូគី # ត្រូវបាន​ទប់ស្កាត់}}</translation>
+<translation id="864423554496711319">បានរក្សាទុក​ឧបករណ៍​ទៅក្នុង​គណនី​របស់អ្នក</translation>
 <translation id="8644655801811752511">មិនអាចកំណត់​សោសុវត្ថិភាពនេះ​ឡើងវិញបានទេ។ សូមសាកល្បងកំណត់​សោសុវត្ថិភាពនេះ​ឡើងវិញភ្លាមៗ បន្ទាប់ពីដោតបញ្ចូលវាហើយ។</translation>
 <translation id="8645354835496065562">បន្ត​អនុញ្ញាត​ឱ្យចូលប្រើ​ឧបករណ៍​ចាប់សញ្ញា</translation>
 <translation id="8645920082661222035">ព្យាករ និងព្រមានអ្នកអំពី​ព្រឹត្តិការណ៍គ្រោះថ្នាក់ មុនពេលព្រឹត្តិការណ៍ទាំងនោះកើតឡើង</translation>
diff --git a/chrome/app/resources/generated_resources_ky.xtb b/chrome/app/resources/generated_resources_ky.xtb
index 0220e7e0..a4bd467 100644
--- a/chrome/app/resources/generated_resources_ky.xtb
+++ b/chrome/app/resources/generated_resources_ky.xtb
@@ -2588,6 +2588,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> <ph name="FILENAME" /> файлын көрө алат</translation>
 <translation id="3445047461171030979">Google Жардамчынын ыкчам жооптору</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> мүн.</translation>
+<translation id="344537926140058498">Бул файлда купуя же кооптуу маалымат болгондуктан, уюмуңуз аны бөгөттөп койду. Ээсинен файлды оңдоону сураныңыз.</translation>
 <translation id="3445925074670675829">USB-C түзмөгү</translation>
 <translation id="3446274660183028131">Windows'ту орнотуу үчүн Parallels Desktop кызматын иштетиңиз.</translation>
 <translation id="344630545793878684">Дайын-даректериңизди бир нече вебсайттан окуңуз</translation>
@@ -3146,6 +3147,7 @@
 <translation id="397105322502079400">Эсептелүүдө…</translation>
 <translation id="3971764089670057203">Бул коопсуздук ачкычы менен катталган манжа издери</translation>
 <translation id="3973005893595042880">Колдонуучуга уруксат жок</translation>
+<translation id="3973062011568994448">Сырсөздөрдү өткөрүп алуу үчүн CSV файлын тандаңыз.</translation>
 <translation id="3973660817924297510">Сырсөздөр өзгөртүлүүдө (<ph name="TOTAL_PASSWORDS" /> ичинен <ph name="CHECKED_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">Экрандагы элементтерге өтүү үчүн “Кийинки” баскычын басыңыз</translation>
 <translation id="3975201861340929143">Түшүндүрмө</translation>
@@ -4617,6 +4619,7 @@
 <translation id="5466374726908360271">"<ph name="SEARCH_TERMS" />" дегенди ча&amp;птап, издөө</translation>
 <translation id="5467207440419968613">Төмөнкүлөр бөгөттөлдү: <ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /></translation>
 <translation id="5468173180030470402">Бөлүшүлгөн файлдар изделүүдө</translation>
+<translation id="5468881191994555667">Файл тандоо</translation>
 <translation id="5469852975082458401">Барактарды текст курсору менен көрө аласыз. Өчүрүү үчүн F7 баскычын басыңыз.</translation>
 <translation id="5470735824776589490">Түзмөктү "жууп салып" баштапкы абалга келтирээрден мурун, аны өчүрүп күйгүзүү керек. <ph name="LINK_BEGIN" />Кеңири маалымат<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Салам! Мен сизге текстти окуп беремин.</translation>
@@ -6348,6 +6351,7 @@
 <translation id="7191159667348037">Белгисиз принтер (USB)</translation>
 <translation id="7193051357671784796">Бул колдонмону уюмуңуз кошту. Колдонмону орнотуп бүтүрүү үчүн, аны өчүрүп күйгүзүңүз.</translation>
 <translation id="7193374945610105795"><ph name="ORIGIN" /> үчүн бир да сырсөз сакталган эмес</translation>
+<translation id="7194873994243265344">Бул файл шифрленгендиктен, уюмуңуз аны бөгөттөп койду. Ээсинен анын шифрин чечмелөөнү сураныңыз.</translation>
 <translation id="7196913789568937443">Камдык көчүрмөнү Google Drive'га сактоо. Дайын-даректериңизди оңой эле калыбына келтирип, бир түзмөктөн экинчисине өткөрүүгө мүмкүнчүлүк берет. Көчүрмөдө колдонмо дайындары дагы сакталат. Камдык көчүрмөлөр Google'га жүктөлүп берилип, Google аккаунтуңуздун сырсөзү менен шифрленет. <ph name="BEGIN_LINK1" />Кеңири маалымат<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Google Издөө менен Google'дун акылдуу функцияларын серептеген сайын колдонуңуз</translation>
 <translation id="719791532916917144">Ыкчам баскыч</translation>
@@ -6366,6 +6370,7 @@
 <translation id="7211783048245131419">Азырынча бир да которгуч дайындала элек</translation>
 <translation id="7212097698621322584">Аны өзгөртүү үчүн учурдагы PIN кодуңузду киргизиңиз. Эгер PIN кодду билбесеңиз, коопсуздук ачкычын баштапкы абалга келтирип, анан жаңы PIN код түзүшүңүз керек.</translation>
 <translation id="7213903639823314449">Дарек тилкесинде колдонулган издөө каражаты</translation>
+<translation id="721490496276866468">Сырсөздөрдү өткөрүп алуу</translation>
 <translation id="7216595297012131718">Тилдерди өзүңүз каалагандай иреттештириңиз</translation>
 <translation id="7219473482981809164">Жүктөлүп алына турган бир нече профиль табылды. Улантуудан мурун, жүктөп алгыңыз келгендерин тандаңыз.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Начар сырсөздөр жок}=1{1 начар сырсөз бар}other{{NUM_WEAK} начар сырсөз бар}}</translation>
@@ -6999,6 +7004,7 @@
 <translation id="7826190688224781865">Чекене сатуучу дүкөндүн идентификатор коду</translation>
 <translation id="7826249772873145665">ADB аркылуу мүчүлүштүктөрдү оңдоо өчүрүлдү</translation>
 <translation id="7826254698725248775">Түзмөктүн идентификаторлору дал келбей калууда.</translation>
+<translation id="7828642077514646543">Ката: Тастыктаманын кодун чечмелөө мүмкүн эмес</translation>
 <translation id="7828731929332799387">Бул аракет үчүнчү тараптын булактарындагы бардык cookie файлдарын жана сайттын дайындарын өчүрөт. Улантасызбы?</translation>
 <translation id="7829877209233347340">Мектеп аккаунтун кошууга уруксат берүү үчүн ата-энеңден аккаунтуна кирүүнү суран</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7960,6 +7966,7 @@
 <translation id="8775653927968399786">{0,plural, =1{<ph name="DEVICE_TYPE" /> түзмөгүңүз # секунддан кийин автоматтык түрдө кулпуланат.
 <ph name="DOMAIN" /> эрежелери боюнча акылдуу картаңыз салынып турушу керек.}other{<ph name="DEVICE_TYPE" /> түзмөгүңүз # секунддан кийин автоматтык түрдө кулпуланат.
 <ph name="DOMAIN" /> эрежелери боюнча акылдуу картаңыз салынып турушу керек.}}</translation>
+<translation id="8776294611668764629">Бул файл коопсуздук текшерүүсү үчүн өтө чоң болгондуктан, уюмуңуз аны бөгөттөп койду. Көлөмү 50 Мб чейинки файлдарды ача аласыз.</translation>
 <translation id="8777628254805677039">тамыр сырсөзү</translation>
 <translation id="8779944680596936487">Сайттар cookie файлдары аркылуу гана сайтында көрүлгөн барактарды көрө алышат</translation>
 <translation id="8780123805589053431">Google'дан сүрөттөрдүн түшүндүрмөлөрүн алуу</translation>
diff --git a/chrome/app/resources/generated_resources_lo.xtb b/chrome/app/resources/generated_resources_lo.xtb
index b4835cf6..76f7180 100644
--- a/chrome/app/resources/generated_resources_lo.xtb
+++ b/chrome/app/resources/generated_resources_lo.xtb
@@ -2588,6 +2588,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> ຈະສາມາດເບິ່ງ <ph name="FILENAME" /> ໄດ້</translation>
 <translation id="3445047461171030979">ຄຳຕອບດ່ວນຂອງຜູ້ຊ່ວຍ Google</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> ນາທີ</translation>
+<translation id="344537926140058498">ອົງການຂອງທ່ານບລັອກໄຟລ໌ນີ້ໄວ້ເນື່ອງຈາກມັນມີເນື້ອຫາທີ່ລະອຽດອ່ອນ ຫຼື ເປັນອັນຕະລາຍ. ກະລຸນາຂໍໃຫ້ເຈົ້າຂອງມັນແກ້ໄຂ.</translation>
 <translation id="3445925074670675829">ອຸ​ປະ​ກອນ USB-C</translation>
 <translation id="3446274660183028131">ກະລຸນາເປີດໃຊ້ Parallels Desktop ເພື່ອຕິດຕັ້ງ Windows.</translation>
 <translation id="344630545793878684">ອ່ານ​ຂໍ້​ມູນ​ຂອງ​ທ່ານ​ຢູ່​ເທິງຫຼາຍ​ເວັບ​ໄຊ​ທ໌</translation>
@@ -3146,6 +3147,7 @@
 <translation id="397105322502079400">ກໍາລັງຄິດ​ໄລ່...</translation>
 <translation id="3971764089670057203">ລາຍນິ້ວມືໃນກະແຈຄວາມປອດໄພນີ້</translation>
 <translation id="3973005893595042880">ບໍ່ອະນຸຍາດຜູ້ໃຊ້</translation>
+<translation id="3973062011568994448">ເພື່ອນຳເຂົ້າລະຫັດຜ່ານ, ໃຫ້ເລືອກໄຟລ໌ CSV.</translation>
 <translation id="3973660817924297510">ກຳລັງກວດລະຫັດຜ່ານ (<ph name="CHECKED_PASSWORDS" /> ລາຍການຈາກທັງໝົດ <ph name="TOTAL_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">ໃຊ້ “ຕໍ່ໄປ” ເພື່ອຍ້າຍໂຟກັສຂອງທ່ານໄປທາງໜ້າຢູ່ໜ້າຈໍ</translation>
 <translation id="3975201861340929143">ຄຳອະທິບາຍ</translation>
@@ -4620,6 +4622,7 @@
 <translation id="5466374726908360271">ວາງໃສ່ ແລະ ຊອກຫາ “<ph name="SEARCH_TERMS" />”</translation>
 <translation id="5467207440419968613">ບລັອກ <ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /> ໄວ້ແລ້ວ</translation>
 <translation id="5468173180030470402">ກຳລັງຊອກຫາການແບ່ງປັນໄຟລ໌</translation>
+<translation id="5468881191994555667">ເລືອກໄຟລ໌</translation>
 <translation id="5469852975082458401">ທ່ານສາມາດໄປຫາໜ້າຕ່າງໆດ້ວຍເຄີເຊີຂໍ້ຄວາມ. ກົດ F7 ເພື່ອປິດ.</translation>
 <translation id="5470735824776589490">ຈໍາເປັນຕ້ອງຣິສະຕາດກ່ອນທີ່ຈະສາມາດຣີເຊັດອຸປະກອນຂອງທ່ານດ້ວຍ Powerwash ໄດ້. <ph name="LINK_BEGIN" />ສຶກສາເພີ່ມເຕີມ<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">ສະບາຍດີ! ຂ້ອຍແມ່ນສຽງການປ່ຽນຂໍ້ຄວາມເປັນສຽງເວົ້າຂອງເຈົ້າ.</translation>
@@ -6352,6 +6355,7 @@
 <translation id="7191159667348037">ເຄື່ອງພິມທີ່ບໍ່ຮູ້ຈັກ (USB)</translation>
 <translation id="7193051357671784796">ແອັບນີ້ຖືກເພີ່ມເຂົ້າໂດຍອົງການຂອງທ່ານ. ປິດເປີດແອັບຄືນໃໝ່ເພື່ອສຳເລັດການຕິດຕັ້ງມັນ.</translation>
 <translation id="7193374945610105795">ບໍ່ມີລະຫັດຜ່ານທີ່ບັນທຶກໄວ້ສຳລັບ <ph name="ORIGIN" /></translation>
+<translation id="7194873994243265344">ອົງການຂອງທ່ານບລັອກໄຟລ໌ນີ້ໄວ້ເນື່ອງຈາກມັນຖືກເຂົ້າລະຫັດ. ກະລຸນາຂໍໃຫ້ເຈົ້າຂອງມັນຖອດລະຫັດ.</translation>
 <translation id="7196913789568937443">ສຳຮອງຂໍ້ມູນໄວ້ໃນ Google Drive. ກູ້ຄືນຂໍ້ມູນຂອງທ່ານໄດ້ຢ່າງງ່າຍດາຍ ຫຼື ປ່ຽນອຸປະກອນໄດ້ທຸກເວລາ. ຂໍ້ມູນທີ່ສຳຮອງໄວ້ຂອງທ່ານຮວມເອົາຂໍ້ມູນແອັບ. ຂໍ້ມູນທີ່ສຳຮອງໄວ້ຂອງທ່ານຖືກອັບໂຫຼດໄວ້ໃນ Google ແລະ ເຂົ້າລະຫັດໄວ້ໂດຍໃຊ້ລະຫັດຜ່ານບັນຊີ Google ຂອງທ່ານ. <ph name="BEGIN_LINK1" />ສຶກສາເພີ່ມເຕີມ<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">ໃຊ້ Google ຊອກຫາ ແລະ Google ອັດສະລິຍະທຸກຄັ້ງທີ່ທ່ານທ່ອງເວັບ</translation>
 <translation id="719791532916917144">ຄີລັດ</translation>
@@ -6370,6 +6374,7 @@
 <translation id="7211783048245131419">ບໍ່ທັນກຳນົດປຸ່ມໃດເທື່ອ</translation>
 <translation id="7212097698621322584">ປ້ອນ PIN ປັດຈຸບັນຂອງທ່ານເພື່ອປ່ຽນມັນ. ຖ້າທ່ານບໍ່ຮູ້ຈັກ PIN ຂອງທ່ານ, ທ່ານຈະຈໍາເປັນຕ້ອງຣີເຊັດກະແຈຄວາມປອດໄພ, ແລ້ວສ້າງ PIN ໃໝ່.</translation>
 <translation id="7213903639823314449">ໂປຣແກຣມຊອກຫາທີ່ໃຊ້ໃນແຖບທີ່ຢູ່</translation>
+<translation id="721490496276866468">ນຳເຂົ້າລະຫັດຜ່ານ</translation>
 <translation id="7216595297012131718">ຈັດລຳດັບພາສາອີງຕາມການຕັ້ງຄ່າຂອງທ່ານ</translation>
 <translation id="7219473482981809164">ພວກເຮົາພົບເຫັນຫຼາຍໂປຣໄຟລ໌ທີ່ພ້ອມໃຫ້ດາວໂຫຼດ. ເລືອກໂປຣໄຟລ໌ທີ່ທ່ານຕ້ອງການດາວໂຫຼດກ່ອນທີ່ຈະດຳເນີນຕໍ່.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{ບໍ່ມີລະຫັດຜ່ານງ່າຍ}=1{ລະຫັດຜ່ານງ່າຍ 1 ລາຍການ}other{ລະຫັດຜ່ານງ່າຍ {NUM_WEAK} ລາຍການ}}</translation>
@@ -7002,6 +7007,7 @@
 <translation id="7826190688224781865">ລະຫັດ ID ຮ້ານຄ້າ-ຜູ້ຂາຍຍ່ອຍ</translation>
 <translation id="7826249772873145665">ປິດການນຳໃຊ້ການດີບັກ ADB ແລ້ວ</translation>
 <translation id="7826254698725248775">ຕົວລະບຸອຸປະກອນຂັດກັນ.</translation>
+<translation id="7828642077514646543">ຜິດພາດ: ບໍ່ສາມາດຖອດລະຫັດໃບຮັບຮອງໄດ້</translation>
 <translation id="7828731929332799387">ນີ້ຈະລຶບຄຸກກີ້ ແລະ ຂໍ້ມູນເວັບໄຊທັງໝົດທີ່ມີໃຫ້ໃນບໍລິບົດພາກສ່ວນທີສາມ. ທ່ານຕ້ອງການດຳເນີນການຕໍ່ບໍ?</translation>
 <translation id="7829877209233347340">ຂໍໃຫ້ພໍ່ແມ່ເຂົ້າສູ່ລະບົບເພື່ອອະນຸຍາດໃຫ້ເພີ່ມບັນຊີໂຮງຮຽນ</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7964,6 +7970,7 @@
 <translation id="8775653927968399786">{0,plural, =1{<ph name="DEVICE_TYPE" /> ຂອງທ່ານຈະຖືກລັອກໄວ້ໂດຍອັດຕະໂນມັດໃນ # ວິນາທີ.
 <ph name="DOMAIN" /> ກຳນົດໃຫ້ທ່ານສຽບບັດອັດສະລິຍະຄາໄວ້.}other{<ph name="DEVICE_TYPE" /> ຂອງທ່ານຈະຖືກລັອກໄວ້ໂດຍອັດຕະໂນມັດໃນ # ວິນາທີ.
 <ph name="DOMAIN" /> ກຳນົດໃຫ້ທ່ານສຽບບັດອັດສະລິຍະຄາໄວ້.}}</translation>
+<translation id="8776294611668764629">ອົງການຂອງທ່ານບລັອກໄຟລ໌ນີ້ໄວ້ເນື່ອງຈາກມັນໃຫຍ່ເກີນໄປສຳລັບການກວດສອບຄວາມປອດໄພ. ທ່ານສາມາດເປີດໄຟລ໌ໄດ້ບໍ່ເກີນ 50 MB.</translation>
 <translation id="8777628254805677039">ລະ​ຫັດ​ຜ່ານ​ພື້ນ​ຖານ</translation>
 <translation id="8779944680596936487">ເວັບໄຊຕ່າງໆສາມາດໃຊ້ຄຸກກີ້ເພື່ອເບິ່ງການເຄື່ອນໄຫວການທ່ອງເວັບຂອງທ່ານຢູ່ເວັບໄຊຂອງພວກມັນເອງໄດ້ເທົ່ານັ້ນ</translation>
 <translation id="8780123805589053431">ຮັບລາຍລະອຽດຮູບພາບຈາກ Google</translation>
diff --git a/chrome/app/resources/generated_resources_lt.xtb b/chrome/app/resources/generated_resources_lt.xtb
index a4614c1a..84ad8616 100644
--- a/chrome/app/resources/generated_resources_lt.xtb
+++ b/chrome/app/resources/generated_resources_lt.xtb
@@ -3940,6 +3940,7 @@
 <translation id="4768332406694066911">Turite jus identifikuojančius sertifikatus iš šių organizacijų</translation>
 <translation id="4770119228883592393">Pateikta užklausa dėl leidimo; paspauskite ⌘ + „Option“ + žemyn, kad atsakytumėte</translation>
 <translation id="4773112038801431077">„Linux“ naujovinimas</translation>
+<translation id="4774337692467964393">Jei „Smart Lock“ įjungta, PIN kodo ar slaptažodžio įvesti nereikia</translation>
 <translation id="4775142426314270551">Padėkite tobulinti „Chrome“ ir „Chrome“ OS funkcijas bei našumą automatiškai siųsdami strigčių ataskaitas ir diagnostikos bei naudojimo duomenis į sistemą „Google“. Be to, tam tikri sukaupti duomenys bus naudingi „Android“ programoms ir „Google“ partneriams. Jei Žiniatinklio ir programų veiklos nustatymas įjungtas vaiko „Google“ paskyroje, vaiko „Android“ duomenys gali būti išsaugoti jo „Google“ paskyroje.</translation>
 <translation id="477647109558161443">Sukurti darbalaukio šaukinį</translation>
 <translation id="4776594120007763294">Jei norite pridėti puslapį, kad galėtumėte skaityti vėliau, spustelėkite mygtuką</translation>
@@ -3989,6 +3990,7 @@
 <translation id="4820236583224459650">Nustatyti kaip aktyvų bilietą</translation>
 <translation id="4821935166599369261">&amp;Profiliavimas įgalintas</translation>
 <translation id="4823484602432206655">Skaityti ir keisti naudotojo bei įrenginio nustatymus</translation>
+<translation id="4823894915586516138">Šis PIN kodas arba slaptažodis apsaugo jūsų duomenis šiame „<ph name="DEVICE_TYPE" />“ įrenginyje, įskaitant bet kokią informaciją, kurią pasiekiate iš savo telefono</translation>
 <translation id="4824037980212326045">„Linux“ atsarginės kopijos kūrimas ir atkūrimas</translation>
 <translation id="4824958205181053313">Atšaukti sinchronizavimą?</translation>
 <translation id="4827675678516992122">Nepavyko prisijungti</translation>
@@ -5647,6 +5649,7 @@
 <translation id="648927581764831596">Nėra</translation>
 <translation id="6490471652906364588">USB-C įrenginys (prievadas dešinėje)</translation>
 <translation id="6491376743066338510">Nepavyko suteikti prieigos teisės</translation>
+<translation id="6492396476180293140">Vidinė kamera išaktyvinta naudojant aparatinės įrangos jungiklį</translation>
 <translation id="6494327278868541139">Rodyti išsamią informaciją apie sustiprintą apsaugą</translation>
 <translation id="6494445798847293442">Ne sertifikavimo institucija</translation>
 <translation id="6494974875566443634">Tinkinimas</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 48e46a9..0d5cc5c 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -1922,6 +1922,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{सपोर्ट नसलेले एक अ‍ॅप काढून टाका}other{सपोर्ट नसलेली # अ‍ॅप्स काढून टाका}}</translation>
 <translation id="2776560192867872731"><ph name="DEVICE_NAME" /> या डिव्हाइसचे नाव बदला</translation>
 <translation id="2777251078198759550">हा कंटेनर हटवा</translation>
+<translation id="2778471504622896352">ChromeOS लाँचरमध्ये रिमोट अ‍ॅप्स जोडा</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Linux ॲप्लिकेशन इंस्टॉल करताना एरर आली</translation>
 <translation id="2783298271312924866">डाउनलोड केलेले</translation>
@@ -3555,6 +3556,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" />, आणि आणखी <ph name="NUMBER_OF_OTHER_SWITCHES" /> स्विच</translation>
 <translation id="439266289085815679">ब्लूटूथ कॉंफिगरेशन <ph name="USER_EMAIL" /> नियंत्रित करते.</translation>
 <translation id="4392896746540753732">कॉंफिगरेशन फाइल संपादित करा</translation>
+<translation id="4393713825278446281">जलद पेअरिंग डिव्हाइस ही <ph name="PRIMARY_EMAIL" /> मध्ये सेव्ह केली आहेत</translation>
 <translation id="4394049700291259645">अक्षम करा</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{Open all}=1{बुकमार्क उघडा}other{सर्व ({COUNT}) उघडा}}</translation>
 <translation id="4397372003838952832">तुम्ही हा पासवर्ड लक्षात ठेवण्याची आवश्यकता नाही. तो <ph name="EMAIL" /> साठी <ph name="GOOGLE_PASSWORD_MANAGER" /> मध्ये सेव्ह केला जाईल.</translation>
@@ -3785,6 +3787,7 @@
 <translation id="4615586811063744755">कोणत्याही कुकीज निवडलेल्या नाही</translation>
 <translation id="461661862154729886">ऊर्जा स्रोत</translation>
 <translation id="4617001782309103936">खूपच लहान</translation>
+<translation id="4617019240346358451">"<ph name="EXTENSION_NAME" />" वापरण्यासाठी पेज रीलोड करा</translation>
 <translation id="4617270414136722281">एक्स्टेंशन पर्याय</translation>
 <translation id="4617880081511131945">कनेक्शन स्थापित करू शकत नाही</translation>
 <translation id="4619564267100705184">हे तुम्हीच असल्याची पडताळणी करा</translation>
@@ -4000,6 +4003,7 @@
 <translation id="4833683849865011483">प्रिंट सर्व्हरवरील एक प्रिंटर आढळला</translation>
 <translation id="4836504898754963407">फिंगरप्रिंट व्यवस्‍थापित करा</translation>
 <translation id="4837128290434901661">Google Search वर परत बदलायचे आहे का?</translation>
+<translation id="4837165100461973682">तुमचे बदल लागू करण्यासाठी पेज रीलोड करा</translation>
 <translation id="4837926214103741331">तुम्ही हे डिव्हाइस वापरण्यासाठी प्राधिकृत नाही. कृपया साइन इन करण्याच्या परवानगीसाठी डिव्हाइस मालकाशी संपर्क साधा.</translation>
 <translation id="4837952862063191349">तुमचा स्थानिक डेटा अनलॉक आणि रिस्टोअर करण्‍यासाठी, कृपया तुमचा जुना <ph name="DEVICE_TYPE" /> पासवर्ड एंटर करा.</translation>
 <translation id="4838170306476614339">तुमच्या फोनमधील फोटो, मीडिया आणि सूचना पहा</translation>
@@ -4309,6 +4313,7 @@
 <translation id="5150254825601720210">Netscape सर्टिफिकेट SSL सर्व्हर नाव</translation>
 <translation id="5151354047782775295">डिस्क स्थान मोकळे करा किंवा निवडलेला डेटा स्वयंचलितपणे हटवला जाऊ शकतो</translation>
 <translation id="5153234146675181447">फोन विसरा</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722"><ph name="PRINTING_DESTINATION" /> यासाठी प्रगत सेटिंग्ज</translation>
 <translation id="5154702632169343078">विषय</translation>
 <translation id="5155327081870541046">तुम्हाला शोधायच्या असलेल्या साइटचा शॉर्टकट अ‍ॅड्रेस बारमध्ये एंटर करा जसे की, "@bookmarks". त्यानंतर, तुमचा प्राधान्य दिलेला कीबोर्ड शॉर्टकट दाबा आणि तुमची शोध संज्ञा एंटर करा.</translation>
@@ -5945,6 +5950,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> दूरस्थपणे जोडला</translation>
 <translation id="6790820461102226165">व्यक्ती जोडा...</translation>
 <translation id="6793604637258913070">मजकूर घालण्याचे स्थान दिसते किंवा हलते तेव्हा ते हायलाइट करा</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">ऑटो-स्कॅन हे तुम्हाला स्क्रीनवरील आयटमदरम्यान आपोआप नेव्हिगेट करू देते. एखादा आयटम हायलाइट केला जातो तेव्हा, तो अ‍ॅक्टिव्हेट करण्यासाठी “निवडा” दाबा.</translation>
 <translation id="6795884519221689054">पांडा</translation>
 <translation id="6797493596609571643">अरेरे, काहीतरी चूक झाली.</translation>
@@ -7816,6 +7822,7 @@
 <translation id="8642947597466641025">मजकूर मोठा करा</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> धोकादायक असू शकते. ती स्कॅन करण्यासाठी Google प्रगत संरक्षण कडे पाठवायची?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{No cookies}=1{एक कुकी ब्लॉक केली}other{# कुकी ब्लॉक केल्या}}</translation>
+<translation id="864423554496711319">तुमच्या खात्यामध्ये डिव्हाइस सेव्ह केली आहेत</translation>
 <translation id="8644655801811752511">ही सिक्युरिटी की रीसेट करू शकत नाही. की घातल्यानंतर ती लगेच रीसेट करण्याचा प्रयत्न करा.</translation>
 <translation id="8645354835496065562">सेन्सर ॲक्सेस देणे सुरू ठेवा</translation>
 <translation id="8645920082661222035">धोकादायक घटना घडण्याआधी त्यांचे पूर्वानुमान करते आणि त्यांबद्दल तुम्हाला चेतावणी देते</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb
index 564896e5..f2bddc98 100644
--- a/chrome/app/resources/generated_resources_ms.xtb
+++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -2588,6 +2588,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> akan dapat melihat <ph name="FILENAME" /></translation>
 <translation id="3445047461171030979">Jawapan pantas Google Assistant</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
+<translation id="344537926140058498">Organisasi anda menyekat fail ini kerana kandungannya sensitif atau berbahaya. Minta pemilik membetulkan fail ini.</translation>
 <translation id="3445925074670675829">Peranti USB-C</translation>
 <translation id="3446274660183028131">Sila lancarkan Parallels Desktop untuk memasang Windows.</translation>
 <translation id="344630545793878684">Baca data anda di beberapa laman web</translation>
@@ -3146,6 +3147,7 @@
 <translation id="397105322502079400">Mengira...</translation>
 <translation id="3971764089670057203">Cap jari pada kunci keselamatan ini</translation>
 <translation id="3973005893595042880">Pengguna tidak dibenarkan</translation>
+<translation id="3973062011568994448">Untuk mengimport kata laluan, pilih fail CSV.</translation>
 <translation id="3973660817924297510">Menyemak kata laluan (<ph name="CHECKED_PASSWORDS" /> daripada <ph name="TOTAL_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">Gunakan “Seterusnya” untuk menggerakkan fokus anda ke hadapan pada skrin</translation>
 <translation id="3975201861340929143">Penjelasan</translation>
@@ -3935,6 +3937,7 @@
 <translation id="4768332406694066911">Anda mempunyai sijil daripada organisasi ini yang mengenal pasti anda</translation>
 <translation id="4770119228883592393">Kebenaran diminta, tekan ⌘ + Pilihan + Anak panah ke bawah untuk memberikan respons</translation>
 <translation id="4773112038801431077">Tingkatkan Linux</translation>
+<translation id="4774337692467964393">Jika Smart Lock dihidupkan, anda tidak perlu memasukkan PIN atau kata laluan</translation>
 <translation id="4775142426314270551">Bantu kami meningkatkan ciri dan prestasi Chrome dan OS Chrome dengan menghantar laporan ranap sistem serta data diagnostik dan penggunaan kepada Google secara automatik. Sesetengah data agregat juga akan membantu apl Android dan rakan kongsi Google. Jika tetapan Aktiviti Web &amp; Apl dihidupkan untuk Google Account anak anda, data Android anak anda mungkin disimpan pada Google Account anak anda.</translation>
 <translation id="477647109558161443">Buat pintasan desktop</translation>
 <translation id="4776594120007763294">Untuk menambah halaman untuk dibaca kemudian, klik butang</translation>
@@ -3984,6 +3987,7 @@
 <translation id="4820236583224459650">Tetapkan sebagai tiket aktif</translation>
 <translation id="4821935166599369261">&amp;Pemprofilan Didayakan</translation>
 <translation id="4823484602432206655">Baca dan tukar pengguna dan tetapan peranti</translation>
+<translation id="4823894915586516138">PIN atau kata laluan ini melindungi data anda pada <ph name="DEVICE_TYPE" />ini, termasuk sebarang maklumat yang anda akses daripada telefon anda</translation>
 <translation id="4824037980212326045">Sandaran dan pemulihan Linux</translation>
 <translation id="4824958205181053313">Batalkan penyegerakan?</translation>
 <translation id="4827675678516992122">Tidak dapat menyambung</translation>
@@ -4615,6 +4619,7 @@
 <translation id="5466374726908360271">Ta&amp;mpal dan cari “<ph name="SEARCH_TERMS" />”</translation>
 <translation id="5467207440419968613"><ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /> disekat</translation>
 <translation id="5468173180030470402">Mencari perkongsian fail</translation>
+<translation id="5468881191994555667">Pilih fail</translation>
 <translation id="5469852975082458401">Anda boleh menukar halaman dengan kursor teks. Tekan F7 untuk mematikannya.</translation>
 <translation id="5470735824776589490">Mula semula diperlukan sebelum peranti anda boleh ditetapkan semula dengan Powerwash. <ph name="LINK_BEGIN" />Ketahui lebih lanjut<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Hai! Saya ialah suara teks ke pertuturan anda.</translation>
@@ -5640,6 +5645,7 @@
 <translation id="648927581764831596">Tiada yang tersedia</translation>
 <translation id="6490471652906364588">Peranti USB-C (port kanan)</translation>
 <translation id="6491376743066338510">Pengesahan gagal</translation>
+<translation id="6492396476180293140">Kamera dalaman dinyahaktifkan oleh suis perkakasan</translation>
 <translation id="6494327278868541139">Paparkan butiran perlindungan dipertingkatkan</translation>
 <translation id="6494445798847293442">Bukan Pihak Berkuasa Pensijilan</translation>
 <translation id="6494974875566443634">Penyesuaian</translation>
@@ -6345,6 +6351,7 @@
 <translation id="7191159667348037">Pencetak Tidak Diketahui (USB)</translation>
 <translation id="7193051357671784796">Apl ini ditambahkan oleh organisasi anda. Mulakan semula apl untuk menyelesaikan pemasangan.</translation>
 <translation id="7193374945610105795">Tiada kata laluan disimpan untuk <ph name="ORIGIN" /></translation>
+<translation id="7194873994243265344">Organisasi anda menyekat fail ini kerana disulitkan. Minta pemilik menyahsulitkan fail ini.</translation>
 <translation id="7196913789568937443">Buat sandaran ke Google Drive. Pulihkan data atau tukar peranti anda dengan mudah pada bila-bila masa. Sandaran anda merangkumi data apl. Sandaran anda dimuat naik ke Google dan disulitkan dengan menggunakan kata laluan Akaun Google anda. <ph name="BEGIN_LINK1" />Ketahui Lebih Lanjut<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Dapatkan Google Search dan ciri pintar Google setiap kali anda menyemak imbas</translation>
 <translation id="719791532916917144">Pintasan papan kekunci</translation>
@@ -6363,6 +6370,7 @@
 <translation id="7211783048245131419">Belum ada suis yang telah ditetapkan</translation>
 <translation id="7212097698621322584">Masukkan PIN semasa anda untuk menukar PIN. Jika anda tidak tahu PIN anda, anda perlu menetapkan semula kunci keselamatan, kemudian buat PIN baharu.</translation>
 <translation id="7213903639823314449">Enjin carian yang digunakan dalam bar alamat</translation>
+<translation id="721490496276866468">Import kata laluan</translation>
 <translation id="7216595297012131718">Susun bahasa berdasarkan pilihan anda</translation>
 <translation id="7219473482981809164">Kami telah menemukan beberapa profil yang tersedia untuk dimuat turun. Pilih profil yang ingin anda muat turun sebelum meneruskan.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Tiada kata laluan lemah}=1{1 kata laluan lemah}other{{NUM_WEAK} kata laluan lemah}}</translation>
@@ -6996,6 +7004,7 @@
 <translation id="7826190688224781865">Kod ID gedung Peruncit</translation>
 <translation id="7826249772873145665">Penyahpepijatan ADB dilumpuhkan</translation>
 <translation id="7826254698725248775">Pengecam peranti bercanggah.</translation>
+<translation id="7828642077514646543">Ralat: Tidak dapat menyahkod sijil</translation>
 <translation id="7828731929332799387">Tindakan ini akan memadam semua kuki dan data tapak yang tersedia dalam konteks pihak ketiga. Anda ingin teruskan?</translation>
 <translation id="7829877209233347340">Minta ibu atau bapa log masuk untuk memberikan kebenaran bagi penambahan akaun institusi pengajian</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7959,6 +7968,7 @@
 <translation id="8775653927968399786">{0,plural, =1{<ph name="DEVICE_TYPE" /> anda akan dikunci secara automatik dalam masa # saat.
 <ph name="DOMAIN" /> menghendaki anda memastikan kad pintar anda tidak dikeluarkan.}other{<ph name="DEVICE_TYPE" /> anda akan dikunci secara automatik dalam masa # saat.
 <ph name="DOMAIN" /> menghendaki anda memastikan kad pintar anda tidak dikeluarkan.}}</translation>
+<translation id="8776294611668764629">Organisasi anda menyekat fail ini kerana saiznya terlalu besar untuk semakan keselamatan. Anda boleh membuka fail sehingga 50 MB.</translation>
 <translation id="8777628254805677039">kata laluan akar</translation>
 <translation id="8779944680596936487">Laman hanya boleh menggunakan kuki untuk melihat aktiviti penyemakan imbas anda pada laman mereka sendiri</translation>
 <translation id="8780123805589053431">Dapatkan perihalan imej daripada Google</translation>
diff --git a/chrome/app/resources/generated_resources_my.xtb b/chrome/app/resources/generated_resources_my.xtb
index 8bd9e65f..b93fc5d 100644
--- a/chrome/app/resources/generated_resources_my.xtb
+++ b/chrome/app/resources/generated_resources_my.xtb
@@ -3937,6 +3937,7 @@
 <translation id="4768332406694066911">ဤအဖွဲ့အစည်းများမှနေ၍ သင်၏ အထောက်အထား အသိအမှတ်ပြုလက်မှတ်များ သင့်ထံတွင်ရှိပါသည်</translation>
 <translation id="4770119228883592393">ခွင့်ပြုချက်တောင်းထားသည်၊ တုံ့ပြန်ရန် ⌘ + Option + 'အောက်ညွှန်မြား' နှိပ်ပါ</translation>
 <translation id="4773112038801431077">Linux အဆင့်မြှင့်ခြင်း</translation>
+<translation id="4774337692467964393">Smart Lock ဖွင့်ထားလျှင် ပင်နံပါတ် (သို့) စကားဝှက် မလိုအပ်ပါ</translation>
 <translation id="4775142426314270551">အမှားရှာဖွေမှုနှင့် သုံးစွဲမှု ဒေတာများအပြင် ပျက်စီးမှု အစီရင်ခံစာများကို Google သို့ အလိုအလျောက်ပို့ပြီး Chrome နှင့် ChromeOS ဝန်ဆောင်မှုများနှင့် စွမ်းဆောင်ရည် ပိုမိုကောင်းမွန်လာစေရန် ကူညီပါ။ ပေါင်းစည်းထားသည့် ဒေတာအချို့သည်လည်း Android အက်ပ်များနှင့် Google ပါတနာများကို ကူညီပေးပါမည်။ သင့်ကလေး၏ Google Account အတွက် ‘ဝဘ်နှင့်အက်ပ်လုပ်ဆောင်ချက်’ ဆက်တင်ကို ဖွင့်ထားပါက သင့်ကလေး၏ Android ဒေတာကို သင့်ကလေး၏ Google Account တွင် သိမ်းထားနိုင်ပါသည်။</translation>
 <translation id="477647109558161443">အမြန်ဖွင့်ဖြတ်လမ်းလင့်ခ်တစ်ခု ပြုလုပ်ရန်</translation>
 <translation id="4776594120007763294">နောက်မှဖတ်ရန်အတွက် စာမျက်နှာထည့်ရန် ခလုတ်ကိုနှိပ်ပါ</translation>
@@ -3986,6 +3987,7 @@
 <translation id="4820236583224459650">လက်ရှိအသုံးပြုနေသည့် လက်မှတ်သတ်မှတ်ရန်</translation>
 <translation id="4821935166599369261">&amp;ပရိုဖိုင်ကြည့်မှု ဖွင့်ထား</translation>
 <translation id="4823484602432206655">သုံးစွဲသူနှင့် စက်ကိရိယာ ဆက်တင်များအား ဖတ်ပြီး ပြောင်းရန်</translation>
+<translation id="4823894915586516138">ပင်နံပါတ် (သို့) စကားဝှက်က ဤစက်<ph name="DEVICE_TYPE" /> တွင် ဖုန်းမှယူသုံးသော အကြောင်းအရာအပါအဝင် သင့်ဒေတာများကို ကာကွယ်ပေးသည်။</translation>
 <translation id="4824037980212326045">Linux အရန်ကူးခြင်းနှင့် ပြန်လည်ရယူခြင်း</translation>
 <translation id="4824958205181053313">စင့်ခ်လုပ်ခြင်းကို ပယ်ဖျက်လိုပါသလား။</translation>
 <translation id="4827675678516992122">ချိတ်ဆက်၍ မရပါ</translation>
@@ -5645,6 +5647,7 @@
 <translation id="648927581764831596">မရနိုင်ပါ</translation>
 <translation id="6490471652906364588">USB-C ကိရိယာ (ညာ ပို့တ်)</translation>
 <translation id="6491376743066338510">ခွင့်ပြုချက် မရရှိပါ</translation>
+<translation id="6492396476180293140">အတွင်းကင်မရာကို ဟာ့ဒ်ဝဲခလုတ်က ရပ်ထားသည်</translation>
 <translation id="6494327278868541139">အဆင့်မြှင့်တင်ထားသော ကာကွယ်မှု အသေးစိတ်ကို ပြရန်</translation>
 <translation id="6494445798847293442">စီမံခန့်ခွဲမှုဆိုင်ရာ အသိအမှတ်ပြုလက်မှတ် ထုတ်ပေးသူ မဟုတ်ပါ</translation>
 <translation id="6494974875566443634">စိတ်ကြိုက်ပြုလုပ်ခြင်း</translation>
diff --git a/chrome/app/resources/generated_resources_ne.xtb b/chrome/app/resources/generated_resources_ne.xtb
index a3dac9b..891d84e 100644
--- a/chrome/app/resources/generated_resources_ne.xtb
+++ b/chrome/app/resources/generated_resources_ne.xtb
@@ -3918,6 +3918,7 @@
 <translation id="4768332406694066911">तपाईँसँग यी संगठनहरूका तपाईँको पहिचान गर्ने प्रमाणपत्रहरू छन्</translation>
 <translation id="4770119228883592393">अनुमति मागियो, यस सम्बन्धमा कारबाही गर्न ⌘ + Option + डाउन एरो थिच्नुहोस्</translation>
 <translation id="4773112038801431077">Linux अपग्रेड गर्नुहोस्</translation>
+<translation id="4774337692467964393">Smart Lock अन गरियो भने तपाईंले कुनै PIN वा पासवर्ड हालिराख्नु पर्दैन</translation>
 <translation id="4775142426314270551">Google लाई निदान तथा प्रयोगसम्बन्धी डेटाका साथै क्र्यास रिपोर्ट स्वतः पठाएर Chrome र ChromeOS को पर्फर्मेन्स र तिनका सुविधाहरूको गुणस्तर सुधार्न मद्दत गर्नुहोस्। Android एप र Google का साझेदारहरूलाई पनि केही समग्र डेटा काम लाग्ने छ। तपाईंका बच्चाको Google खाताका हकमा "वेब तथा एपसम्बन्धी गतिविधि" सेटिङ अन गरिएको छ भने Android मा भएको तपाईंका बच्चाको डेटा तपाईंका बच्चाको Google खातामा सेभ गरिन सक्छ।</translation>
 <translation id="477647109558161443">एउटा डेस्कटप सर्टकट सिर्जना गर्नुहोस्</translation>
 <translation id="4776594120007763294">"पछि पढ्नुहोस्" मा कुनै पेज हाल्न यो बटन थिच्नुहोस्</translation>
@@ -3967,6 +3968,7 @@
 <translation id="4820236583224459650">सक्रिय टिकटको रूपमा सेट गर्नुहोस्</translation>
 <translation id="4821935166599369261">&amp;रूपरेखा सक्षम गरिएको छ</translation>
 <translation id="4823484602432206655">पढ्नुहोस् र प्रयोगकर्ता तथा यन्त्र सेटिङहरू परिवर्तन गर्नुहोस्</translation>
+<translation id="4823894915586516138">तपाईंले PIN वा पासवर्ड सेट गर्नुभयो भने तपाईंले आफ्नो फोनबाट हेर्ने तथा प्रयोग गर्ने जानकारीका साथै यो <ph name="DEVICE_TYPE" /> मा भएको तपाईंको जानकारी सुरक्षित रहन्छ</translation>
 <translation id="4824037980212326045">Linux को ब्याकअप तथा पुनर्स्थापना</translation>
 <translation id="4824958205181053313">सिंक रद्द गर्ने हो?</translation>
 <translation id="4827675678516992122">जडान गर्न सकिएन</translation>
@@ -5623,6 +5625,7 @@
 <translation id="648927581764831596">कुनै पनि उपलब्ध छैन</translation>
 <translation id="6490471652906364588">USB-C यन्त्र (दायाँ पोर्ट)</translation>
 <translation id="6491376743066338510">अनुमति दिन सकिएन</translation>
+<translation id="6492396476180293140">हार्डवेयर स्विच थिचेर आन्तरिक क्यामेरा डिएक्टिभ गरिएको छ</translation>
 <translation id="6494327278868541139">परिष्कृत सुरक्षासम्बन्धी विवरण देखाइयोस्</translation>
 <translation id="6494445798847293442">प्रमाणीकरण अधिकारी होइन</translation>
 <translation id="6494974875566443634">व्यक्तिगत सेटिङ</translation>
diff --git a/chrome/app/resources/generated_resources_or.xtb b/chrome/app/resources/generated_resources_or.xtb
index 7604d04..888318a27 100644
--- a/chrome/app/resources/generated_resources_or.xtb
+++ b/chrome/app/resources/generated_resources_or.xtb
@@ -3919,6 +3919,7 @@
 <translation id="4768332406694066911">ଆପଣଙ୍କ ପାଖରେ ଏହି ସଂଗଠନଗୁଡ଼ିକରୁ ସାର୍ଟିଫିକେଟ୍‍ଗୁଡ଼ିକ ଅଛି ଯାହା ଆପଣଙ୍କୁ ଚିହ୍ନଟ କରିଥାଏ</translation>
 <translation id="4770119228883592393">ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରାଯାଇଛି, ଉତ୍ତର ଦେବାକୁ ⌘ + Option + ଡାଉନ୍ ତୀର କୀ ଦବାନ୍ତୁ</translation>
 <translation id="4773112038801431077">Linux ଅପଗ୍ରେଡ୍ କରନ୍ତୁ</translation>
+<translation id="4774337692467964393">ଯଦି ସ୍ମାର୍ଟ ଲକ ଚାଲୁ କରାଯାଏ, ତେବେ ଆପଣଙ୍କୁ ଏକ PIN କିମ୍ବା ପାସୱାର୍ଡ ଲେଖିବାର ଆବଶ୍ୟକତା ହେବ ନାହିଁ</translation>
 <translation id="4775142426314270551">Googleକୁ ସ୍ୱଚାଳିତ ଭାବେ କ୍ରାସ ରିପୋର୍ଟଗୁଡ଼ିକ ସମେତ ଡାଏଗ୍ନୋଷ୍ଟିକ ଓ ବ୍ୟବହାର ଡାଟା ପଠାଇ Chrome ଏବଂ ChromeOS ଫିଚର ଓ ପରଫରମାନ୍ସକୁ ଉନ୍ନତ କରିବାରେ ସାହାଯ୍ୟ କରନ୍ତୁ। କିଛି ଏକତ୍ରିତ ଡାଟା Android ଆପ ଏବଂ Google ପାର୍ଟନରଗୁଡ଼ିକୁ ମଧ୍ୟ ସାହାଯ୍ୟ କରିବ। ଯଦି ଆପଣଙ୍କ ପିଲାର Google ଆକାଉଣ୍ଟ ପାଇଁ ୱେବ ଓ ଆପ କାର୍ଯ୍ୟକଳାପ ସେଟିଂ ଚାଲୁ ଅଛି, ତେବେ ଆପଣଙ୍କ ପିଲାର Android ଡାଟା ତା'ର Google ଆକାଉଣ୍ଟରେ ସେଭ କରାଯାଇପାରେ।</translation>
 <translation id="477647109558161443">ଏକ ଡେସ୍କଟପ୍ ସର୍ଟକଟ୍ ତିଆରି କରନ୍ତୁ</translation>
 <translation id="4776594120007763294">ପରେ ପଢ଼ିବା ପାଇଁ ଏକ ପୃଷ୍ଠା ଯୋଗ କରିବାକୁ, ଏହି ବଟନରେ କ୍ଲିକ୍ କରନ୍ତୁ</translation>
@@ -3968,6 +3969,7 @@
 <translation id="4820236583224459650">ସକ୍ରିୟ ଟିକେଟ୍ ଭାବେ ସେଟ୍ କରନ୍ତୁ</translation>
 <translation id="4821935166599369261">&amp;ପ୍ରୋଫାଇଲିଂ ସକ୍ଷମ କରାଗଲା</translation>
 <translation id="4823484602432206655">ଉପଯୋଗକର୍ତ୍ତା ଏବଂ ଡିଭାଇସ୍‌ ସେଟିଂସ୍‌ ପଢ଼ନ୍ତୁ ଏବଂ ପରିବର୍ତ୍ତନ କରନ୍ତୁ</translation>
+<translation id="4823894915586516138">ଏହି PIN କିମ୍ବା ପାସୱାର୍ଡ ଆପଣ ଆପଣଙ୍କ ଫୋନରୁ ଆକ୍ସେସ କରୁଥିବା ଯେ କୌଣସି ସୂଚନା ସମେତ ଏହି <ph name="DEVICE_TYPE" />ରେ ଥିବା ଆପଣଙ୍କ ଡାଟାକୁ ସୁରକ୍ଷିତ ରଖେ</translation>
 <translation id="4824037980212326045">Linux ବ୍ୟାକଅପ୍ ଓ ରିଷ୍ଟୋର୍</translation>
 <translation id="4824958205181053313">ସିଙ୍କ୍‌ ବାତିଲ୍‌ କରିବେ?</translation>
 <translation id="4827675678516992122">ସଂଯୋଗ କରିହେଲା ନାହିଁ</translation>
@@ -5622,6 +5624,7 @@
 <translation id="648927581764831596">କେହି ମଧ୍ୟ ଉପଲବ୍ଧ ନାହାନ୍ତି</translation>
 <translation id="6490471652906364588">USB-C ଡିଭାଇସ୍‍ (ଡାହାଣ ପୋର୍ଟ)</translation>
 <translation id="6491376743066338510">ପ୍ରାଧିକରଣ ବିଫଳ ହେଲା</translation>
+<translation id="6492396476180293140">ହାର୍ଡୱେର ସ୍ୱିଚ ଦ୍ୱାରା ଇଣ୍ଟର୍ନଲ କ୍ୟାମେରାକୁ ନିଷ୍କ୍ରିୟ କରାଯାଇଛି</translation>
 <translation id="6494327278868541139">ଉନ୍ନତ ସୁରକ୍ଷା ବିବରଣୀ ଦେଖାନ୍ତୁ</translation>
 <translation id="6494445798847293442">କୌଣସି ପ୍ରାମାଣିକରଣ ଅଧିକାରୀ ନୁହେଁ</translation>
 <translation id="6494974875566443634">କଷ୍ଟମାଇଜେସନ୍</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb
index 4df091ef..aac64641 100644
--- a/chrome/app/resources/generated_resources_ru.xtb
+++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -2574,6 +2574,7 @@
 <translation id="3444726579402183581">Сайт <ph name="ORIGIN" /> сможет просматривать файл "<ph name="FILENAME" />".</translation>
 <translation id="3445047461171030979">Быстрые ответы Google Ассистента</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> мин.</translation>
+<translation id="344537926140058498">Ваша организация заблокировала файл, так как он содержит конфиденциальный или опасный контент. Попросите владельца его исправить.</translation>
 <translation id="3445925074670675829">Устройство USB-C</translation>
 <translation id="3446274660183028131">Чтобы установить Windows, запустите Parallels Desktop.</translation>
 <translation id="344630545793878684">Просмотр данных на нескольких сайтах</translation>
@@ -3132,6 +3133,7 @@
 <translation id="397105322502079400">Вычисление…</translation>
 <translation id="3971764089670057203">Цифровые отпечатки на этом электронном ключе</translation>
 <translation id="3973005893595042880">Пользователю не разрешено выполнять ВМ.</translation>
+<translation id="3973062011568994448">Чтобы импортировать пароли, выберите CSV-файл.</translation>
 <translation id="3973660817924297510">Проверка паролей (<ph name="CHECKED_PASSWORDS" /> из <ph name="TOTAL_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">Нажмите "Далее", чтобы перейти к следующему элементу.</translation>
 <translation id="3975201861340929143">Описание</translation>
@@ -4600,6 +4602,7 @@
 <translation id="5466374726908360271">Вст&amp;авить и найти "<ph name="SEARCH_TERMS" />"</translation>
 <translation id="5467207440419968613">Отключены разрешения "<ph name="PERMISSION_1" />" и "<ph name="PERMISSION_2" />"</translation>
 <translation id="5468173180030470402">Поиск общих папок…</translation>
+<translation id="5468881191994555667">Выбрать файл</translation>
 <translation id="5469852975082458401">Вы сможете использовать курсор для навигации по страницам. Нажмите F7, чтобы отключить эту функцию.</translation>
 <translation id="5470735824776589490">Перед сбросом настроек с помощью функции Powerwash необходимо перезагрузить устройство. <ph name="LINK_BEGIN" />Подробнее…<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Здравствуйте! Я буду озвучивать для вас текст.</translation>
@@ -6336,6 +6339,7 @@
 <translation id="7191159667348037">Неизвестный принтер (USB)</translation>
 <translation id="7193051357671784796">Это приложение добавила ваша организация. Перезапустите его, чтобы завершить установку.</translation>
 <translation id="7193374945610105795">Для сайта <ph name="ORIGIN" /> нет сохраненных паролей</translation>
+<translation id="7194873994243265344">Ваша организация заблокировала файл, так как он зашифрован. Попросите владельца его расшифровать.</translation>
 <translation id="7196913789568937443">Резервное копирование на Google Диск. Позволяет в любой момент восстановить данные (в том числе данные приложений) или перенести их на новое устройство. Резервные копии загружаются в Google и шифруются с помощью пароля вашего аккаунта Google. <ph name="BEGIN_LINK1" />Подробнее…<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Помогите Поиску и другим сервисам Google узнать вас лучше!</translation>
 <translation id="719791532916917144">Сочетания клавиш</translation>
@@ -6354,6 +6358,7 @@
 <translation id="7211783048245131419">Переключатели не назначены.</translation>
 <translation id="7212097698621322584">Сначала введите текущий PIN-код. Если вы его не знаете, сбросьте настройки электронного ключа и установите новый PIN-код.</translation>
 <translation id="7213903639823314449">Поисковая система, используемая в адресной строке.</translation>
+<translation id="721490496276866468">Импорт паролей</translation>
 <translation id="7216595297012131718">Расположите языки, исходя из своих предпочтений</translation>
 <translation id="7219473482981809164">Доступно несколько профилей. Выберите, какие нужно скачать.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Нет простых паролей}=1{1 простой пароль}one{{NUM_WEAK} простой пароль}few{{NUM_WEAK} простых пароля}many{{NUM_WEAK} простых паролей}other{{NUM_WEAK} простого пароля}}</translation>
@@ -6987,6 +6992,7 @@
 <translation id="7826190688224781865">Код идентификатора розничного продавца</translation>
 <translation id="7826249772873145665">Отладка с ADB отключена</translation>
 <translation id="7826254698725248775">Конфликт идентификаторов устройств.</translation>
+<translation id="7828642077514646543">Ошибка: не удалось расшифровать сертификат.</translation>
 <translation id="7828731929332799387">Все сторонние файлы cookie и данные сайтов будут удалены. Продолжить?</translation>
 <translation id="7829877209233347340">Попросите родителя войти в систему, чтобы дать вам разрешение на добавление учебного аккаунта.</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7951,6 +7957,7 @@
 По правилам домена <ph name="DOMAIN" /> смарт-карта должна быть вставлена.}many{Ваше устройство <ph name="DEVICE_TYPE" /> будет автоматически заблокировано через # секунд.
 По правилам домена <ph name="DOMAIN" /> смарт-карта должна быть вставлена.}other{Ваше устройство <ph name="DEVICE_TYPE" /> будет автоматически заблокировано через # секунды.
 По правилам домена <ph name="DOMAIN" /> смарт-карта должна быть вставлена.}}</translation>
+<translation id="8776294611668764629">Ваша организация заблокировала файл, так как он слишком большой для проверки безопасности. Можно открывать файлы размером до 50 МБ.</translation>
 <translation id="8777628254805677039">пароль суперпользователя</translation>
 <translation id="8779944680596936487">С помощью файлов cookie сайт может только определять, какие действия вы совершали на нем.</translation>
 <translation id="8780123805589053431">Получать описания изображений от Google</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index 2d950186..31da148 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -1910,6 +1910,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Odstrániť 1 nepodporovanú aplikáciu}few{Odstrániť # nepodporované aplikácie}many{Remove # unsupported apps}other{Odstrániť # nepodporovaných aplikácií}}</translation>
 <translation id="2776560192867872731">Zmeniť názov zariadenia <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Odstrániť tento kontajner</translation>
+<translation id="2778471504622896352">Pridanie vzdialených aplikácií do spúšťača systému ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Pri inštalácii aplikácie pre Linux sa vyskytla chyba</translation>
 <translation id="2783298271312924866">Stiahnuté</translation>
@@ -3545,6 +3546,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> a ďalšie (<ph name="NUMBER_OF_OTHER_SWITCHES" />) prepínače</translation>
 <translation id="439266289085815679">Konfiguráciu rozhrania Bluetooth spravuje <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Úprava konfiguračného súboru</translation>
+<translation id="4393713825278446281">Zariadenia podporujúce rýchle párovanie uložené do účtu <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Zakázať</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{Otvoriť všetky}=1{Otvoriť záložku}few{Otvoriť všetky ({COUNT})}many{Otvoriť všetky ({COUNT})}other{Otvoriť všetky ({COUNT})}}</translation>
 <translation id="4397372003838952832">Toto heslo si nebudete musieť pamätať. Bude uložené v službe <ph name="GOOGLE_PASSWORD_MANAGER" /> pre účet <ph name="EMAIL" />.</translation>
@@ -3774,6 +3776,7 @@
 <translation id="4615586811063744755">nevybrali ste žiadny súbor cookie</translation>
 <translation id="461661862154729886">Zdroj napájania</translation>
 <translation id="4617001782309103936">Príliš krátky</translation>
+<translation id="4617019240346358451">Ak chcete použiť rozšírenie <ph name="EXTENSION_NAME" />, znova načítajte stránku</translation>
 <translation id="4617270414136722281">Možnosti rozšírenia</translation>
 <translation id="4617880081511131945">Pripojenie sa nedá nadviazať</translation>
 <translation id="4619564267100705184">Overte, že ste to vy</translation>
@@ -3989,6 +3992,7 @@
 <translation id="4833683849865011483">Na tlačovom serveri bola nájdená jedna tlačiareň</translation>
 <translation id="4836504898754963407">Správa odtlačkov</translation>
 <translation id="4837128290434901661">Chcete prepnúť späť na Vyhľadávanie Google?</translation>
+<translation id="4837165100461973682">Ak chcete zmeny použiť, znova načítajte stránku</translation>
 <translation id="4837926214103741331">Nemáte oprávnenie používať toto zariadenie. Ak chcete získať povolenie na prihlásenie, kontaktujte majiteľa zariadenia.</translation>
 <translation id="4837952862063191349">Ak chcete zariadenie odomknúť a obnoviť svoje miestne údaje, zadajte svoje staré heslo pre zariadenie <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Zobrazujte si fotky, médiá a upozornenia svojho telefónu</translation>
@@ -4298,6 +4302,7 @@
 <translation id="5150254825601720210">Netscape – názov servera SSL certifikátu</translation>
 <translation id="5151354047782775295">Uvoľnite miesto na disku, inak môže dôjsť k automatickému odstráneniu vybraných údajov</translation>
 <translation id="5153234146675181447">Odstránenie telefónu</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Rozšírené nastavenia pre <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Predmet</translation>
 <translation id="5155327081870541046">V paneli s adresou zadajte odkaz zodpovedajúci webu, na ktorom chcete hľadať, napríklad @bookmarks. Potom stlačte preferovanú klávesovú skratku a zadajte hľadaný výraz.</translation>
@@ -5937,6 +5942,7 @@
 <translation id="6790497603648687708">Rozšírenie <ph name="EXTENSION_NAME" /> bolo pridané vzdialene</translation>
 <translation id="6790820461102226165">Pridať osobu...</translation>
 <translation id="6793604637258913070">Zvýrazňovať textový kurzor, keď sa zobrazí alebo pohne</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">Automatické prehľadávanie vám umožňuje prechádzať po položkách na obrazovke automaticky. Po zvýraznení aktivujte položku stlačením tlačidla Vybrať.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Hops, niečo sa pokazilo.</translation>
@@ -7809,6 +7815,7 @@
 <translation id="8642947597466641025">Zväčšiť text</translation>
 <translation id="8643443571868262066">Súbor <ph name="FILE_NAME" /> môže byť nebezpečný. Chcete ho odoslať na kontrolu do rozšírenej ochrany Googlu?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Žiadne súbory cookie}=1{1 súbor cookie je blokovaný}few{# súbory cookie sú blokované}many{# cookies are blocked}other{# súborov cookie je blokovaných}}</translation>
+<translation id="864423554496711319">Zariadenia uložené do účtu</translation>
 <translation id="8644655801811752511">Tento bezpečnostný kľúč sa nedá resetovať. Skúste ho resetovať ihneď po vložení.</translation>
 <translation id="8645354835496065562">Naďalej umožňovať prístup k senzorom</translation>
 <translation id="8645920082661222035">Predpovedá nebezpečné udalosti a upozorní vás, než k nim dôjde</translation>
diff --git a/chrome/app/resources/generated_resources_sq.xtb b/chrome/app/resources/generated_resources_sq.xtb
index e4aa86c9..22e86ed3 100644
--- a/chrome/app/resources/generated_resources_sq.xtb
+++ b/chrome/app/resources/generated_resources_sq.xtb
@@ -2570,6 +2570,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> do të ketë mundësi të shikojë <ph name="FILENAME" /></translation>
 <translation id="3445047461171030979">Përgjigjet e shpejta të "Asistentit të Google"</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
+<translation id="344537926140058498">Organizata jote e bllokoi këtë skedar sepse ai ka përmbajtje delikate ose të rrezikshme. Kërkoji zotëruesit ta rregullojë.</translation>
 <translation id="3445925074670675829">Pajisja USB-C</translation>
 <translation id="3446274660183028131">Hap Parallels Desktop për të instaluar Windows.</translation>
 <translation id="344630545793878684">Lexo të dhënat e tua në një numër sajtesh uebi</translation>
@@ -3128,6 +3129,7 @@
 <translation id="397105322502079400">Po llogarit...</translation>
 <translation id="3971764089670057203">Gjurmët e gishtave në këtë çelës sigurie</translation>
 <translation id="3973005893595042880">Përdoruesi nuk lejohet</translation>
+<translation id="3973062011568994448">Për të importuar fjalëkalimet, zgjidh një skedar CSV.</translation>
 <translation id="3973660817924297510">Po kontrollon fjalëkalimet (<ph name="CHECKED_PASSWORDS" /> nga <ph name="TOTAL_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">Përdor butonin “Para” për ta zhvendosur fokusin përpara në ekran</translation>
 <translation id="3975201861340929143">Shpjegimi</translation>
@@ -4596,6 +4598,7 @@
 <translation id="5466374726908360271">Ngj&amp;it dhe kërko për “<ph name="SEARCH_TERMS" />”</translation>
 <translation id="5467207440419968613">Të bllokuara: <ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /></translation>
 <translation id="5468173180030470402">Po kërkon për ndarjet e skedarëve</translation>
+<translation id="5468881191994555667">Zgjidh skedarin</translation>
 <translation id="5469852975082458401">Mund t'i navigosh faqet me një kursor teksti. Shtyp F7 për ta çaktivizuar.</translation>
 <translation id="5470735824776589490">Kërkohet një rinisje para se pajisja jote të mund të rivendoset me Powerwash. <ph name="LINK_BEGIN" />Mëso më shumë<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Përshëndetje! Unë jam zëri i tekstit në ligjërim.</translation>
@@ -6326,6 +6329,7 @@
 <translation id="7191159667348037">Printer i panjohur (USB)</translation>
 <translation id="7193051357671784796">Ky aplikacion është shtuar nga organizata jote. Rinis aplikacionin për të përfunduar instalimin e tij.</translation>
 <translation id="7193374945610105795">Nuk ka asnjë fjalëkalim të ruajtur për <ph name="ORIGIN" /></translation>
+<translation id="7194873994243265344">Organizata jote e bllokoi këtë skedar sepse ai është i enkriptuar. Kërkoji zotëruesit ta deshifrojë.</translation>
 <translation id="7196913789568937443">Rezervo në "Diskun e Google". Restauro me lehtësi të dhënat e tua ose ndërro pajisjen në çdo kohë. Rezervimi yt përfshin të dhënat e aplikacioneve. Rezervimet ngarkohen në Google dhe enkriptohen duke përdorur fjalëkalimin e "Llogarisë sate të Google". <ph name="BEGIN_LINK1" />Mëso më shumë<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Merr funksionet inteligjente të Google dhe "Kërko me Google" sa herë që shfleton</translation>
 <translation id="719791532916917144">Shkurtorja e tastierës</translation>
@@ -6344,6 +6348,7 @@
 <translation id="7211783048245131419">Nuk është caktuar ende asnjë çelës</translation>
 <translation id="7212097698621322584">Fut kodin PIN aktual për ta ndryshuar. Nëse nuk e di kodin PIN, duhet të rivendosësh çelësin e sigurisë, dhe më pas të krijosh një kod të ri PIN.</translation>
 <translation id="7213903639823314449">Motori i kërkimit i përdorur në shiritin e adresës</translation>
+<translation id="721490496276866468">Importo fjalëkalimet</translation>
 <translation id="7216595297012131718">Renditi gjuhët sipas preferencës tënde</translation>
 <translation id="7219473482981809164">Kemi gjetur disa profile të disponueshme për t'u shkarkuar. Zgjidh ata që dëshiron të shkarkosh përpara se të vazhdosh.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Asnjë fjalëkalim i dobët}=1{1 fjalëkalim i dobët}other{{NUM_WEAK} fjalëkalime të dobëta}}</translation>
@@ -6976,6 +6981,7 @@
 <translation id="7826190688224781865">Kodi i ID-së së dyqanit të shitjes me pakicë</translation>
 <translation id="7826249772873145665">Korrigjimi i ADB-së është çaktivizuar</translation>
 <translation id="7826254698725248775">Identifikuesi i pajisjes është në konflikt.</translation>
+<translation id="7828642077514646543">Gabim: Certifikata nuk mund të dekodohet</translation>
 <translation id="7828731929332799387">Kjo do të fshijë të gjitha kukit dhe të dhënat e sajtit që ofrohen në kontekstet e palëve të treta. Dëshiron të vazhdosh?</translation>
 <translation id="7829877209233347340">Kërkoji prindit që të të japë leje për të shtuar një llogari shkolle</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7936,6 +7942,7 @@
 <translation id="8775653927968399786">{0,plural, =1{Pajisja jote <ph name="DEVICE_TYPE" /> do të kyçet automatikisht brenda # sekonde.
 <ph name="DOMAIN" /> kërkon që ti ta mbash kartën tënde smart të futur.}other{Pajisja jote <ph name="DEVICE_TYPE" /> do të kyçet automatikisht brenda # sekondash.
 <ph name="DOMAIN" /> kërkon që ti ta mbash kartën tënde smart të futur.}}</translation>
+<translation id="8776294611668764629">Organizata jote e bllokoi këtë skedar sepse ai është shumë i madh për një kontroll sigurie. Mund të hapësh skedarë deri në 50 MB.</translation>
 <translation id="8777628254805677039">fjalëkalimi rrënjë</translation>
 <translation id="8779944680596936487">Sajtet mund t'i përdorin kukit vetëm për të parë aktivitetin tënd të shfletimit në sajtin e tyre</translation>
 <translation id="8780123805589053431">Merr përshkrimet e imazhit nga Google</translation>
diff --git a/chrome/app/resources/generated_resources_sv.xtb b/chrome/app/resources/generated_resources_sv.xtb
index 4f7c90f4..df8166b 100644
--- a/chrome/app/resources/generated_resources_sv.xtb
+++ b/chrome/app/resources/generated_resources_sv.xtb
@@ -2588,6 +2588,7 @@
 <translation id="3444726579402183581"><ph name="ORIGIN" /> får läsbehörighet till <ph name="FILENAME" /></translation>
 <translation id="3445047461171030979">Snabba svar från Google Assistent</translation>
 <translation id="3445288400492335833"><ph name="MINUTES" /> min</translation>
+<translation id="344537926140058498">Organisationen blockerade filen eftersom den har känsligt eller farligt innehåll Be ägaren att åtgärda detta.</translation>
 <translation id="3445925074670675829">USB-C-enhet</translation>
 <translation id="3446274660183028131">Starta Parallels Desktop om du vill installera Windows.</translation>
 <translation id="344630545793878684">Läsa din data på ett antal webbplatser</translation>
@@ -3146,6 +3147,7 @@
 <translation id="397105322502079400">Beräknar ...</translation>
 <translation id="3971764089670057203">Fingeravtryck på den här säkerhetsnyckeln</translation>
 <translation id="3973005893595042880">Otillåten användare</translation>
+<translation id="3973062011568994448">Välj en CSV-fil för att importera lösenord.</translation>
 <translation id="3973660817924297510">Kontrollerar lösenord (<ph name="CHECKED_PASSWORDS" /> av <ph name="TOTAL_PASSWORDS" />)…</translation>
 <translation id="3974514184580396500">Flytta fokus till nästa objekt på skärmen med Nästa</translation>
 <translation id="3975201861340929143">Förklaring</translation>
@@ -4615,6 +4617,7 @@
 <translation id="5466374726908360271">Kli&amp;stra in och sök efter <ph name="SEARCH_TERMS" /></translation>
 <translation id="5467207440419968613">Behörighet till <ph name="PERMISSION_1" /> och <ph name="PERMISSION_2" /> har blockerats</translation>
 <translation id="5468173180030470402">Söker efter filresurser</translation>
+<translation id="5468881191994555667">Välj fil</translation>
 <translation id="5469852975082458401">Du kan navigera på sidor med en textmarkör. Tryck på F7 om du vill inaktivera detta.</translation>
 <translation id="5470735824776589490">En omstart krävs innan enheten kan återställas med Powerwash. <ph name="LINK_BEGIN" />Läs mer<ph name="LINK_END" /></translation>
 <translation id="5471768120198416576">Hejsan! Nu används min röst för text till tal.</translation>
@@ -6345,6 +6348,7 @@
 <translation id="7191159667348037">Okänd skrivare (USB)</translation>
 <translation id="7193051357671784796">Appen lades till av din organisation. Starta om appen för att slutföra installationen.</translation>
 <translation id="7193374945610105795">Inga lösenord har sparats för <ph name="ORIGIN" /></translation>
+<translation id="7194873994243265344">Organisationen blockerade filen eftersom den är krypterad. Be ägaren att dekryptera den.</translation>
 <translation id="7196913789568937443">Säkerhetskopiera till Google Drive. Återställ enkelt data eller byt enhet när som helst. Säkerhetskopian innehåller appdata. Säkerhetskopiorna krypteras med hjälp av Google-kontots lösenord och laddas upp på Google. <ph name="BEGIN_LINK1" />Läs mer<ph name="END_LINK1" /></translation>
 <translation id="7197190419934240522">Få Google Sök och Google-teknik varje gång du surfar</translation>
 <translation id="719791532916917144">Kortkommando</translation>
@@ -6363,6 +6367,7 @@
 <translation id="7211783048245131419">Ingen brytare har tilldelats ännu</translation>
 <translation id="7212097698621322584">Ange den nuvarande pinkoden om du vill ändra den. Om du inte kan pinkoden måste du återställa säkerhetsnyckeln och sedan ställa in en ny pinkod.</translation>
 <translation id="7213903639823314449">Sökmotorn som används i adressfältet</translation>
+<translation id="721490496276866468">Importera lösenord</translation>
 <translation id="7216595297012131718">Sortera språk i prioriteringsordning</translation>
 <translation id="7219473482981809164">Vi har hittat flera profiler som är tillgängliga för nedladdning. Välj de profiler som du vill ladda ned innan du fortsätter.</translation>
 <translation id="7219762788664143869">{NUM_WEAK,plural, =0{Inga svaga lösenord}=1{1 svagt lösenord}other{{NUM_WEAK} svaga lösenord}}</translation>
@@ -6996,6 +7001,7 @@
 <translation id="7826190688224781865">Id-kod för återförsäljarbutik</translation>
 <translation id="7826249772873145665">Felsökning med ADB har inaktiverats</translation>
 <translation id="7826254698725248775">Motstridiga enhetsidentifierare.</translation>
+<translation id="7828642077514646543">Fel: Det gick inte att avkoda certifikatet</translation>
 <translation id="7828731929332799387">Med denna åtgärd raderas alla cookies och webbplatsuppgifter som är tillgängliga i sammanhang där en tredje part är inblandad. Vill du fortsätta?</translation>
 <translation id="7829877209233347340">Be en förälder att logga in och ge behörighet att lägga till ett skolkonto</translation>
 <translation id="7831754656372780761"><ph name="TAB_TITLE" /> <ph name="EMOJI_MUTING" /></translation>
@@ -7958,6 +7964,7 @@
 <translation id="8775653927968399786">{0,plural, =1{Din <ph name="DEVICE_TYPE" /> kommer att låsas automatiskt om # sekund.
 <ph name="DOMAIN" /> kräver att du har smartkortet isatt.}other{Din <ph name="DEVICE_TYPE" /> kommer att låsas automatiskt om # sekunder.
 <ph name="DOMAIN" /> kräver att du har smartkortet isatt.}}</translation>
+<translation id="8776294611668764629">Organisationen blockerade filen eftersom den är för stor för en säkerhetskontroll. Du kan öppna filer som är upp till 50 MB stora.</translation>
 <translation id="8777628254805677039">rotlösenord</translation>
 <translation id="8779944680596936487">Webbplatser får endast se din webbaktivitet på den aktuella webbplatsen med hjälp av cookies</translation>
 <translation id="8780123805589053431">Hämta bildbeskrivningar från Google</translation>
diff --git a/chrome/browser/commerce/price_tracking/android/BUILD.gn b/chrome/browser/commerce/price_tracking/android/BUILD.gn
index 61eabf7..e2e9c23 100644
--- a/chrome/browser/commerce/price_tracking/android/BUILD.gn
+++ b/chrome/browser/commerce/price_tracking/android/BUILD.gn
@@ -11,20 +11,20 @@
 
 android_library("java") {
   sources = [
-    "java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java",
     "java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingFeatures.java",
     "java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingUtilities.java",
   ]
 
   deps = [
     "//base:base_java",
+    "//chrome/browser/commerce/subscriptions/android:java",
     "//chrome/browser/flags:java",
-    "//chrome/browser/notifications:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/signin/services/android:java",
     "//chrome/browser/tabmodel:java",
     "//components/signin/public/android:java",
+    "//components/sync/android:sync_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
 }
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java
index fcb50d77..0d2e352 100644
--- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java
+++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java
@@ -4,42 +4,227 @@
 
 package org.chromium.chrome.browser.price_tracking;
 
+import android.app.Activity;
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
 import android.content.Intent;
+import android.net.Uri;
 import android.os.Build;
+import android.os.Bundle;
+import android.provider.Browser;
+import android.provider.Settings;
+import android.text.TextUtils;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.VisibleForTesting;
 
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import org.chromium.base.Callback;
+import org.chromium.base.ContextUtils;
+import org.chromium.base.IntentUtils;
+import org.chromium.base.Log;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
+import org.chromium.chrome.browser.browserservices.intents.WebappConstants;
+import org.chromium.chrome.browser.document.ChromeLauncherActivity;
+import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
+import org.chromium.chrome.browser.notifications.NotificationIntentInterceptor;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker.SystemNotificationType;
+import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.subscriptions.CommerceSubscription;
+import org.chromium.chrome.browser.subscriptions.CommerceSubscription.CommerceSubscriptionType;
+import org.chromium.chrome.browser.subscriptions.CommerceSubscription.SubscriptionManagementType;
+import org.chromium.chrome.browser.subscriptions.CommerceSubscription.TrackingIdType;
+import org.chromium.chrome.browser.subscriptions.CommerceSubscriptionsServiceFactory;
+import org.chromium.chrome.browser.subscriptions.SubscriptionsManager;
+import org.chromium.chrome.browser.subscriptions.SubscriptionsManagerImpl;
+import org.chromium.components.browser_ui.notifications.NotificationManagerProxy;
+import org.chromium.components.browser_ui.notifications.NotificationManagerProxyImpl;
+import org.chromium.components.browser_ui.notifications.channels.ChannelsInitializer;
 
-/** Manage price drop notifications. */
-public interface PriceDropNotificationManager {
+import java.util.Locale;
+
+/**
+ * Manage price drop notifications.
+ */
+public class PriceDropNotificationManager {
+    private static final String TAG = "PriceDropNotif";
+    private static final String ACTION_APP_NOTIFICATION_SETTINGS =
+            "android.settings.APP_NOTIFICATION_SETTINGS";
+    private static final String EXTRA_APP_PACKAGE = "app_package";
+    private static final String EXTRA_APP_UID = "app_uid";
+    // The action ids should be the same as defined in the server, see {@link
+    // HandleProductUpdateEventsProducerModule}.
+    static final String ACTION_ID_VISIT_SITE = "visit_site";
+    static final String ACTION_ID_TURN_OFF_ALERT = "turn_off_alert";
+
+    static final String EXTRA_DESTINATION_URL =
+            "org.chromium.chrome.browser.price_tracking.DESTINATION_URL";
+    static final String EXTRA_ACTION_ID = "org.chromium.chrome.browser.price_tracking.ACTION_ID";
+    static final String EXTRA_OFFER_ID = "org.chromium.chrome.browser.price_tracking.OFFER_ID";
+    static final String EXTRA_PRODUCT_CLUSTER_ID =
+            "org.chromium.chrome.browser.price_tracking.PRODUCT_CLUSTER_ID";
+    static final String EXTRA_NOTIFICATION_ID =
+            "org.chromium.chrome.browser.price_tracking.NOTIFICATION_ID";
+
+    static final String CHROME_MANAGED_TIMESTAMPS =
+            ChromePreferenceKeys.PRICE_TRACKING_CHROME_MANAGED_NOTIFICATIONS_TIMESTAMPS;
+    static final String USER_MANAGED_TIMESTAMPS =
+            ChromePreferenceKeys.PRICE_TRACKING_USER_MANAGED_NOTIFICATIONS_TIMESTAMPS;
+
+    @VisibleForTesting
+    public static final String NOTIFICATION_ENABLED_HISTOGRAM =
+            "Commerce.PriceDrop.SystemNotificationEnabled";
+    @VisibleForTesting
+    public static final String NOTIFICATION_CHROME_MANAGED_COUNT_HISTOGRAM =
+            "Commerce.PriceDrops.ChromeManaged.NotificationCount";
+    @VisibleForTesting
+    public static final String NOTIFICATION_USER_MANAGED_COUNT_HISTOGRAM =
+            "Commerce.PriceDrops.UserManaged.NotificationCount";
+
+    private static NotificationManagerProxy sNotificationManagerForTesting;
+    private static BookmarkBridge sBookmarkBridgeForTesting;
+
+    /**
+     * Used to host click logic for "turn off alert" action intent.
+     */
+    public static class TrampolineActivity extends Activity {
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            Intent intent = getIntent();
+            String destinationUrl = IntentUtils.safeGetStringExtra(intent, EXTRA_DESTINATION_URL);
+            String actionId = IntentUtils.safeGetStringExtra(intent, EXTRA_ACTION_ID);
+            String offerId = IntentUtils.safeGetStringExtra(intent, EXTRA_OFFER_ID);
+            String clusterId = IntentUtils.safeGetStringExtra(intent, EXTRA_PRODUCT_CLUSTER_ID);
+            int notificationId = IntentUtils.safeGetIntExtra(intent, EXTRA_NOTIFICATION_ID, 0);
+
+            dismissNotification(notificationId);
+
+            if (TextUtils.isEmpty(offerId)) {
+                Log.e(TAG, "No offer id is provided when handling turn off alert action.");
+                finish();
+                return;
+            }
+
+            // Handles "turn off alert" action button click.
+            ChromeBrowserInitializer.getInstance().runNowOrAfterFullBrowserStarted(() -> {
+                PriceDropNotificationManager priceDropNotificationManager =
+                        PriceDropNotificationManagerFactory.create();
+                assert ACTION_ID_TURN_OFF_ALERT.equals(actionId)
+                    : "Currently only turn off alert action uses this activity.";
+                priceDropNotificationManager.onNotificationActionClicked(
+                        actionId, destinationUrl, offerId, clusterId, /*recordMetrics=*/false);
+                // Finish immediately. Could be better to have a callback from shopping backend.
+                finish();
+            });
+        }
+    }
+
+    /**
+     * Used to dismiss the notification after content click or "visit site" action click.
+     */
+    public static class DismissNotificationChromeActivity extends ChromeLauncherActivity {
+        @Override
+        public void onCreate(@Nullable Bundle savedInstanceState) {
+            int notificationId = IntentUtils.safeGetIntExtra(getIntent(), EXTRA_NOTIFICATION_ID, 0);
+            dismissNotification(notificationId);
+            super.onCreate(savedInstanceState);
+            finish();
+        }
+    }
+
+    private final Context mContext;
+    private final NotificationManagerProxy mNotificationManager;
+    private final SharedPreferencesManager mPreferencesManager;
+
+    // TODO(shaktisahu): Remove this after landing downstream changes.
+    public PriceDropNotificationManager() {
+        this(ContextUtils.getApplicationContext(),
+                new NotificationManagerProxyImpl(ContextUtils.getApplicationContext()));
+    }
+
+    /**
+     * Constructor.
+     * @param context The application context.
+     * @param notificationManagerProxy The {@link NotificationManagerProxy} for sending
+     *         notifications.
+     */
+    public PriceDropNotificationManager(
+            Context context, NotificationManagerProxy notificationManagerProxy) {
+        mContext = context;
+        mNotificationManager = notificationManagerProxy;
+        mPreferencesManager = SharedPreferencesManager.getInstance();
+    }
+
     /**
      * @return Whether the price drop notification type is enabled. For now it is used in downstream
      *         which could influence the Chime registration.
      */
-    boolean isEnabled();
+    public boolean isEnabled() {
+        return PriceTrackingFeatures.getPriceTrackingNotificationsEnabled();
+    }
 
     /**
      * @return Whether price drop notifications can be posted.
      */
-    boolean canPostNotification();
+    public boolean canPostNotification() {
+        if (!areAppNotificationsEnabled()
+                || !PriceTrackingFeatures.isPriceDropNotificationEligible()) {
+            return false;
+        }
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            NotificationChannel channel = getNotificationChannel();
+            if (channel == null || channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
+                return false;
+            }
+        }
+
+        return true;
+    }
 
     /**
      * @return Whether price drop notifications can be posted and record user opt-in metrics.
      */
-    boolean canPostNotificationWithMetricsRecorded();
+    public boolean canPostNotificationWithMetricsRecorded() {
+        if (!PriceTrackingFeatures.isPriceDropNotificationEligible()) return false;
+        boolean isSystemNotificationEnabled = areAppNotificationsEnabled();
+        RecordHistogram.recordBooleanHistogram(
+                NOTIFICATION_ENABLED_HISTOGRAM, isSystemNotificationEnabled);
+        if (!isSystemNotificationEnabled) return false;
+
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return true;
+
+        NotificationChannel channel = getNotificationChannel();
+        boolean isChannelCreated = channel != null;
+        RecordHistogram.recordBooleanHistogram(
+                "Commerce.PriceDrop.NotificationChannelCreated", isChannelCreated);
+        if (!isChannelCreated) return false;
+        boolean isChannelBlocked = channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
+        RecordHistogram.recordBooleanHistogram(
+                "Commerce.PriceDrop.NotificationChannelBlocked", isChannelBlocked);
+        return !isChannelBlocked;
+    }
 
     /**
      * Record UMAs after posting price drop notifications.
      *
      * @param notification that has been posted.
      */
-    void onNotificationPosted(@Nullable Notification notification);
+    public void onNotificationPosted(@Nullable Notification notification) {
+        NotificationUmaTracker.getInstance().onNotificationShown(
+                NotificationUmaTracker.SystemNotificationType.PRICE_DROP_ALERTS, notification);
+    }
 
     /**
      * When user clicks the notification, they will be sent to the tab with price drop which
@@ -47,7 +232,11 @@
      *
      * @param url of the tab which triggered the notification.
      */
-    void onNotificationClicked(String url);
+    public void onNotificationClicked(String url) {
+        NotificationUmaTracker.getInstance().onNotificationContentClick(
+                NotificationUmaTracker.SystemNotificationType.PRICE_DROP_ALERTS,
+                NotificationIntentInterceptor.INVALID_CREATE_TIME);
+    }
 
     /**
      * Handles the notification action click events.
@@ -58,8 +247,10 @@
      * @param recordMetrics Whether to record metrics using {@link NotificationUmaTracker}. Only
      *         Chime notification code path should set this to true.
      */
-    void onNotificationActionClicked(
-            String actionId, String url, @Nullable String offerId, boolean recordMetrics);
+    public void onNotificationActionClicked(
+            String actionId, String url, @Nullable String offerId, boolean recordMetrics) {
+        onNotificationActionClicked(actionId, url, offerId, null, recordMetrics);
+    }
 
     /**
      * Handles the notification action click events.
@@ -71,11 +262,79 @@
      * @param recordMetrics Whether to record metrics using {@link NotificationUmaTracker}. Only
      *         Chime notification code path should set this to true.
      */
-    void onNotificationActionClicked(String actionId, String url, @Nullable String offerId,
-            @Nullable String clusterId, boolean recordMetrics);
+    public void onNotificationActionClicked(String actionId, String url, @Nullable String offerId,
+            @Nullable String clusterId, boolean recordMetrics) {
+        if (actionId.equals(ACTION_ID_VISIT_SITE) && recordMetrics) {
+            NotificationUmaTracker.getInstance().onNotificationActionClick(
+                    NotificationUmaTracker.ActionType.PRICE_DROP_VISIT_SITE,
+                    NotificationUmaTracker.SystemNotificationType.PRICE_DROP_ALERTS,
+                    NotificationIntentInterceptor.INVALID_CREATE_TIME);
+        } else if (actionId.equals(ACTION_ID_TURN_OFF_ALERT)) {
+            if (offerId == null && clusterId == null) return;
+            SubscriptionsManagerImpl subscriptionsManager =
+                    (new CommerceSubscriptionsServiceFactory())
+                            .getForLastUsedProfile()
+                            .getSubscriptionsManager();
+            Callback<Integer> callback = (status) -> {
+                assert status
+                        == SubscriptionsManager.StatusCode.OK : "Failed to remove subscriptions.";
+                Log.e(TAG,
+                        String.format(
+                                Locale.US, "Failed to remove subscriptions. Status: %d", status));
+            };
+            final BookmarkBridge bookmarkBridge;
+            if (sBookmarkBridgeForTesting != null) {
+                bookmarkBridge = sBookmarkBridgeForTesting;
+            } else {
+                bookmarkBridge = new BookmarkBridge(Profile.getLastUsedRegularProfile());
+            }
+
+            Runnable unsubscribeRunnable = () -> {
+                if (offerId != null) {
+                    subscriptionsManager.unsubscribe(
+                            new CommerceSubscription(CommerceSubscriptionType.PRICE_TRACK, offerId,
+                                    SubscriptionManagementType.CHROME_MANAGED,
+                                    TrackingIdType.OFFER_ID),
+                            callback);
+                }
+                if (clusterId != null) {
+                    subscriptionsManager.unsubscribe(
+                            new CommerceSubscription(CommerceSubscriptionType.PRICE_TRACK,
+                                    clusterId, SubscriptionManagementType.USER_MANAGED,
+                                    TrackingIdType.PRODUCT_CLUSTER_ID),
+                            callback);
+                }
+            };
+
+            // Only attempt to unsubscribe once the corresponding bookmarks can also be updated.
+            if (bookmarkBridge.isBookmarkModelLoaded()) {
+                unsubscribeRunnable.run();
+            } else {
+                bookmarkBridge.addObserver(new BookmarkBridge.BookmarkModelObserver() {
+                    @Override
+                    public void bookmarkModelLoaded() {
+                        unsubscribeRunnable.run();
+                        bookmarkBridge.removeObserver(this);
+                    }
+
+                    @Override
+                    public void bookmarkModelChanged() {}
+                });
+            }
+
+            if (recordMetrics) {
+                NotificationUmaTracker.getInstance().onNotificationActionClick(
+                        NotificationUmaTracker.ActionType.PRICE_DROP_TURN_OFF_ALERT,
+                        NotificationUmaTracker.SystemNotificationType.PRICE_DROP_ALERTS,
+                        NotificationIntentInterceptor.INVALID_CREATE_TIME);
+            }
+        }
+    }
 
     @Deprecated
-    Intent getNotificationClickIntent(String url);
+    public Intent getNotificationClickIntent(String url) {
+        return getNotificationClickIntent(url, 0);
+    }
 
     /**
      * @return The intent that we will use to send users to the tab which triggered the
@@ -84,14 +343,30 @@
      * @param url of the tab which triggered the notification.
      * @param notificationId the notification id.
      */
-    Intent getNotificationClickIntent(String url, int notificationId);
+    public Intent getNotificationClickIntent(String url, int notificationId) {
+        Intent intent =
+                new Intent()
+                        .setAction(Intent.ACTION_VIEW)
+                        .setData(Uri.parse(url))
+                        .setClass(mContext, DismissNotificationChromeActivity.class)
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+                        .putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName())
+                        .putExtra(WebappConstants.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true)
+                        .putExtra(EXTRA_NOTIFICATION_ID, notificationId);
+        IntentUtils.addTrustedIntentExtras(intent);
+        return intent;
+    }
 
     @Deprecated
-    Intent getNotificationActionClickIntent(String actionId, String url, String offerId);
+    public Intent getNotificationActionClickIntent(String actionId, String url, String offerId) {
+        return getNotificationActionClickIntent(actionId, url, offerId, null, 0);
+    }
 
     @Deprecated
-    Intent getNotificationActionClickIntent(
-            String actionId, String url, String offerId, String clusterId);
+    public Intent getNotificationActionClickIntent(
+            String actionId, String url, String offerId, String clusterId) {
+        return getNotificationActionClickIntent(actionId, url, offerId, clusterId, 0);
+    }
 
     /**
      * Gets the notification action click intents.
@@ -102,54 +377,153 @@
      * @param clusterId The cluster id of the product.
      * @param notificationId the notification id.
      */
-    Intent getNotificationActionClickIntent(
-            String actionId, String url, String offerId, String clusterId, int notificationId);
+    public Intent getNotificationActionClickIntent(
+            String actionId, String url, String offerId, String clusterId, int notificationId) {
+        if (ACTION_ID_VISIT_SITE.equals(actionId)) {
+            return getNotificationClickIntent(url, notificationId);
+        }
+        if (ACTION_ID_TURN_OFF_ALERT.equals(actionId)) {
+            Intent intent = new Intent(mContext, TrampolineActivity.class);
+            intent.putExtra(EXTRA_DESTINATION_URL, url);
+            intent.putExtra(EXTRA_ACTION_ID, actionId);
+            intent.putExtra(EXTRA_OFFER_ID, offerId);
+            if (clusterId != null) intent.putExtra(EXTRA_PRODUCT_CLUSTER_ID, clusterId);
+            intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
+            IntentUtils.addTrustedIntentExtras(intent);
+            return intent;
+        }
+        return null;
+    }
 
     /**
      * @return Whether app notifications are enabled.
      */
-    boolean areAppNotificationsEnabled();
+    public boolean areAppNotificationsEnabled() {
+        if (sNotificationManagerForTesting != null) {
+            return sNotificationManagerForTesting.areNotificationsEnabled();
+        }
+        return mNotificationManager.areNotificationsEnabled();
+    }
 
     /**
      * Create the notification channel for price drop notifications.
      */
     @RequiresApi(Build.VERSION_CODES.O)
-    void createNotificationChannel();
+    public void createNotificationChannel() {
+        NotificationChannel channel = getNotificationChannel();
+        if (channel != null) return;
+        new ChannelsInitializer(mNotificationManager, ChromeChannelDefinitions.getInstance(),
+                mContext.getResources())
+                .ensureInitialized(ChromeChannelDefinitions.ChannelId.PRICE_DROP);
+    }
 
     /**
      * Send users to notification settings so they can manage price drop notifications.
      */
-    void launchNotificationSettings();
+    public void launchNotificationSettings() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            // Make sure the channel is initialized before sending users to the settings.
+            createNotificationChannel();
+        }
+        mContext.startActivity(getNotificationSettingsIntent());
+        // Disable PriceAlertsMessageCard after the first time we send users to notification
+        // settings.
+        PriceTrackingUtilities.disablePriceAlertsMessageCard();
+    }
 
     /**
      * @return The intent that we will use to send users to notification settings.
      */
     @VisibleForTesting
-    Intent getNotificationSettingsIntent();
+    public Intent getNotificationSettingsIntent() {
+        Intent intent = new Intent();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            if (areAppNotificationsEnabled()) {
+                intent.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
+                intent.putExtra(Settings.EXTRA_APP_PACKAGE, mContext.getPackageName());
+                intent.putExtra(
+                        Settings.EXTRA_CHANNEL_ID, ChromeChannelDefinitions.ChannelId.PRICE_DROP);
+            } else {
+                intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
+                intent.putExtra(Settings.EXTRA_APP_PACKAGE, mContext.getPackageName());
+            }
+        } else {
+            intent.setAction(ACTION_APP_NOTIFICATION_SETTINGS);
+            intent.putExtra(EXTRA_APP_PACKAGE, mContext.getPackageName());
+            intent.putExtra(EXTRA_APP_UID, mContext.getApplicationInfo().uid);
+        }
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return intent;
+    }
 
     /**
      * @return The price drop notification channel.
      */
     @VisibleForTesting
     @RequiresApi(Build.VERSION_CODES.O)
-    NotificationChannel getNotificationChannel();
+    public NotificationChannel getNotificationChannel() {
+        return mNotificationManager.getNotificationChannel(
+                ChromeChannelDefinitions.ChannelId.PRICE_DROP);
+    }
+
+    /**
+     * Set notificationManager for testing.
+     *
+     * @param notificationManager that will be set.
+     */
+    @VisibleForTesting
+    public static void setNotificationManagerForTesting(
+            NotificationManagerProxy notificationManager) {
+        sNotificationManagerForTesting = notificationManager;
+    }
+
+    /**
+     * Set a mock BookmarkBridge for testing so we don't need to access Profile.
+     *
+     * @param bookmarkBridge The bookmark bridge to use.
+     */
+    @VisibleForTesting
+    public static void setBookmarkBridgeForTesting(BookmarkBridge bookmarkBridge) {
+        sBookmarkBridgeForTesting = bookmarkBridge;
+    }
 
     /**
      * Delete price drop notification channel for testing.
      */
     @VisibleForTesting
     @RequiresApi(Build.VERSION_CODES.O)
-    void deleteChannelForTesting();
+    public void deleteChannelForTesting() {
+        mNotificationManager.deleteNotificationChannel(
+                ChromeChannelDefinitions.ChannelId.PRICE_DROP);
+    }
 
     /**
      * Record how many notifications are shown in the given window per management type.
      */
-    void recordMetricsForNotificationCounts();
+    public void recordMetricsForNotificationCounts() {
+        RecordHistogram.recordCount100Histogram(NOTIFICATION_CHROME_MANAGED_COUNT_HISTOGRAM,
+                updateNotificationTimestamps(
+                        SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED, false));
+        RecordHistogram.recordCount100Histogram(NOTIFICATION_USER_MANAGED_COUNT_HISTOGRAM,
+                updateNotificationTimestamps(
+                        SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED, false));
+    }
 
     /**
      * Check if the shown notifications in given window have reached the max allowed number.
      */
-    boolean hasReachedMaxAllowedNotificationNumber(@SystemNotificationType int type);
+    boolean hasReachedMaxAllowedNotificationNumber(@SystemNotificationType int type) {
+        boolean hasReached = updateNotificationTimestamps(type, false)
+                >= PriceTrackingNotificationConfig.getMaxAllowedNotificationNumber(type);
+        String managementType = notificationTypeToManagementType(type);
+        if (managementType != null) {
+            RecordHistogram.recordBooleanHistogram(
+                    String.format(Locale.US, "Commerce.PriceDrops.%s.NotificationReachedCap",
+                            managementType),
+                    hasReached);
+        }
+        return hasReached;
+    }
 
     /**
      * Update the stored notification timestamps. Outdated timestamps are removed and current
@@ -159,5 +533,64 @@
      * @param attachCurrentTime Whether to store current timestamp.
      * @return the number of stored timestamps after update.
      */
-    int updateNotificationTimestamps(@SystemNotificationType int type, boolean attachCurrentTime);
+    int updateNotificationTimestamps(@SystemNotificationType int type, boolean attachCurrentTime) {
+        long currentTime = System.currentTimeMillis();
+        JSONArray newTimestamps = new JSONArray();
+        try {
+            String oldSerializedTimestamps = getStoredNotificationTimestamps(type);
+            JSONArray oldTimestamps = new JSONArray(oldSerializedTimestamps);
+            for (int i = 0; i < oldTimestamps.length(); i++) {
+                long timestamp = oldTimestamps.getLong(i);
+                if (currentTime - timestamp > PriceTrackingNotificationConfig
+                                                      .getNotificationTimestampsStoreWindowMs()) {
+                    continue;
+                }
+                newTimestamps.put(timestamp);
+            }
+        } catch (JSONException e) {
+            Log.e(TAG,
+                    String.format(Locale.US, "Failed to parse notification timestamps. Details: %s",
+                            e.getMessage()));
+            // If one parse fails, we discard all data and reset the stored timestamps.
+            newTimestamps = new JSONArray();
+        }
+        if (attachCurrentTime) newTimestamps.put(currentTime);
+        writeSerializedNotificationTimestamps(type, newTimestamps.toString());
+        return newTimestamps.length();
+    }
+
+    private String getStoredNotificationTimestamps(@SystemNotificationType int type) {
+        String serializedTimestamps = "";
+        if (type == SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED) {
+            serializedTimestamps = mPreferencesManager.readString(CHROME_MANAGED_TIMESTAMPS, "");
+        } else if (type == SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED) {
+            serializedTimestamps = mPreferencesManager.readString(USER_MANAGED_TIMESTAMPS, "");
+        }
+        return serializedTimestamps;
+    }
+
+    private void writeSerializedNotificationTimestamps(
+            @SystemNotificationType int type, String serializedTimestamps) {
+        if (type == SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED) {
+            mPreferencesManager.writeString(CHROME_MANAGED_TIMESTAMPS, serializedTimestamps);
+        } else if (type == SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED) {
+            mPreferencesManager.writeString(USER_MANAGED_TIMESTAMPS, serializedTimestamps);
+        }
+    }
+
+    private String notificationTypeToManagementType(@SystemNotificationType int type) {
+        if (type == SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED) {
+            return "ChromeManaged";
+        } else if (type == SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED) {
+            return "UserManaged";
+        } else {
+            Log.e(TAG, "Invalid notification type.");
+            return null;
+        }
+    }
+
+    private static void dismissNotification(int notificationId) {
+        new NotificationManagerProxyImpl(ContextUtils.getApplicationContext())
+                .cancel(PriceDropNotifier.NOTIFICATION_TAG, notificationId);
+    }
 }
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerFactory.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerFactory.java
index 32d3d1f4..db26a33d 100644
--- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerFactory.java
+++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerFactory.java
@@ -16,7 +16,7 @@
 public class PriceDropNotificationManagerFactory {
     /** Builds a {@link PriceDropNotificationManager} instance. */
     public static PriceDropNotificationManager create() {
-        return new PriceDropNotificationManagerImpl(ContextUtils.getApplicationContext(),
+        return new PriceDropNotificationManager(ContextUtils.getApplicationContext(),
                 new NotificationManagerProxyImpl(ContextUtils.getApplicationContext()));
     }
 
@@ -29,6 +29,6 @@
      */
     public static PriceDropNotificationManager create(
             Context context, NotificationManagerProxy notificationManagerProxy) {
-        return new PriceDropNotificationManagerImpl(context, notificationManagerProxy);
+        return new PriceDropNotificationManager(context, notificationManagerProxy);
     }
 }
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerImpl.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerImpl.java
deleted file mode 100644
index 26ea4164..0000000
--- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerImpl.java
+++ /dev/null
@@ -1,527 +0,0 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.price_tracking;
-
-import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.provider.Browser;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.annotation.VisibleForTesting;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import org.chromium.base.Callback;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.IntentUtils;
-import org.chromium.base.Log;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
-import org.chromium.chrome.browser.browserservices.intents.WebappConstants;
-import org.chromium.chrome.browser.document.ChromeLauncherActivity;
-import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
-import org.chromium.chrome.browser.notifications.NotificationIntentInterceptor;
-import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
-import org.chromium.chrome.browser.notifications.NotificationUmaTracker.SystemNotificationType;
-import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
-import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
-import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.subscriptions.CommerceSubscription;
-import org.chromium.chrome.browser.subscriptions.CommerceSubscription.CommerceSubscriptionType;
-import org.chromium.chrome.browser.subscriptions.CommerceSubscription.SubscriptionManagementType;
-import org.chromium.chrome.browser.subscriptions.CommerceSubscription.TrackingIdType;
-import org.chromium.chrome.browser.subscriptions.CommerceSubscriptionsServiceFactory;
-import org.chromium.chrome.browser.subscriptions.SubscriptionsManager;
-import org.chromium.chrome.browser.subscriptions.SubscriptionsManagerImpl;
-import org.chromium.components.browser_ui.notifications.NotificationManagerProxy;
-import org.chromium.components.browser_ui.notifications.NotificationManagerProxyImpl;
-import org.chromium.components.browser_ui.notifications.channels.ChannelsInitializer;
-
-import java.util.Locale;
-
-/**
- * Manage price drop notifications.
- */
-public class PriceDropNotificationManagerImpl implements PriceDropNotificationManager {
-    private static final String TAG = "PriceDropNotif";
-    private static final String ACTION_APP_NOTIFICATION_SETTINGS =
-            "android.settings.APP_NOTIFICATION_SETTINGS";
-    private static final String EXTRA_APP_PACKAGE = "app_package";
-    private static final String EXTRA_APP_UID = "app_uid";
-    // The action ids should be the same as defined in the server, see {@link
-    // HandleProductUpdateEventsProducerModule}.
-    static final String ACTION_ID_VISIT_SITE = "visit_site";
-    static final String ACTION_ID_TURN_OFF_ALERT = "turn_off_alert";
-
-    static final String EXTRA_DESTINATION_URL =
-            "org.chromium.chrome.browser.price_tracking.DESTINATION_URL";
-    static final String EXTRA_ACTION_ID = "org.chromium.chrome.browser.price_tracking.ACTION_ID";
-    static final String EXTRA_OFFER_ID = "org.chromium.chrome.browser.price_tracking.OFFER_ID";
-    static final String EXTRA_PRODUCT_CLUSTER_ID =
-            "org.chromium.chrome.browser.price_tracking.PRODUCT_CLUSTER_ID";
-    static final String EXTRA_NOTIFICATION_ID =
-            "org.chromium.chrome.browser.price_tracking.NOTIFICATION_ID";
-
-    static final String CHROME_MANAGED_TIMESTAMPS =
-            ChromePreferenceKeys.PRICE_TRACKING_CHROME_MANAGED_NOTIFICATIONS_TIMESTAMPS;
-    static final String USER_MANAGED_TIMESTAMPS =
-            ChromePreferenceKeys.PRICE_TRACKING_USER_MANAGED_NOTIFICATIONS_TIMESTAMPS;
-
-    @VisibleForTesting
-    public static final String NOTIFICATION_ENABLED_HISTOGRAM =
-            "Commerce.PriceDrop.SystemNotificationEnabled";
-    @VisibleForTesting
-    public static final String NOTIFICATION_CHROME_MANAGED_COUNT_HISTOGRAM =
-            "Commerce.PriceDrops.ChromeManaged.NotificationCount";
-    @VisibleForTesting
-    public static final String NOTIFICATION_USER_MANAGED_COUNT_HISTOGRAM =
-            "Commerce.PriceDrops.UserManaged.NotificationCount";
-
-    private static NotificationManagerProxy sNotificationManagerForTesting;
-    private static BookmarkBridge sBookmarkBridgeForTesting;
-
-    /**
-     * Used to host click logic for "turn off alert" action intent.
-     */
-    public static class TrampolineActivity extends Activity {
-        @Override
-        protected void onCreate(@Nullable Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            Intent intent = getIntent();
-            String destinationUrl = IntentUtils.safeGetStringExtra(intent, EXTRA_DESTINATION_URL);
-            String actionId = IntentUtils.safeGetStringExtra(intent, EXTRA_ACTION_ID);
-            String offerId = IntentUtils.safeGetStringExtra(intent, EXTRA_OFFER_ID);
-            String clusterId = IntentUtils.safeGetStringExtra(intent, EXTRA_PRODUCT_CLUSTER_ID);
-            int notificationId = IntentUtils.safeGetIntExtra(intent, EXTRA_NOTIFICATION_ID, 0);
-
-            dismissNotification(notificationId);
-
-            if (TextUtils.isEmpty(offerId)) {
-                Log.e(TAG, "No offer id is provided when handling turn off alert action.");
-                finish();
-                return;
-            }
-
-            // Handles "turn off alert" action button click.
-            ChromeBrowserInitializer.getInstance().runNowOrAfterFullBrowserStarted(() -> {
-                PriceDropNotificationManager priceDropNotificationManager =
-                        PriceDropNotificationManagerFactory.create();
-                assert ACTION_ID_TURN_OFF_ALERT.equals(actionId)
-                    : "Currently only turn off alert action uses this activity.";
-                priceDropNotificationManager.onNotificationActionClicked(
-                        actionId, destinationUrl, offerId, clusterId, /*recordMetrics=*/false);
-                // Finish immediately. Could be better to have a callback from shopping backend.
-                finish();
-            });
-        }
-    }
-
-    /**
-     * Used to dismiss the notification after content click or "visit site" action click.
-     */
-    public static class DismissNotificationChromeActivity extends ChromeLauncherActivity {
-        @Override
-        public void onCreate(@Nullable Bundle savedInstanceState) {
-            int notificationId = IntentUtils.safeGetIntExtra(getIntent(), EXTRA_NOTIFICATION_ID, 0);
-            dismissNotification(notificationId);
-            super.onCreate(savedInstanceState);
-            finish();
-        }
-    }
-
-    private final Context mContext;
-    private final NotificationManagerProxy mNotificationManager;
-    private final SharedPreferencesManager mPreferencesManager;
-
-    /**
-     * Constructor.
-     * @param context The application context.
-     * @param notificationManagerProxy The {@link NotificationManagerProxy} for sending
-     *         notifications.
-     */
-    public PriceDropNotificationManagerImpl(
-            Context context, NotificationManagerProxy notificationManagerProxy) {
-        mContext = context;
-        mNotificationManager = notificationManagerProxy;
-        mPreferencesManager = SharedPreferencesManager.getInstance();
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return PriceTrackingFeatures.getPriceTrackingNotificationsEnabled();
-    }
-
-    @Override
-    public boolean canPostNotification() {
-        if (!areAppNotificationsEnabled()
-                || !PriceTrackingFeatures.isPriceDropNotificationEligible()) {
-            return false;
-        }
-
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            NotificationChannel channel = getNotificationChannel();
-            if (channel == null || channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean canPostNotificationWithMetricsRecorded() {
-        if (!PriceTrackingFeatures.isPriceDropNotificationEligible()) return false;
-        boolean isSystemNotificationEnabled = areAppNotificationsEnabled();
-        RecordHistogram.recordBooleanHistogram(
-                NOTIFICATION_ENABLED_HISTOGRAM, isSystemNotificationEnabled);
-        if (!isSystemNotificationEnabled) return false;
-
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return true;
-
-        NotificationChannel channel = getNotificationChannel();
-        boolean isChannelCreated = channel != null;
-        RecordHistogram.recordBooleanHistogram(
-                "Commerce.PriceDrop.NotificationChannelCreated", isChannelCreated);
-        if (!isChannelCreated) return false;
-        boolean isChannelBlocked = channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
-        RecordHistogram.recordBooleanHistogram(
-                "Commerce.PriceDrop.NotificationChannelBlocked", isChannelBlocked);
-        return !isChannelBlocked;
-    }
-
-    @Override
-    public void onNotificationPosted(@Nullable Notification notification) {
-        NotificationUmaTracker.getInstance().onNotificationShown(
-                NotificationUmaTracker.SystemNotificationType.PRICE_DROP_ALERTS, notification);
-    }
-
-    @Override
-    public void onNotificationClicked(String url) {
-        NotificationUmaTracker.getInstance().onNotificationContentClick(
-                NotificationUmaTracker.SystemNotificationType.PRICE_DROP_ALERTS,
-                NotificationIntentInterceptor.INVALID_CREATE_TIME);
-    }
-
-    @Override
-    public void onNotificationActionClicked(
-            String actionId, String url, @Nullable String offerId, boolean recordMetrics) {
-        onNotificationActionClicked(actionId, url, offerId, null, recordMetrics);
-    }
-
-    @Override
-    public void onNotificationActionClicked(String actionId, String url, @Nullable String offerId,
-            @Nullable String clusterId, boolean recordMetrics) {
-        if (actionId.equals(ACTION_ID_VISIT_SITE) && recordMetrics) {
-            NotificationUmaTracker.getInstance().onNotificationActionClick(
-                    NotificationUmaTracker.ActionType.PRICE_DROP_VISIT_SITE,
-                    NotificationUmaTracker.SystemNotificationType.PRICE_DROP_ALERTS,
-                    NotificationIntentInterceptor.INVALID_CREATE_TIME);
-        } else if (actionId.equals(ACTION_ID_TURN_OFF_ALERT)) {
-            if (offerId == null && clusterId == null) return;
-            SubscriptionsManagerImpl subscriptionsManager =
-                    (new CommerceSubscriptionsServiceFactory())
-                            .getForLastUsedProfile()
-                            .getSubscriptionsManager();
-            Callback<Integer> callback = (status) -> {
-                assert status
-                        == SubscriptionsManager.StatusCode.OK : "Failed to remove subscriptions.";
-                Log.e(TAG,
-                        String.format(
-                                Locale.US, "Failed to remove subscriptions. Status: %d", status));
-            };
-            final BookmarkBridge bookmarkBridge;
-            if (sBookmarkBridgeForTesting != null) {
-                bookmarkBridge = sBookmarkBridgeForTesting;
-            } else {
-                bookmarkBridge = new BookmarkBridge(Profile.getLastUsedRegularProfile());
-            }
-
-            Runnable unsubscribeRunnable = () -> {
-                if (offerId != null) {
-                    subscriptionsManager.unsubscribe(
-                            new CommerceSubscription(CommerceSubscriptionType.PRICE_TRACK, offerId,
-                                    SubscriptionManagementType.CHROME_MANAGED,
-                                    TrackingIdType.OFFER_ID),
-                            callback);
-                }
-                if (clusterId != null) {
-                    subscriptionsManager.unsubscribe(
-                            new CommerceSubscription(CommerceSubscriptionType.PRICE_TRACK,
-                                    clusterId, SubscriptionManagementType.USER_MANAGED,
-                                    TrackingIdType.PRODUCT_CLUSTER_ID),
-                            callback);
-                }
-            };
-
-            // Only attempt to unsubscribe once the corresponding bookmarks can also be updated.
-            if (bookmarkBridge.isBookmarkModelLoaded()) {
-                unsubscribeRunnable.run();
-            } else {
-                bookmarkBridge.addObserver(new BookmarkBridge.BookmarkModelObserver() {
-                    @Override
-                    public void bookmarkModelLoaded() {
-                        unsubscribeRunnable.run();
-                        bookmarkBridge.removeObserver(this);
-                    }
-
-                    @Override
-                    public void bookmarkModelChanged() {}
-                });
-            }
-
-            if (recordMetrics) {
-                NotificationUmaTracker.getInstance().onNotificationActionClick(
-                        NotificationUmaTracker.ActionType.PRICE_DROP_TURN_OFF_ALERT,
-                        NotificationUmaTracker.SystemNotificationType.PRICE_DROP_ALERTS,
-                        NotificationIntentInterceptor.INVALID_CREATE_TIME);
-            }
-        }
-    }
-
-    @Override
-    @Deprecated
-    public Intent getNotificationClickIntent(String url) {
-        return getNotificationClickIntent(url, 0);
-    }
-
-    @Override
-    public Intent getNotificationClickIntent(String url, int notificationId) {
-        Intent intent =
-                new Intent()
-                        .setAction(Intent.ACTION_VIEW)
-                        .setData(Uri.parse(url))
-                        .setClass(mContext, DismissNotificationChromeActivity.class)
-                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
-                        .putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName())
-                        .putExtra(WebappConstants.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true)
-                        .putExtra(EXTRA_NOTIFICATION_ID, notificationId);
-        IntentUtils.addTrustedIntentExtras(intent);
-        return intent;
-    }
-
-    @Override
-    @Deprecated
-    public Intent getNotificationActionClickIntent(String actionId, String url, String offerId) {
-        return getNotificationActionClickIntent(actionId, url, offerId, null, 0);
-    }
-
-    @Override
-    @Deprecated
-    public Intent getNotificationActionClickIntent(
-            String actionId, String url, String offerId, String clusterId) {
-        return getNotificationActionClickIntent(actionId, url, offerId, clusterId, 0);
-    }
-
-    @Override
-    public Intent getNotificationActionClickIntent(
-            String actionId, String url, String offerId, String clusterId, int notificationId) {
-        if (ACTION_ID_VISIT_SITE.equals(actionId)) {
-            return getNotificationClickIntent(url, notificationId);
-        }
-        if (ACTION_ID_TURN_OFF_ALERT.equals(actionId)) {
-            Intent intent = new Intent(mContext, TrampolineActivity.class);
-            intent.putExtra(EXTRA_DESTINATION_URL, url);
-            intent.putExtra(EXTRA_ACTION_ID, actionId);
-            intent.putExtra(EXTRA_OFFER_ID, offerId);
-            if (clusterId != null) intent.putExtra(EXTRA_PRODUCT_CLUSTER_ID, clusterId);
-            intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
-            IntentUtils.addTrustedIntentExtras(intent);
-            return intent;
-        }
-        return null;
-    }
-
-    @Override
-    public boolean areAppNotificationsEnabled() {
-        if (sNotificationManagerForTesting != null) {
-            return sNotificationManagerForTesting.areNotificationsEnabled();
-        }
-        return mNotificationManager.areNotificationsEnabled();
-    }
-
-    @Override
-    @RequiresApi(Build.VERSION_CODES.O)
-    public void createNotificationChannel() {
-        NotificationChannel channel = getNotificationChannel();
-        if (channel != null) return;
-        new ChannelsInitializer(mNotificationManager, ChromeChannelDefinitions.getInstance(),
-                mContext.getResources())
-                .ensureInitialized(ChromeChannelDefinitions.ChannelId.PRICE_DROP);
-    }
-
-    @Override
-    public void launchNotificationSettings() {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            // Make sure the channel is initialized before sending users to the settings.
-            createNotificationChannel();
-        }
-        mContext.startActivity(getNotificationSettingsIntent());
-        // Disable PriceAlertsMessageCard after the first time we send users to notification
-        // settings.
-        PriceTrackingUtilities.disablePriceAlertsMessageCard();
-    }
-
-    @Override
-    @VisibleForTesting
-    public Intent getNotificationSettingsIntent() {
-        Intent intent = new Intent();
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            if (areAppNotificationsEnabled()) {
-                intent.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
-                intent.putExtra(Settings.EXTRA_APP_PACKAGE, mContext.getPackageName());
-                intent.putExtra(
-                        Settings.EXTRA_CHANNEL_ID, ChromeChannelDefinitions.ChannelId.PRICE_DROP);
-            } else {
-                intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
-                intent.putExtra(Settings.EXTRA_APP_PACKAGE, mContext.getPackageName());
-            }
-        } else {
-            intent.setAction(ACTION_APP_NOTIFICATION_SETTINGS);
-            intent.putExtra(EXTRA_APP_PACKAGE, mContext.getPackageName());
-            intent.putExtra(EXTRA_APP_UID, mContext.getApplicationInfo().uid);
-        }
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        return intent;
-    }
-
-    @Override
-    @VisibleForTesting
-    @RequiresApi(Build.VERSION_CODES.O)
-    public NotificationChannel getNotificationChannel() {
-        return mNotificationManager.getNotificationChannel(
-                ChromeChannelDefinitions.ChannelId.PRICE_DROP);
-    }
-
-    /**
-     * Set notificationManager for testing.
-     *
-     * @param notificationManager that will be set.
-     */
-    @VisibleForTesting
-    public static void setNotificationManagerForTesting(
-            NotificationManagerProxy notificationManager) {
-        sNotificationManagerForTesting = notificationManager;
-    }
-
-    /**
-     * Set a mock BookmarkBridge for testing so we don't need to access Profile.
-     *
-     * @param bookmarkBridge The bookmark bridge to use.
-     */
-    @VisibleForTesting
-    public static void setBookmarkBridgeForTesting(BookmarkBridge bookmarkBridge) {
-        sBookmarkBridgeForTesting = bookmarkBridge;
-    }
-
-    /**
-     * Delete price drop notification channel for testing.
-     */
-    @Override
-    @VisibleForTesting
-    @RequiresApi(Build.VERSION_CODES.O)
-    public void deleteChannelForTesting() {
-        mNotificationManager.deleteNotificationChannel(
-                ChromeChannelDefinitions.ChannelId.PRICE_DROP);
-    }
-
-    @Override
-    public void recordMetricsForNotificationCounts() {
-        RecordHistogram.recordCount100Histogram(NOTIFICATION_CHROME_MANAGED_COUNT_HISTOGRAM,
-                updateNotificationTimestamps(
-                        SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED, false));
-        RecordHistogram.recordCount100Histogram(NOTIFICATION_USER_MANAGED_COUNT_HISTOGRAM,
-                updateNotificationTimestamps(
-                        SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED, false));
-    }
-
-    @Override
-    public boolean hasReachedMaxAllowedNotificationNumber(@SystemNotificationType int type) {
-        boolean hasReached = updateNotificationTimestamps(type, false)
-                >= PriceTrackingNotificationConfig.getMaxAllowedNotificationNumber(type);
-        String managementType = notificationTypeToManagementType(type);
-        if (managementType != null) {
-            RecordHistogram.recordBooleanHistogram(
-                    String.format(Locale.US, "Commerce.PriceDrops.%s.NotificationReachedCap",
-                            managementType),
-                    hasReached);
-        }
-        return hasReached;
-    }
-
-    @Override
-    public int updateNotificationTimestamps(
-            @SystemNotificationType int type, boolean attachCurrentTime) {
-        long currentTime = System.currentTimeMillis();
-        JSONArray newTimestamps = new JSONArray();
-        try {
-            String oldSerializedTimestamps = getStoredNotificationTimestamps(type);
-            JSONArray oldTimestamps = new JSONArray(oldSerializedTimestamps);
-            for (int i = 0; i < oldTimestamps.length(); i++) {
-                long timestamp = oldTimestamps.getLong(i);
-                if (currentTime - timestamp > PriceTrackingNotificationConfig
-                                                      .getNotificationTimestampsStoreWindowMs()) {
-                    continue;
-                }
-                newTimestamps.put(timestamp);
-            }
-        } catch (JSONException e) {
-            Log.e(TAG,
-                    String.format(Locale.US, "Failed to parse notification timestamps. Details: %s",
-                            e.getMessage()));
-            // If one parse fails, we discard all data and reset the stored timestamps.
-            newTimestamps = new JSONArray();
-        }
-        if (attachCurrentTime) newTimestamps.put(currentTime);
-        writeSerializedNotificationTimestamps(type, newTimestamps.toString());
-        return newTimestamps.length();
-    }
-
-    private String getStoredNotificationTimestamps(@SystemNotificationType int type) {
-        String serializedTimestamps = "";
-        if (type == SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED) {
-            serializedTimestamps = mPreferencesManager.readString(CHROME_MANAGED_TIMESTAMPS, "");
-        } else if (type == SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED) {
-            serializedTimestamps = mPreferencesManager.readString(USER_MANAGED_TIMESTAMPS, "");
-        }
-        return serializedTimestamps;
-    }
-
-    private void writeSerializedNotificationTimestamps(
-            @SystemNotificationType int type, String serializedTimestamps) {
-        if (type == SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED) {
-            mPreferencesManager.writeString(CHROME_MANAGED_TIMESTAMPS, serializedTimestamps);
-        } else if (type == SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED) {
-            mPreferencesManager.writeString(USER_MANAGED_TIMESTAMPS, serializedTimestamps);
-        }
-    }
-
-    private String notificationTypeToManagementType(@SystemNotificationType int type) {
-        if (type == SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED) {
-            return "ChromeManaged";
-        } else if (type == SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED) {
-            return "UserManaged";
-        } else {
-            Log.e(TAG, "Invalid notification type.");
-            return null;
-        }
-    }
-
-    private static void dismissNotification(int notificationId) {
-        new NotificationManagerProxyImpl(ContextUtils.getApplicationContext())
-                .cancel(PriceDropNotifier.NOTIFICATION_TAG, notificationId);
-    }
-}
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifier.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifier.java
index 25688a6a..b0cbd42c 100644
--- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifier.java
+++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifier.java
@@ -197,10 +197,10 @@
     }
 
     private static @NotificationUmaTracker.ActionType int actionIdToUmaActionType(String actionId) {
-        if (PriceDropNotificationManagerImpl.ACTION_ID_VISIT_SITE.equals(actionId)) {
+        if (PriceDropNotificationManager.ACTION_ID_VISIT_SITE.equals(actionId)) {
             return ActionType.PRICE_DROP_VISIT_SITE;
         }
-        if (PriceDropNotificationManagerImpl.ACTION_ID_TURN_OFF_ALERT.equals(actionId)) {
+        if (PriceDropNotificationManager.ACTION_ID_TURN_OFF_ALERT.equals(actionId)) {
             return ActionType.PRICE_DROP_TURN_OFF_ALERT;
         }
         return ActionType.UNKNOWN;
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationBridge.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationBridge.java
index d9bdf70e..c5aec19 100644
--- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationBridge.java
+++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationBridge.java
@@ -216,9 +216,9 @@
     private static @Nullable String getActionText(String actionId) {
         if (TextUtils.isEmpty(actionId)) return null;
         Context context = ContextUtils.getApplicationContext();
-        if (PriceDropNotificationManagerImpl.ACTION_ID_VISIT_SITE.equals(actionId)) {
+        if (PriceDropNotificationManager.ACTION_ID_VISIT_SITE.equals(actionId)) {
             return context.getString(R.string.price_drop_notification_action_visit_site);
-        } else if (PriceDropNotificationManagerImpl.ACTION_ID_TURN_OFF_ALERT.equals(actionId)) {
+        } else if (PriceDropNotificationManager.ACTION_ID_TURN_OFF_ALERT.equals(actionId)) {
             return context.getString(R.string.price_drop_notification_action_turn_off_alert);
         }
         return null;
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingUtilities.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingUtilities.java
index 947dfd73..ace2080b 100644
--- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingUtilities.java
+++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingUtilities.java
@@ -6,10 +6,9 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.base.FeatureList;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.subscriptions.CommerceSubscriptionsServiceConfig;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 
 /** Utility class for price tracking. */
@@ -29,11 +28,6 @@
     public static final String PRICE_ALERTS_MESSAGE_CARD_SHOW_COUNT =
             ChromePreferenceKeys.PRICE_TRACKING_PRICE_ALERTS_MESSAGE_CARD_SHOW_COUNT;
 
-    // TODO(zhiyuancai): Dedup from CommerceSubscriptionsServiceConfig.java.
-    @VisibleForTesting
-    public static final String IMPLICIT_SUBSCRIPTIONS_ENABLED_PARAM =
-            "implicit_subscriptions_enabled";
-
     @VisibleForTesting
     public static final SharedPreferencesManager SHARED_PREFERENCES_MANAGER =
             SharedPreferencesManager.getInstance();
@@ -108,7 +102,7 @@
      */
     public static boolean isPriceAlertsMessageCardEnabled() {
         return PriceTrackingFeatures.isPriceDropNotificationEligible()
-                && isImplicitSubscriptionsEnabled()
+                && CommerceSubscriptionsServiceConfig.isImplicitSubscriptionsEnabled()
                 && SHARED_PREFERENCES_MANAGER.readBoolean(
                         PRICE_ALERTS_MESSAGE_CARD, PriceTrackingFeatures.isPriceTrackingEnabled());
     }
@@ -153,13 +147,4 @@
     public static boolean shouldShowPriceTrackingMenu() {
         return false;
     }
-
-    private static boolean isImplicitSubscriptionsEnabled() {
-        if (FeatureList.isInitialized()) {
-            return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
-                    ChromeFeatureList.COMMERCE_PRICE_TRACKING, IMPLICIT_SUBSCRIPTIONS_ENABLED_PARAM,
-                    false);
-        }
-        return false;
-    }
 }
\ No newline at end of file
diff --git a/chrome/browser/commerce/price_tracking/android/java_sources.gni b/chrome/browser/commerce/price_tracking/android/java_sources.gni
index 5c6dc83..539dd4c 100644
--- a/chrome/browser/commerce/price_tracking/android/java_sources.gni
+++ b/chrome/browser/commerce/price_tracking/android/java_sources.gni
@@ -3,13 +3,10 @@
 # found in the LICENSE file.
 
 price_tracking_java_sources = [
+  "//chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java",
   "//chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerFactory.java",
-  "//chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerImpl.java",
   "//chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifier.java",
   "//chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingButtonController.java",
   "//chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationBridge.java",
   "//chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationConfig.java",
 ]
-
-price_tracking_java_deps =
-    [ "//chrome/browser/commerce/price_tracking/android:java" ]
diff --git a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java
index b107f5f..5db25fe 100644
--- a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java
+++ b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java
@@ -47,7 +47,7 @@
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker.SystemNotificationType;
 import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
-import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl.DismissNotificationChromeActivity;
+import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager.DismissNotificationChromeActivity;
 import org.chromium.chrome.browser.subscriptions.CommerceSubscription;
 import org.chromium.chrome.browser.subscriptions.CommerceSubscription.CommerceSubscriptionType;
 import org.chromium.chrome.browser.subscriptions.CommerceSubscription.SubscriptionManagementType;
@@ -110,10 +110,10 @@
     @Before
     public void setUp() {
         mMockNotificationManager = new MockNotificationManagerProxy();
-        PriceDropNotificationManagerImpl.setNotificationManagerForTesting(mMockNotificationManager);
+        PriceDropNotificationManager.setNotificationManagerForTesting(mMockNotificationManager);
         mPriceDropNotificationManager = PriceDropNotificationManagerFactory.create();
         when(mMockBookmarkBridge.isBookmarkModelLoaded()).thenReturn(true);
-        PriceDropNotificationManagerImpl.setBookmarkBridgeForTesting(mMockBookmarkBridge);
+        PriceDropNotificationManager.setBookmarkBridgeForTesting(mMockBookmarkBridge);
     }
 
     @After
@@ -121,7 +121,7 @@
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             mPriceDropNotificationManager.deleteChannelForTesting();
         }
-        PriceDropNotificationManagerImpl.setNotificationManagerForTesting(null);
+        PriceDropNotificationManager.setNotificationManagerForTesting(null);
     }
 
     private void verifyClickIntent(Intent intent) {
@@ -136,7 +136,7 @@
         assertEquals(true,
                 intent.getBooleanExtra(WebappConstants.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, false));
         assertEquals(NOTIFICATION_ID,
-                intent.getIntExtra(PriceDropNotificationManagerImpl.EXTRA_NOTIFICATION_ID, 0));
+                intent.getIntExtra(PriceDropNotificationManager.EXTRA_NOTIFICATION_ID, 0));
     }
 
     @Test
@@ -240,23 +240,23 @@
         Intent turnOffAlertIntent = mPriceDropNotificationManager.getNotificationActionClickIntent(
                 ACTION_ID_TURN_OFF_ALERT, TEST_URL, OFFER_ID, PRODUCT_CLUSTER_ID, NOTIFICATION_ID);
         assertNotNull(turnOffAlertIntent);
-        assertEquals(PriceDropNotificationManagerImpl.TrampolineActivity.class.getName(),
+        assertEquals(PriceDropNotificationManager.TrampolineActivity.class.getName(),
                 turnOffAlertIntent.getComponent().getClassName());
         assertEquals(PRODUCT_CLUSTER_ID,
-                IntentUtils.safeGetStringExtra(turnOffAlertIntent,
-                        PriceDropNotificationManagerImpl.EXTRA_PRODUCT_CLUSTER_ID));
+                IntentUtils.safeGetStringExtra(
+                        turnOffAlertIntent, PriceDropNotificationManager.EXTRA_PRODUCT_CLUSTER_ID));
         assertEquals(OFFER_ID,
                 IntentUtils.safeGetStringExtra(
-                        turnOffAlertIntent, PriceDropNotificationManagerImpl.EXTRA_OFFER_ID));
+                        turnOffAlertIntent, PriceDropNotificationManager.EXTRA_OFFER_ID));
         assertEquals(TEST_URL,
-                IntentUtils.safeGetStringExtra(turnOffAlertIntent,
-                        PriceDropNotificationManagerImpl.EXTRA_DESTINATION_URL));
+                IntentUtils.safeGetStringExtra(
+                        turnOffAlertIntent, PriceDropNotificationManager.EXTRA_DESTINATION_URL));
         assertEquals(ACTION_ID_TURN_OFF_ALERT,
                 IntentUtils.safeGetStringExtra(
-                        turnOffAlertIntent, PriceDropNotificationManagerImpl.EXTRA_ACTION_ID));
+                        turnOffAlertIntent, PriceDropNotificationManager.EXTRA_ACTION_ID));
         assertEquals(NOTIFICATION_ID,
-                IntentUtils.safeGetIntExtra(turnOffAlertIntent,
-                        PriceDropNotificationManagerImpl.EXTRA_NOTIFICATION_ID, 0));
+                IntentUtils.safeGetIntExtra(
+                        turnOffAlertIntent, PriceDropNotificationManager.EXTRA_NOTIFICATION_ID, 0));
     }
 
     @Test
@@ -300,7 +300,7 @@
         JSONArray jsonArray = new JSONArray();
         jsonArray.put(mockTimestamp);
         preferencesManager.writeString(
-                PriceDropNotificationManagerImpl.USER_MANAGED_TIMESTAMPS, jsonArray.toString());
+                PriceDropNotificationManager.USER_MANAGED_TIMESTAMPS, jsonArray.toString());
         assertEquals(
                 0, mPriceDropNotificationManager.updateNotificationTimestamps(mockType, false));
 
@@ -308,15 +308,14 @@
         jsonArray = new JSONArray();
         jsonArray.put(mockTimestamp);
         preferencesManager.writeString(
-                PriceDropNotificationManagerImpl.USER_MANAGED_TIMESTAMPS, jsonArray.toString());
+                PriceDropNotificationManager.USER_MANAGED_TIMESTAMPS, jsonArray.toString());
         assertEquals(
                 1, mPriceDropNotificationManager.updateNotificationTimestamps(mockType, false));
 
         assertEquals(2, mPriceDropNotificationManager.updateNotificationTimestamps(mockType, true));
         assertEquals(3, mPriceDropNotificationManager.updateNotificationTimestamps(mockType, true));
 
-        preferencesManager.writeString(
-                PriceDropNotificationManagerImpl.USER_MANAGED_TIMESTAMPS, "");
+        preferencesManager.writeString(PriceDropNotificationManager.USER_MANAGED_TIMESTAMPS, "");
         assertEquals(
                 0, mPriceDropNotificationManager.updateNotificationTimestamps(mockType, false));
         assertEquals(1, mPriceDropNotificationManager.updateNotificationTimestamps(mockType, true));
diff --git a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifierUnitTest.java b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifierUnitTest.java
index 7dba11a..4fd63d67 100644
--- a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifierUnitTest.java
+++ b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifierUnitTest.java
@@ -139,10 +139,10 @@
 
     private void showNotification() {
         List<ActionData> actionDataList = new ArrayList<>();
+        actionDataList.add(
+                new ActionData(PriceDropNotificationManager.ACTION_ID_VISIT_SITE, ACTION_TEXT_0));
         actionDataList.add(new ActionData(
-                PriceDropNotificationManagerImpl.ACTION_ID_VISIT_SITE, ACTION_TEXT_0));
-        actionDataList.add(new ActionData(
-                PriceDropNotificationManagerImpl.ACTION_ID_TURN_OFF_ALERT, ACTION_TEXT_1));
+                PriceDropNotificationManager.ACTION_ID_TURN_OFF_ALERT, ACTION_TEXT_1));
         showNotification(actionDataList);
     }
 
@@ -161,7 +161,7 @@
         // Simulate to send a PendingIntent by manually starting the TrampolineActivity.
         ShadowPendingIntent shadowPendingIntent = Shadows.shadowOf(pendingIntent);
         Robolectric
-                .buildActivity(PriceDropNotificationManagerImpl.TrampolineActivity.class,
+                .buildActivity(PriceDropNotificationManager.TrampolineActivity.class,
                         shadowPendingIntent.getSavedIntent())
                 .create();
     }
diff --git a/chrome/browser/commerce/subscriptions/android/BUILD.gn b/chrome/browser/commerce/subscriptions/android/BUILD.gn
index 4d1781460..d2b163d 100644
--- a/chrome/browser/commerce/subscriptions/android/BUILD.gn
+++ b/chrome/browser/commerce/subscriptions/android/BUILD.gn
@@ -11,41 +11,12 @@
   ]
 }
 
-android_library("subscriptions_java") {
-  sources = [
-    "java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscription.java",
-    "java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionJsonSerializer.java",
-    "java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsMetrics.java",
-    "java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsService.java",
-    "java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceConfig.java",
-    "java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceProxy.java",
-    "java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsStorage.java",
-    "java/src/org/chromium/chrome/browser/subscriptions/ImplicitPriceDropSubscriptionsManager.java",
-    "java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManager.java",
-    "java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImpl.java",
-  ]
+android_library("java") {
+  sources = [ "java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceConfig.java" ]
 
   deps = [
     "//base:base_java",
-    "//base:jni_java",
-    "//build/android:build_java",
-    "//chrome/browser/android/lifecycle:java",
-    "//chrome/browser/commerce/price_tracking/android:java",
-    "//chrome/browser/endpoint_fetcher:java",
     "//chrome/browser/flags:java",
-    "//chrome/browser/preferences:java",
-    "//chrome/browser/profiles/android:java",
-    "//chrome/browser/signin/services/android:java",
-    "//chrome/browser/tab:java",
-    "//chrome/browser/tabmodel:java",
-    "//components/prefs/android:java",
-    "//components/signin/public/android:java",
-    "//components/user_prefs/android:java",
-    "//content/public/android:content_full_java",
-    "//net/android:net_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
-    "//url:gurl_java",
   ]
-
-  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
diff --git a/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsService.java b/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsService.java
index 34017bbe..17a8264 100644
--- a/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsService.java
+++ b/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsService.java
@@ -11,6 +11,7 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager;
+import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerFactory;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingFeatures;
 import org.chromium.chrome.browser.subscriptions.CommerceSubscription.CommerceSubscriptionType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
@@ -38,9 +39,8 @@
     private PauseResumeWithNativeObserver mPauseResumeWithNativeObserver;
 
     /** Creates a new instance. */
-    CommerceSubscriptionsService(SubscriptionsManagerImpl subscriptionsManager,
-            IdentityManager identityManager,
-            PriceDropNotificationManager priceDropNotificationManager) {
+    CommerceSubscriptionsService(
+            SubscriptionsManagerImpl subscriptionsManager, IdentityManager identityManager) {
         mSubscriptionManager = subscriptionsManager;
         mIdentityManager = identityManager;
         mIdentityManagerObserver = new IdentityManager.Observer() {
@@ -51,7 +51,7 @@
         };
         mIdentityManager.addObserver(mIdentityManagerObserver);
         mSharedPreferencesManager = SharedPreferencesManager.getInstance();
-        mPriceDropNotificationManager = priceDropNotificationManager;
+        mPriceDropNotificationManager = PriceDropNotificationManagerFactory.create();
         mMetrics = new CommerceSubscriptionsMetrics();
     }
 
diff --git a/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceFactory.java b/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceFactory.java
index 09124c6..ac923a9 100644
--- a/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceFactory.java
+++ b/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceFactory.java
@@ -6,8 +6,6 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager;
-import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerFactory;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileManager;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
@@ -64,12 +62,8 @@
         Profile profile = Profile.getLastUsedRegularProfile();
         CommerceSubscriptionsService service = sProfileToSubscriptionsService.get(profile);
         if (service == null) {
-            PriceDropNotificationManager priceDropNotificationManager =
-                    PriceDropNotificationManagerFactory.create();
-            service = new CommerceSubscriptionsService(
-                    new SubscriptionsManagerImpl(profile, priceDropNotificationManager),
-                    IdentityServicesProvider.get().getIdentityManager(profile),
-                    priceDropNotificationManager);
+            service = new CommerceSubscriptionsService(new SubscriptionsManagerImpl(profile),
+                    IdentityServicesProvider.get().getIdentityManager(profile));
             sProfileToSubscriptionsService.put(profile, service);
         }
         return service;
diff --git a/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImpl.java b/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImpl.java
index 8eba7bb..0e662047 100644
--- a/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImpl.java
+++ b/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImpl.java
@@ -11,7 +11,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ObserverList;
-import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager;
+import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerFactory;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingFeatures;
 import org.chromium.chrome.browser.profiles.Profile;
 
@@ -43,7 +43,6 @@
     private boolean mCanHandleRequests;
     private Queue<DeferredSubscriptionOperation> mDeferredTasks;
     private final ObserverList<SubscriptionObserver> mObservers;
-    private final PriceDropNotificationManager mPriceDropNotificationManager;
 
     private static class DeferredSubscriptionOperation {
         private final @Operation int mOperation;
@@ -70,19 +69,16 @@
         }
     }
 
-    public SubscriptionsManagerImpl(
-            Profile profile, PriceDropNotificationManager priceDropNotificationManager) {
+    public SubscriptionsManagerImpl(Profile profile) {
         this(profile, new CommerceSubscriptionsStorage(profile),
-                new CommerceSubscriptionsServiceProxy(profile), priceDropNotificationManager);
+                new CommerceSubscriptionsServiceProxy(profile));
     }
 
     @VisibleForTesting
     SubscriptionsManagerImpl(Profile profile, CommerceSubscriptionsStorage storage,
-            CommerceSubscriptionsServiceProxy proxy,
-            PriceDropNotificationManager priceDropNotificationManager) {
+            CommerceSubscriptionsServiceProxy proxy) {
         mStorage = storage;
         mServiceProxy = proxy;
-        mPriceDropNotificationManager = priceDropNotificationManager;
         mDeferredTasks = new LinkedList<>();
         mCanHandleRequests = false;
         initTypes(this::onInitComplete);
@@ -152,7 +148,7 @@
                 && CommerceSubscription.SubscriptionManagementType.USER_MANAGED.equals(
                         subscriptions.get(0).getManagementType())
                 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            mPriceDropNotificationManager.createNotificationChannel();
+            (PriceDropNotificationManagerFactory.create()).createNotificationChannel();
         }
 
         if (!mCanHandleRequests) {
@@ -435,4 +431,4 @@
     public void setCanHandlerequests(boolean value) {
         mCanHandleRequests = value;
     }
-}
+}
\ No newline at end of file
diff --git a/chrome/browser/commerce/subscriptions/android/java_sources.gni b/chrome/browser/commerce/subscriptions/android/java_sources.gni
index 53a1fc8..dc262ae 100644
--- a/chrome/browser/commerce/subscriptions/android/java_sources.gni
+++ b/chrome/browser/commerce/subscriptions/android/java_sources.gni
@@ -4,10 +4,29 @@
 
 # TODO(crbug/1210158): This should be a separate build target when circular
 # dependencies are removed.
-commerce_subscriptions_java_sources = [ "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceFactory.java" ]
+commerce_subscriptions_java_sources = [
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscription.java",
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionJsonSerializer.java",
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsMetrics.java",
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsService.java",
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceFactory.java",
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceProxy.java",
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsStorage.java",
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/ImplicitPriceDropSubscriptionsManager.java",
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManager.java",
+  "//chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImpl.java",
+]
 
 commerce_subscriptions_java_deps = [
   "//base:base_java",
+  "//base:jni_java",
+  "//chrome/android:base_module_java",
+  "//chrome/browser/android/lifecycle:java",
+  "//chrome/browser/endpoint_fetcher:java",
+  "//chrome/browser/flags:java",
+  "//chrome/browser/preferences:java",
   "//chrome/browser/profiles/android:java",
-  "//chrome/browser/signin/services/android:java",
+  "//chrome/browser/tab:java",
+  "//chrome/browser/tabmodel:java",
+  "//url:gurl_java",
 ]
diff --git a/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceUnitTest.java b/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceUnitTest.java
index 0fd2eb6..81d05273 100644
--- a/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceUnitTest.java
+++ b/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceUnitTest.java
@@ -42,8 +42,6 @@
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager;
-import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerFactory;
-import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingFeatures;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
@@ -105,7 +103,6 @@
     private CommerceSubscriptionsService mService;
     private SharedPreferencesManager mSharedPreferencesManager;
     private MockNotificationManagerProxy mMockNotificationManager;
-    private PriceDropNotificationManager mPriceDropNotificationManager;
     private FeatureList.TestValues mTestValues;
 
     @Before
@@ -131,7 +128,7 @@
 
         mMockNotificationManager = new MockNotificationManagerProxy();
         mMockNotificationManager.setNotificationsEnabled(false);
-        PriceDropNotificationManagerImpl.setNotificationManagerForTesting(mMockNotificationManager);
+        PriceDropNotificationManager.setNotificationManagerForTesting(mMockNotificationManager);
 
         mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsJni);
         Profile.setLastUsedProfileForTesting(mProfile);
@@ -139,16 +136,14 @@
         IdentityServicesProvider.setInstanceForTests(mIdentityServicesProvider);
         when(mIdentityServicesProvider.getIdentityManager(mProfile)).thenReturn(mIdentityManager);
 
-        mPriceDropNotificationManager = PriceDropNotificationManagerFactory.create();
-        mService = new CommerceSubscriptionsService(
-                mSubscriptionsManager, mIdentityManager, mPriceDropNotificationManager);
+        mService = new CommerceSubscriptionsService(mSubscriptionsManager, mIdentityManager);
         verify(mIdentityManager, times(1)).addObserver(mIdentityManagerObserverCaptor.capture());
         mService.setImplicitSubscriptionsManagerForTesting(mImplicitSubscriptionsManager);
     }
 
     @After
     public void tearDown() {
-        PriceDropNotificationManagerImpl.setNotificationManagerForTesting(null);
+        PriceDropNotificationManager.setNotificationManagerForTesting(null);
     }
 
     @Test
@@ -187,15 +182,14 @@
     public void testOnResume() {
         setupTestOnResume();
         assertThat(RecordHistogram.getHistogramTotalCountForTesting(
-                           PriceDropNotificationManagerImpl.NOTIFICATION_ENABLED_HISTOGRAM),
-                equalTo(1));
-        assertThat(RecordHistogram.getHistogramTotalCountForTesting(
-                           PriceDropNotificationManagerImpl
-                                   .NOTIFICATION_CHROME_MANAGED_COUNT_HISTOGRAM),
+                           PriceDropNotificationManager.NOTIFICATION_ENABLED_HISTOGRAM),
                 equalTo(1));
         assertThat(
                 RecordHistogram.getHistogramTotalCountForTesting(
-                        PriceDropNotificationManagerImpl.NOTIFICATION_USER_MANAGED_COUNT_HISTOGRAM),
+                        PriceDropNotificationManager.NOTIFICATION_CHROME_MANAGED_COUNT_HISTOGRAM),
+                equalTo(1));
+        assertThat(RecordHistogram.getHistogramTotalCountForTesting(
+                           PriceDropNotificationManager.NOTIFICATION_USER_MANAGED_COUNT_HISTOGRAM),
                 equalTo(1));
         verify(mSubscriptionsManager, times(1))
                 .getSubscriptions(eq(CommerceSubscriptionType.PRICE_TRACK), eq(false),
@@ -239,7 +233,7 @@
 
         setupTestOnResume();
         assertThat(RecordHistogram.getHistogramTotalCountForTesting(
-                           PriceDropNotificationManagerImpl.NOTIFICATION_ENABLED_HISTOGRAM),
+                           PriceDropNotificationManager.NOTIFICATION_ENABLED_HISTOGRAM),
                 equalTo(0));
         verify(mSubscriptionsManager, times(0)).getSubscriptions(anyString(), anyBoolean(), any());
         verify(mImplicitSubscriptionsManager, times(0)).initializeSubscriptions();
@@ -254,7 +248,7 @@
 
         setupTestOnResume();
         assertThat(RecordHistogram.getHistogramTotalCountForTesting(
-                           PriceDropNotificationManagerImpl.NOTIFICATION_ENABLED_HISTOGRAM),
+                           PriceDropNotificationManager.NOTIFICATION_ENABLED_HISTOGRAM),
                 equalTo(0));
         verify(mSubscriptionsManager, times(0)).getSubscriptions(anyString(), anyBoolean(), any());
         verify(mImplicitSubscriptionsManager, times(0)).initializeSubscriptions();
diff --git a/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImplTest.java b/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImplTest.java
index 2015ad404..83b04525 100644
--- a/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImplTest.java
+++ b/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/SubscriptionsManagerImplTest.java
@@ -33,8 +33,6 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager;
-import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerFactory;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingFeatures;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.test.util.browser.Features;
@@ -97,11 +95,8 @@
         FeatureList.setTestValues(mTestValues);
         PriceTrackingFeatures.setIsSignedInAndSyncEnabledForTesting(true);
 
-        PriceDropNotificationManager priceDropNotificationManager =
-                PriceDropNotificationManagerFactory.create();
         mMocker.mock(CommerceSubscriptionsStorageJni.TEST_HOOKS, mCommerceSubscriptionsStorageJni);
-        mSubscriptionsManager = new SubscriptionsManagerImpl(
-                mProfile, mStorage, mProxy, priceDropNotificationManager);
+        mSubscriptionsManager = new SubscriptionsManagerImpl(mProfile, mStorage, mProxy);
 
         mSubscription1 =
                 new CommerceSubscription(CommerceSubscription.CommerceSubscriptionType.PRICE_TRACK,
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index e42c253..1b02eb4 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -97,6 +97,10 @@
   // Whether the download is currently being revived.
   bool is_being_revived_;
 
+  // Whether the safe browsing download warning was shown (and recorded) earlier
+  // on the UI.
+  bool was_ui_warning_shown_ = false;
+
  private:
   DownloadItemModelData();
 
@@ -419,6 +423,16 @@
   data->was_ui_notified_ = was_ui_notified;
 }
 
+bool DownloadItemModel::WasUIWarningShown() const {
+  const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
+  return data && data->was_ui_warning_shown_;
+}
+
+void DownloadItemModel::SetWasUIWarningShown(bool was_ui_warning_shown) {
+  DownloadItemModelData* data = DownloadItemModelData::GetOrCreate(download_);
+  data->was_ui_warning_shown_ = was_ui_warning_shown;
+}
+
 bool DownloadItemModel::ShouldPreferOpeningInBrowser() const {
   const DownloadItemModelData* data = DownloadItemModelData::Get(download_);
   return data && data->should_prefer_opening_in_browser_;
diff --git a/chrome/browser/download/download_item_model.h b/chrome/browser/download/download_item_model.h
index 6267e09..362f349 100644
--- a/chrome/browser/download/download_item_model.h
+++ b/chrome/browser/download/download_item_model.h
@@ -66,6 +66,8 @@
   bool ShouldNotifyUI() const override;
   bool WasUINotified() const override;
   void SetWasUINotified(bool should_notify) override;
+  bool WasUIWarningShown() const override;
+  void SetWasUIWarningShown(bool should_notify) override;
   bool ShouldPreferOpeningInBrowser() const override;
   void SetShouldPreferOpeningInBrowser(bool preference) override;
   safe_browsing::DownloadFileType::DangerLevel GetDangerLevel() const override;
diff --git a/chrome/browser/download/download_ui_model.cc b/chrome/browser/download/download_ui_model.cc
index a45307cb..b9c7f62 100644
--- a/chrome/browser/download/download_ui_model.cc
+++ b/chrome/browser/download/download_ui_model.cc
@@ -414,6 +414,12 @@
 
 void DownloadUIModel::SetWasUINotified(bool should_notify) {}
 
+bool DownloadUIModel::WasUIWarningShown() const {
+  return false;
+}
+
+void DownloadUIModel::SetWasUIWarningShown(bool was_ui_warning_shown) {}
+
 bool DownloadUIModel::ShouldPreferOpeningInBrowser() const {
   return true;
 }
diff --git a/chrome/browser/download/download_ui_model.h b/chrome/browser/download/download_ui_model.h
index 702797b..d889c4a0 100644
--- a/chrome/browser/download/download_ui_model.h
+++ b/chrome/browser/download/download_ui_model.h
@@ -293,6 +293,14 @@
   // Change what's returned by WasUINotified().
   virtual void SetWasUINotified(bool should_notify);
 
+  // Returns |true| if the Download Bubble UI has shown this download warning.
+  // By default, this value is |false| and should be changed explicitly using
+  // SetWasUIWarningShown().
+  virtual bool WasUIWarningShown() const;
+
+  // Change what's returned by WasUIWarningShown().
+  virtual void SetWasUIWarningShown(bool was_ui_warning_shown);
+
   // Returns |true| if opening in the browser is preferred for this download. If
   // |false|, the download should be opened with the system default application.
   virtual bool ShouldPreferOpeningInBrowser() const;
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_as.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_as.xtb
index 2340101..2c9b8e0 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_as.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_as.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">এই ডিভাইচটোত কণ্ঠধ্বনিৰ দ্বাৰা সন্ধান কৰাৰ সুবিধাটো উপলব্ধ নহয়</translation>
 <translation id="3749259744154402564">অসমৰ্থিত</translation>
 <translation id="3771033907050503522">ইনক’গনিট’ টেব</translation>
+<translation id="377124182565324804"><ph name="SITE" /> যোগ দিয়ক</translation>
 <translation id="3771290962915251154">অভিভাৱকীয় নিয়ন্ত্ৰণসমূহ অন হৈ থকাৰ বাবে এই ছেটিংটো অক্ষম কৰা হৈছে</translation>
 <translation id="3771694256347217732">Google সেৱাৰ চৰ্তাৱলী</translation>
 <translation id="3773856050682458546">প্ৰাথমিক ডেটাৰ লগতে আপুনি চোৱা ৱেবছাইট আৰু আপুনি ব্যৱহাৰ কৰা এপৰ বিষয়ে তথ্য</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">মুক্ত উত্‍সৰ অনুজ্ঞাপত্ৰ</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />কি ডেটা ব্যৱহাৰ কৰা হয়:<ph name="END_BOLD" /> আপোনাৰ ব্ৰাউজিঙৰ ইতিহাস, আপুনি এই ডিভাইচটোত Chrome ব্যৱহাৰ কৰি চোৱা ছাইটৰ ৰেকৰ্ড।</translation>
 <translation id="4263656433980196874">Assistantৰ কণ্ঠধ্বনিৰদ্বাৰা সন্ধানৰ সন্মতিৰ ইউআই পূৰ্ণ উচ্চতাত খোল খাইছে</translation>
+<translation id="4266054596873078491">আপোনাৰ Google একাউণ্টটোৰ জৰিয়তে এইটো ছাইট আৰু Chromeত ছাইন ইন কৰক।</translation>
 <translation id="4269820728363426813">লিংকৰ ঠিকনাটো প্ৰতিলিপি কৰক</translation>
 <translation id="4290281343757112331">ইয়াৰ সলনি পাছত ডাউনল'ড কৰিবনে?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Android ছেটিঙত স্ক্ৰীন লক অন কৰক<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">আপোনাৰ ব্ৰাউজাৰটো পৰিচালিত নহয়</translation>
 <translation id="5339031667684712858">আপুনি আঁতৰোৱা ছাইট</translation>
 <translation id="5342314432463739672">অনুমতিৰ অনুৰোধবোৰ</translation>
+<translation id="53537532693258630">আপুনি আঁতৰোৱা ছাইটসমূহ ইয়াত প্ৰদৰ্শিত হ’ব</translation>
 <translation id="5355191726083956201">বৰ্ধিত সুৰক্ষা অন আছে</translation>
 <translation id="5368227114232678694">এই ব্ৰাউজাৰটোত ব্যক্তিগতভাৱে ব্ৰাউজ কৰিবলৈ, ইনক’গনিট’ টেবটো ব্যৱহাৰ কৰি চাওক</translation>
 <translation id="5375577065097716013">Google Lensৰে প্ৰতিচ্ছবি সন্ধান কৰক <ph name="BEGIN_NEW" />নতুন<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">ইনক’গনিট’ ম’ডত এটা নতুন টেব খোলক</translation>
 <translation id="8996847606757455498">অন্য এক প্ৰদানকাৰী বাছনি কৰক</translation>
 <translation id="8998729206196772491">আপুনি <ph name="MANAGED_DOMAIN" />এ পৰিচালনা কৰা এটা একাউণ্টৰ জৰিয়তে ছাইন ইন কৰিছে আৰু সেইটোৰ প্ৰশাসকে আপোনাৰ Chrome ডেটা নিয়ন্ত্ৰণ কৰিবলৈ সুবিধা দিছে। আপোনাৰ ডেটা এই একাউণ্টটোৰ সৈতে স্থায়ীভাৱে সংযুক্তহৈ থাকিব। Chromeৰ পৰা ছাইন আউট কৰিলে আপোনাৰ ডেটা মচা যাব কিন্ত সেইবোৰ আপোনাৰ Google একাউণ্টত জমা হৈয়ে থাকিব।</translation>
+<translation id="9021388532480169802">ছাইট যোগ দিয়া হ’ল</translation>
 <translation id="9022774213089566801">সঘনাই যোৱা</translation>
 <translation id="9028914725102941583">সমগ্ৰ ডিভাইচত শ্বেয়াৰ কৰিবলৈ ছিংক অন কৰক</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{#টা ভিডিঅ’}one{#টা ভিডিঅ’}other{#টা ভিডিঅ’}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_es.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_es.xtb
index cad05a3..a069a36 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_es.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_es.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">La búsqueda por voz no está disponible en este dispositivo</translation>
 <translation id="3749259744154402564">No admitido</translation>
 <translation id="3771033907050503522">Pestañas incógnito</translation>
+<translation id="377124182565324804">Añadir <ph name="SITE" /></translation>
 <translation id="3771290962915251154">Este ajuste está inhabilitado porque el control parental está activado</translation>
 <translation id="3771694256347217732">Términos del Servicio de Google</translation>
 <translation id="3773856050682458546">Datos básicos e información sobre los sitios web que visitas y las aplicaciones que usas.</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Licencias de software libre</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Qué datos se usan:<ph name="END_BOLD" /> tu historial de navegación, un registro de los sitios que has visitado usando Chrome en este dispositivo.</translation>
 <translation id="4263656433980196874">Interfaz de consentimiento de la búsqueda por voz del Asistente abierta a altura completa</translation>
+<translation id="4266054596873078491">Inicia sesión en este sitio y en Chrome con tu cuenta de Google.</translation>
 <translation id="4269820728363426813">Copiar la dirección del enlace</translation>
 <translation id="4290281343757112331">¿Prefieres descargar el archivo más tarde?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Activa el bloqueo de pantalla en los ajustes de Android<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">Tu navegador no está administrado</translation>
 <translation id="5339031667684712858">Sitios que has eliminado</translation>
 <translation id="5342314432463739672">Solicitudes de permiso</translation>
+<translation id="53537532693258630">Los sitios que hayas quitado aparecerán aquí</translation>
 <translation id="5355191726083956201">La protección mejorada está activada</translation>
 <translation id="5368227114232678694">Para navegar de forma privada en este dispositivo, prueba incógnito</translation>
 <translation id="5375577065097716013">Buscar imagen con Lens <ph name="BEGIN_NEW" />Nuevo<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Abre una nueva pestaña en modo Incógnito</translation>
 <translation id="8996847606757455498">Elegir otro proveedor</translation>
 <translation id="8998729206196772491">Estás iniciando sesión con una cuenta gestionada por <ph name="MANAGED_DOMAIN" />, lo que significa que vas a proporcionar a su administrador el control sobre tus datos de Chrome. Los datos se vincularán de forma permanente a esta cuenta. Si cierras sesión en Chrome, se eliminarán los datos de este dispositivo, pero permanecerán almacenados en tu cuenta de Google.</translation>
+<translation id="9021388532480169802">Sitio añadido</translation>
 <translation id="9022774213089566801">Visitados con frecuencia</translation>
 <translation id="9028914725102941583">Activar la sincronización para compartir con otros dispositivos</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# vídeo}other{# vídeos}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr-CA.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr-CA.xtb
index e9cca4d..5bc8ab44 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr-CA.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr-CA.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">Cet appareil ne prend pas en charge la recherche vocale</translation>
 <translation id="3749259744154402564">Non compatible</translation>
 <translation id="3771033907050503522">Onglets nav. priv.</translation>
+<translation id="377124182565324804">Ajouter <ph name="SITE" /></translation>
 <translation id="3771290962915251154">Ce paramètre est désactivé parce que les contrôles parentaux sont activés</translation>
 <translation id="3771694256347217732">Conditions d'utilisation de Google</translation>
 <translation id="3773856050682458546">Des données de base et de l'information sur les sites Web que vous visitez et les applications que vous utilisez</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Licences de logiciels libres</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Quelles données sont utilisées :<ph name="END_BOLD" /> votre historique de navigation et un enregistrement des sites que vous avez visités à l'aide de Chrome sur cet appareil.</translation>
 <translation id="4263656433980196874">Fenêtre d'IU de consentement pour la recherche vocale avec l'Assistant, ouverte à pleine hauteur</translation>
+<translation id="4266054596873078491">Connectez-vous à ce site et à Chrome avec votre compte Google.</translation>
 <translation id="4269820728363426813">Copier l'adresse du lien</translation>
 <translation id="4290281343757112331">Télécharger plus tard?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Activez le verrouillage d'écran dans les paramètres Android<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">Votre navigateur n'est pas géré</translation>
 <translation id="5339031667684712858">Sites que vous avez retirés</translation>
 <translation id="5342314432463739672">Demandes d'autorisation</translation>
+<translation id="53537532693258630">Les sites que vous avez retirés seront affichés ici</translation>
 <translation id="5355191726083956201">La protection renforcée est activée</translation>
 <translation id="5368227114232678694">Pour naviguer en privé sur cet appareil, essayez la navigation privée</translation>
 <translation id="5375577065097716013">Rechercher l'image avec Lentille Google <ph name="BEGIN_NEW" />Nouv.<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Ouvrir un nouvel onglet en mode de nav. privée</translation>
 <translation id="8996847606757455498">Choisir un autre fournisseur</translation>
 <translation id="8998729206196772491">Vous vous connectez avec un compte géré par <ph name="MANAGED_DOMAIN" />, et son administrateur pourra contrôler vos données Google Chrome. Celles-ci seront définitivement liées à votre compte. En vous déconnectant de Chrome, vous supprimerez vos données sur cet appareil, mais celles-ci resteront stockées dans votre compte Google.</translation>
+<translation id="9021388532480169802">Site ajouté</translation>
 <translation id="9022774213089566801">Fréquemment consultés</translation>
 <translation id="9028914725102941583">Activez la synchronisation pour partager des éléments entre des appareils</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# vidéo}one{# vidéo}other{# vidéos}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
index 14416db..7857e56 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">La recherche vocale n'est pas disponible sur cet appareil</translation>
 <translation id="3749259744154402564">Impossible d'effectuer cette action</translation>
 <translation id="3771033907050503522">Ongl. navig. priv.</translation>
+<translation id="377124182565324804">Ajouter <ph name="SITE" /></translation>
 <translation id="3771290962915251154">Ce paramètre est désactivé en raison de l'activation du contrôle parental</translation>
 <translation id="3771694256347217732">Conditions d'utilisation de Google</translation>
 <translation id="3773856050682458546">Données de base, ainsi que des informations sur les sites Web que vous consultez et les applications que vous utilisez</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Licences Open Source</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Quelles sont les données utilisées<ph name="END_BOLD" /> : votre historique de navigation, qui liste tous les sites que vous avez consultés dans Chrome sur cet appareil.</translation>
 <translation id="4263656433980196874">Interface d'autorisation pour la recherche vocale de l'Assistant ouverte à pleine hauteur</translation>
+<translation id="4266054596873078491">Connectez-vous à ce site et à Chrome avec votre compte Google.</translation>
 <translation id="4269820728363426813">Copier l'adresse du lien</translation>
 <translation id="4290281343757112331">Télécharger plus tard ?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Activez le verrouillage de l'écran dans les paramètres Android<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">Votre navigateur n'est pas géré</translation>
 <translation id="5339031667684712858">Sites que vous avez supprimés</translation>
 <translation id="5342314432463739672">Demandes d'autorisation</translation>
+<translation id="53537532693258630">Les sites que vous supprimez s'afficheront ici</translation>
 <translation id="5355191726083956201">La protection renforcée est activée</translation>
 <translation id="5368227114232678694">Pour naviguer en privé sur cet appareil, essayez la navigation privée</translation>
 <translation id="5375577065097716013">Rechercher image avec Google Lens <ph name="BEGIN_NEW" />Nouvelle<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Ouvrir un nouvel onglet en mode navigation privée</translation>
 <translation id="8996847606757455498">Sélectionner un autre fournisseur</translation>
 <translation id="8998729206196772491">Vous vous connectez avec un compte géré par <ph name="MANAGED_DOMAIN" />, ce qui permettra à son administrateur de contrôler vos données Chrome. Celles-ci seront définitivement associées à ce compte. Si vous vous déconnectez de Chrome, vos données seront supprimées de cet appareil, mais elles seront conservées dans votre compte Google.</translation>
+<translation id="9021388532480169802">Site ajouté</translation>
 <translation id="9022774213089566801">Consultés régulièrement</translation>
 <translation id="9028914725102941583">Activer la synchronisation pour partager des contenus entre des appareils</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# vidéo}one{# vidéo}other{# vidéos}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gl.xtb
index 4aad7ba..c6c002d 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gl.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gl.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">A busca por voz non está dispoñible neste dispositivo</translation>
 <translation id="3749259744154402564">Acción non admitida</translation>
 <translation id="3771033907050503522">Pestanas de incógnito</translation>
+<translation id="377124182565324804">Engadir <ph name="SITE" /></translation>
 <translation id="3771290962915251154">Esta opción de configuración está desactivada porque os controis parentais están activados</translation>
 <translation id="3771694256347217732">Condicións de servizo de Google</translation>
 <translation id="3773856050682458546">Datos básicos, así como información sobre os sitios web que visitas e as aplicacións que utilizas</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Licenzas de código aberto</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Que datos se usan?<ph name="END_BOLD" /> O teu historial de navegación e un rexistro dos sitios que visitases usando Chrome neste dispositivo.</translation>
 <translation id="4263656433980196874">A interface de consentimento para a busca por voz a través do Asistente está aberta a pantalla completa</translation>
+<translation id="4266054596873078491">Inicia sesión coa túa Conta de Google neste sitio e en Chrome.</translation>
 <translation id="4269820728363426813">Copiar enderezo da ligazón</translation>
 <translation id="4290281343757112331">Prefires realizar a descarga máis tarde?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Activa o bloqueo de pantalla na configuración de Android<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">O teu navegador non está xestionado</translation>
 <translation id="5339031667684712858">Sitios que quitaches</translation>
 <translation id="5342314432463739672">Solicitudes de permisos</translation>
+<translation id="53537532693258630">Os sitios que quites aparecerán aquí</translation>
 <translation id="5355191726083956201">A protección mellorada está activada</translation>
 <translation id="5368227114232678694">Se queres navegar de forma privada neste dispositivo, proba o modo de incógnito</translation>
 <translation id="5375577065097716013">Buscar imaxe con Google Lens <ph name="BEGIN_NEW" />Novo<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Abrir unha nova pestana no modo de incógnito</translation>
 <translation id="8996847606757455498">Escoller outro provedor</translation>
 <translation id="8998729206196772491">Estás iniciando sesión cunha conta xestionada por <ph name="MANAGED_DOMAIN" /> e proporcionándolle ao seu administrador o control dos teus datos de Chrome, que quedarán ligados permanentemente a esta conta. Se pechas sesión en Chrome, eliminaranse os teus datos deste dispositivo, pero seguirán almacenados na túa conta de Google.</translation>
+<translation id="9021388532480169802">Engadiuse un sitio</translation>
 <translation id="9022774213089566801">Visitas frecuentes</translation>
 <translation id="9028914725102941583">Activa a sincronización para compartir contido entre varios dispositivos</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# vídeo}other{# vídeos}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hy.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hy.xtb
index d070b8c..ab71ba82 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hy.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hy.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">Ձայնային որոնումը հասանելի չէ այս սարքում</translation>
 <translation id="3749259744154402564">Չի աջակցվում</translation>
 <translation id="3771033907050503522">Ինկոգնիտո ներդիրներ</translation>
+<translation id="377124182565324804">Ավելացնել <ph name="SITE" /> կայքը</translation>
 <translation id="3771290962915251154">Այս կարգավորումն անջատված է, քանի որ ակտիվ է ծնողական վերահսկողությունը</translation>
 <translation id="3771694256347217732">Google-ի օգտագործման պայմաններ</translation>
 <translation id="3773856050682458546">Հիմնական տվյալներ, ինչպես նաև տեղեկություններ ձեր այցելած կայքերի և օգտագործած հավելվածների մասին</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Բաց կոդով ծրագրերի լիցենզիաներ</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Ինչ տվյալներ են օգտագործվում.<ph name="END_BOLD" /> ձեր այցելությունների պատմությունը այն կայքերի ցանկն է, որոնք դուք այցելել եք Chrome-ի միջոցով այս սարքում։</translation>
 <translation id="4263656433980196874">Օգնականի միջոցով ձայնային որոնման միջերեսը բացվում է ամբողջ բարձրությամբ</translation>
+<translation id="4266054596873078491">Մուտք գործեք այս կայքում և Chrome-ում ձեր Google հաշվով։</translation>
 <translation id="4269820728363426813">Պատճենել հղման հասցեն</translation>
 <translation id="4290281343757112331">Ներբեռնե՞լ ավելի ուշ</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Միացնել էկրանի կողպումը Android-ի կարգավորումներում<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">Ձեր դիտարկիչը չի կառավարվում</translation>
 <translation id="5339031667684712858">Կայքերը, որոնք հեռացրել եք</translation>
 <translation id="5342314432463739672">Թույլտվությունների հարցումներ</translation>
+<translation id="53537532693258630">Այստեղ կհայտնվեն ձեր հեռացրած կայքերը</translation>
 <translation id="5355191726083956201">Բարելավված պաշտպանությունը միացված է</translation>
 <translation id="5368227114232678694">Օգտագործեք ինկոգնիտո ռեժիմը, որպեսզի ձեր այցելությունների պատմությունը չպահվի</translation>
 <translation id="5375577065097716013">Որոնել Google Տեսապակու միջոցով <ph name="BEGIN_NEW" />Նոր<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Բացել նոր ներդիր ինկոգնիտո ռեժիմում</translation>
 <translation id="8996847606757455498">Ընտրել մեկ այլ մատակարար</translation>
 <translation id="8998729206196772491">Դուք մուտք եք գործում <ph name="MANAGED_DOMAIN" /> տիրույթի կողմից կառավարվող հաշիվ` դրա ադմինիստրատորին թույլ տալով վերահսկել ձեր Chrome-ի տվյալները: Ձեր տվյալները մշտապես կկապվեն այս հաշվի հետ: Եթե դուրս գաք Chrome-ից, այս սարքում պահված տվյալները կջնջվեն, սակայն կպահպանվեն ձեր Google հաշվում:</translation>
+<translation id="9021388532480169802">Կայքն ավելացվեց</translation>
 <translation id="9022774213089566801">Հաճախ այցելած</translation>
 <translation id="9028914725102941583">Միացրեք համաժամացումը՝ մի սարքի տվյալներով մյուսի հետ կիսվելու համար</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# տեսանյութ}one{# տեսանյութ}other{# տեսանյութ}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb
index b70e6f8..5e0bc37e 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">Бұл құрылғыда дауыспен іздеу мүмкін емес.</translation>
 <translation id="3749259744154402564">Қолдау көрсетілмейді</translation>
 <translation id="3771033907050503522">Инкогнито қойындылары</translation>
+<translation id="377124182565324804"><ph name="SITE" /> сайтын қосу</translation>
 <translation id="3771290962915251154">Ата-ана бақылауы қосылып тұрғандықтан, бұл параметр өшірілді.</translation>
 <translation id="3771694256347217732">Google Қызмет көрсету шарттары</translation>
 <translation id="3773856050682458546">Негізгі деректер, сонымен қатар кірген веб-сайттарыңыз бен пайдаланған қолданбаларыңыз</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Ашық кодты бағдарлама лицензиялары</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Қандай дерек пайдаланылады:<ph name="END_BOLD" /> браузерді қолдану тарихы, осы құрылғыда Chrome көмегімен кірген сайттардың жазбасы.</translation>
 <translation id="4263656433980196874">Assistant-ті дауыспен іздеуге пайдалану туралы келісім терезесі толық ашылған.</translation>
+<translation id="4266054596873078491">Осы сайтқа және Chrome браузеріне Google аккаунтыңызбен кіріңіз.</translation>
 <translation id="4269820728363426813">Сілтеме мекенжайын көшіру</translation>
 <translation id="4290281343757112331">Кейінірек жүктеп алынсын ба?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Android параметрлерінен экран құлпын қосыңыз.<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">Браузеріңіз басқарылмайды</translation>
 <translation id="5339031667684712858">Өшірілген сайттар</translation>
 <translation id="5342314432463739672">Рұқсат сұраулары</translation>
+<translation id="53537532693258630">Сіз өшірген сайттар осы жерде болады.</translation>
 <translation id="5355191726083956201">Жақсартылған қорғаныс қосулы.</translation>
 <translation id="5368227114232678694">Осы құрылғыда құпия шолу үшін инкогнито режимін қолданып көріңіз.</translation>
 <translation id="5375577065097716013">Суретті Google Lens арқылы іздеу <ph name="BEGIN_NEW" />Жаңа<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Жаңа қойындыны инкогнито режимінде ашу</translation>
 <translation id="8996847606757455498">Басқа провайдер таңдау</translation>
 <translation id="8998729206196772491"><ph name="MANAGED_DOMAIN" /> басқаратын аккаунтпен кірдіңіз және оның әкімшісіне Chrome дерегін басқару құқығы берілді. Дерек осы аккаунтпен байланыстырылады. Chrome жүйесінен шыққанда, дерек бұл құрылғыдан жойылғанымен, Google аккаунтында сақталады.</translation>
+<translation id="9021388532480169802">Сайт қосылды.</translation>
 <translation id="9022774213089566801">Жиі пайдаланатындар</translation>
 <translation id="9028914725102941583">Барлық құрылғылармен бөлісу үшін синхрондауды іске қосыңыз.</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# бейне}other{# бейне}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ky.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ky.xtb
index 35192e81..5252e8c 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ky.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ky.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">Бул түзмөктө айтып издөө мүмкүнчүлүгү жок</translation>
 <translation id="3749259744154402564">Колдоого алынбайт</translation>
 <translation id="3771033907050503522">Жашыруун өтмөктөр</translation>
+<translation id="377124182565324804"><ph name="SITE" /> кошуу</translation>
 <translation id="3771290962915251154">Бул жөндөө өчүрүлгөн, анткени Ата-эненин көзөмөлү күйүк</translation>
 <translation id="3771694256347217732">Google'дун Тейлөө шарттары</translation>
 <translation id="3773856050682458546">Сиз баш баккан вебсайттар менен пайдаланган колдонмолор тууралуу негизги маалымат</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Ачык программа уруксаттамалары</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Кайсы маалымат колдонулат:<ph name="END_BOLD" /> Бул түзмөктө Chrome аркылуу баш баккан жана көргөн сайттарыңыз.</translation>
 <translation id="4263656433980196874">Жардамчыга айтып издөөгө уруксат берүү интерфейси толук ачылды</translation>
+<translation id="4266054596873078491">Бул сайтка жана Chrome'го Google аккаунтуңуз менен кириңиз.</translation>
 <translation id="4269820728363426813">Шилтеме дарегин көчүрүү</translation>
 <translation id="4290281343757112331">Анын ордуна кийинчерээк жүктөлүп алынсынбы?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Android'дин жөндөөлөрүнөн экранды кулпулоону күйгүзүңүз<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">Серепчиңиз башкарылган жок</translation>
 <translation id="5339031667684712858">Өчүргөн сайттарыңыз</translation>
 <translation id="5342314432463739672">Уруксат сурамдары</translation>
+<translation id="53537532693258630">Сиз өчүргөн сайттар ушул жерден көрүнөт</translation>
 <translation id="5355191726083956201">Өркүндөтүлгөн коргоо күйүк</translation>
 <translation id="5368227114232678694">Бул түзмөктө купуя карап чыгуу үчүн Жашыруун режимди колдонуңуз</translation>
 <translation id="5375577065097716013">Google Lens аркылуу издөө <ph name="BEGIN_NEW" />Жаңы<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Жаңы өтмөктү жашыруун режимде ачуу</translation>
 <translation id="8996847606757455498">Башка провайдерди тандоо</translation>
 <translation id="8998729206196772491">Сиз <ph name="MANAGED_DOMAIN" /> доменинин администратору тарабынан башкарылган аккаунтка кирип жатасыз. Ал мындан тарта сиздин аккаунтуңузга байланган Chrome дайын-даректериңизды башкарып калат. Chrome аккаунткан чыксаңыз, бул түзмөктөн дайын-даректериңиз жок кылынып, бирок Google Каттоо эсебинде сакталып кала берет.</translation>
+<translation id="9021388532480169802">Сайт кошулду</translation>
 <translation id="9022774213089566801">Көп каралгандар</translation>
 <translation id="9028914725102941583">Бардык түзмөктөр менен бөлүшүү үчүн шайкештирүүнү күйгүзүңүз</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# видео}other{# видео}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb
index 0179d6b5..b0f4efc 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">ບໍ່ສາມາດໃຊ້ການຊອກຫາດ້ວຍສຽງຢູ່ອຸປະກອນນີ້ໄດ້</translation>
 <translation id="3749259744154402564">ບໍ່ຮອງຮັບ</translation>
 <translation id="3771033907050503522">ແຖບບໍ່ເຜີຍຕົນຕົວ</translation>
+<translation id="377124182565324804">ເພີ່ມ <ph name="SITE" /></translation>
 <translation id="3771290962915251154">ການຕັ້ງຄ່ານີ້ຖືກປິດການນຳໃຊ້ເນື່ອງຈາກວ່າການຄວບຄຸມຂອງພໍ່ແມ່ເປີດຢູ່</translation>
 <translation id="3771694256347217732">ຂໍ້ກຳນົດການບໍລິການຂອງ Google</translation>
 <translation id="3773856050682458546">ຂໍ້ມູນພື້ນຖານພ້ອມກັບຂໍ້ມູນກ່ຽວກັບເວັບໄຊທີ່ທ່ານເຂົ້າເບິ່ງ ແລະ ແອັບທີ່ທ່ານໃຊ້</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">ໃບ​ອະ​ນຸ​ຍາດ Open source</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />ມີການໃຊ້ຂໍ້ມູນໃດ:<ph name="END_BOLD" /> ປະຫວັດການທ່ອງເວັບຂອງທ່ານ, ບັນທຶກຂອງເວັບໄຊທີ່ທ່ານເຂົ້າເບິ່ງໂດຍໃຊ້ Chrome ຢູ່ອຸປະກອນນີ້.</translation>
 <translation id="4263656433980196874">ສ່ວນຕິດຕໍ່ຜູ້ໃຊ້ສຳລັບຄຳຍິນຍອມການຊອກຫາດ້ວຍສຽງຂອງຜູ້ຊ່ວຍທີ່ເປີດຢູ່ທີ່ຄວາມສູງເຕັມຈໍ</translation>
+<translation id="4266054596873078491">ເຂົ້າສູ່ລະບົບເວັບໄຊນີ້ ແລະ Chrome ດ້ວຍບັນຊີ Google ຂອງທ່ານ.</translation>
 <translation id="4269820728363426813">ກັອບປີ້ທີ່ຢູ່ລິ້ງ</translation>
 <translation id="4290281343757112331">ດາວໂຫຼດໃນພາຍຫຼັງແທນບໍ?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />ເປີດໃຊ້ການລັອກໜ້າຈໍໃນການຕັ້ງຄ່າ Android<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">ບໍ່ຮອງຮັບໂປຣແກຣມທ່ອງເວັບຂອງທ່ານ</translation>
 <translation id="5339031667684712858">ເວັບໄຊທີ່ທ່ານລຶບອອກແລ້ວ</translation>
 <translation id="5342314432463739672">ຄຳຂໍການອະນຸຍາດ</translation>
+<translation id="53537532693258630">ເວັບໄຊທີ່ທ່ານລຶບອອກຈະປາກົດຢູ່ບ່ອນນີ້</translation>
 <translation id="5355191726083956201">ການປົກປ້ອງທີ່ປັບປຸງດີຂຶ້ນເປີດຢູ່</translation>
 <translation id="5368227114232678694">ເພື່ອທ່ອງເວັບແບບສ່ວນຕົວຢູ່ອຸປະກອນນີ້, ໃຫ້ລອງໃຊ້ໂໝດບໍ່ເປີດເຜີຍຕົວຕົນ</translation>
 <translation id="5375577065097716013">ຊອກຫາຮູບພາບດ້ວຍ Google Lens <ph name="BEGIN_NEW" />ໃໝ່<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">ເປີດແຖບໃໝ່ໃນໂໝດ Incognito</translation>
 <translation id="8996847606757455498">ເລືອກຜູ້ໃຫ້ບໍລິການອື່ນ</translation>
 <translation id="8998729206196772491">ທ່ານກຳລັງເຂົ້າສູ່ລະບົບດ້ວຍບັນຊີທີ່ຖືກຈັດການໂດຍ <ph name="MANAGED_DOMAIN" /> ແລະ ໃຫ້ການຄວບຄຸມຂໍ້ມູນ Chrome ຂອງທ່ານແກ່ຜູ້ເບິ່ງແຍງລະບົບຂອງມັນ. ຂໍ້ມູນຂອງທ່ານຈະຖືກເຊື່ອມໂຍງຢ່າງຖາວອນກັບບັນຊີນີ້. ການອອກຈາກລະບົບ Chrome ຈະລຶບຂໍ້ມູນຂອງທ່ານອອກຈາກອຸປະກອນນີ້, ແຕ່ຂໍ້ມູນຈະຍັງຄົງຖືກຮັກສາໄວ້ຢູ່ໃນບັນຊີ Google ຂອງທ່ານ.</translation>
+<translation id="9021388532480169802">ເພີ່ມເວັບໄຊແລ້ວ</translation>
 <translation id="9022774213089566801">ເຂົ້າເບິ່ງເລື້ອຍໆ</translation>
 <translation id="9028914725102941583">ເປີດການຊິ້ງຂໍ້ມູນເພື່ອແບ່ງປັນໃນທົ່ວອຸປະກອນ</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# ວິດີໂອ}other{# ວິດີໂອ}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ms.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ms.xtb
index 118f133..02646ab 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ms.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ms.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">Carian suara tidak tersedia pada peranti ini</translation>
 <translation id="3749259744154402564">Tidak disokong</translation>
 <translation id="3771033907050503522">Tab Inkognito</translation>
+<translation id="377124182565324804">Tambah <ph name="SITE" /></translation>
 <translation id="3771290962915251154">Tetapan ini dilumpuhkan kerana kawalan ibu bapa dihidupkan</translation>
 <translation id="3771694256347217732">Syarat Perkhidmatan Google</translation>
 <translation id="3773856050682458546">Data asas ditambah maklumat tentang laman web yang anda lawati dan apl yang anda gunakan</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Lesen sumber terbuka</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Jenis data yang digunakan:<ph name="END_BOLD" /> Sejarah penyemakan imbas anda, rekod laman yang anda lawati menggunakan Chrome pada peranti ini.</translation>
 <translation id="4263656433980196874">UI persetujuan carian suara Assistant dibuka pada ketinggian penuh</translation>
+<translation id="4266054596873078491">Log masuk ke laman ini dan Chrome menggunakan Akaun Google anda.</translation>
 <translation id="4269820728363426813">Salin alamat pautan</translation>
 <translation id="4290281343757112331">Muat turun kemudian?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Hidupkan kunci skrin dalam tetapan Android<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">Penyemak imbas anda tidak diurus</translation>
 <translation id="5339031667684712858">Laman yang dialih keluar</translation>
 <translation id="5342314432463739672">Permintaan kebenaran</translation>
+<translation id="53537532693258630">Laman yang dialih keluar akan dipaparkan di sini</translation>
 <translation id="5355191726083956201">Perlindungan Dipertingkat dihidupkan</translation>
 <translation id="5368227114232678694">Untuk menyemak imbas secara peribadi pada peranti ini, cubalah Inkognito</translation>
 <translation id="5375577065097716013">Cari imej dengan Lens <ph name="BEGIN_NEW" />Baharu<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Buka tetingkap baharu dalam mod Inkognito</translation>
 <translation id="8996847606757455498">Pilih penyedia lain</translation>
 <translation id="8998729206196772491">Anda log masuk dengan akaun yang diurus oleh <ph name="MANAGED_DOMAIN" /> dan memberikan kawalan terhadap data Chrome anda kepada pentadbirnya. Data anda akan terikat secara kekal kepada akaun ini. Tindakan log keluar daripada Chrome akan memadamkan data anda daripada peranti ini, tetapi data itu akan kekal disimpan dalam Akaun Google anda.</translation>
+<translation id="9021388532480169802">Laman telah ditambahkan</translation>
 <translation id="9022774213089566801">Kerap dilawat</translation>
 <translation id="9028914725102941583">Hidupkan penyegerakan untuk berkongsi merentas peranti</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# Video}other{# Video}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ru.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ru.xtb
index 7877b3b..23848762 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ru.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ru.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">Голосовой поиск недоступен на этом устройстве.</translation>
 <translation id="3749259744154402564">Действие не поддерживается.</translation>
 <translation id="3771033907050503522">Вкладки инкогнито</translation>
+<translation id="377124182565324804">Добавить <ph name="SITE" /></translation>
 <translation id="3771290962915251154">Эта настройка отключена, так как работает родительский контроль</translation>
 <translation id="3771694256347217732">Условия использования Google</translation>
 <translation id="3773856050682458546">Основные данные, а также информация о посещаемых сайтах и используемых приложениях</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Лицензии на ПО с открытым кодом</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Какие данные используются.<ph name="END_BOLD" /> История вашего браузера – список сайтов, которые вы открывали в браузере Chrome на этом устройстве.</translation>
 <translation id="4263656433980196874">Окно, где требуется разрешить использование Ассистента для голосового поиска, открыто на весь экран</translation>
+<translation id="4266054596873078491">Войдите на этот сайт и в Chrome со своим аккаунтом Google.</translation>
 <translation id="4269820728363426813">Копировать адрес ссылки</translation>
 <translation id="4290281343757112331">Скачать позже?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Включить блокировку экрана в настройках Android<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">Этот браузер не управляется администратором</translation>
 <translation id="5339031667684712858">Сайты, которые вы удалили</translation>
 <translation id="5342314432463739672">Запросы разрешений</translation>
+<translation id="53537532693258630">Сайты, которые вы удалили, появятся здесь.</translation>
 <translation id="5355191726083956201">Улучшенная защита включена.</translation>
 <translation id="5368227114232678694">Чтобы анонимно работать в интернете на этом устройстве, воспользуйтесь режимом инкогнито.</translation>
 <translation id="5375577065097716013">Найти через Google Объектив <ph name="BEGIN_NEW" />Новинка<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Открыть новое окно в режиме инкогнито</translation>
 <translation id="8996847606757455498">Выбрать другого поставщика</translation>
 <translation id="8998729206196772491">Вы входите в аккаунт, которым управляет администратор домена <ph name="MANAGED_DOMAIN" />. Он может контролировать ваши данные Chrome, которые теперь будут связаны с управляемым аккаунтом. При выходе из системы все данные Chrome, хранящиеся на этом устройстве, будут удалены, но останутся в вашем аккаунте Google.</translation>
+<translation id="9021388532480169802">Сайт добавлен.</translation>
 <translation id="9022774213089566801">Часто посещаемые</translation>
 <translation id="9028914725102941583">Включите синхронизацию</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# видеофайл}one{# видеофайл}few{# видеофайла}many{# видеофайлов}other{# видеофайла}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sq.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sq.xtb
index ad8a0bc..ff5648f 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sq.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sq.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">Kërkimi zanor nuk mund të përdoret në këtë pajisje</translation>
 <translation id="3749259744154402564">Nuk mbështetet</translation>
 <translation id="3771033907050503522">Skedat "e fshehura"</translation>
+<translation id="377124182565324804">Shto <ph name="SITE" /></translation>
 <translation id="3771290962915251154">Ky cilësim është i çaktivizuar sepse kontrollet prindërore janë të aktivizuara</translation>
 <translation id="3771694256347217732">Kushtet e shërbimit të Google</translation>
 <translation id="3773856050682458546">Të dhëna bazë plus informacione rreth faqeve të internetit që viziton dhe aplikacioneve që përdor</translation>
@@ -590,6 +591,7 @@
 <translation id="4256782883801055595">Licencat me burim të hapur</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Çfarë të dhënash përdoren:<ph name="END_BOLD" /> Historiku yt i shfletimit, regjistri i sajteve që ke vizituar duke përdorur Chrome në këtë pajisje.</translation>
 <translation id="4263656433980196874">Ndërfaqja e përdoruesit e miratimit të kërkimit zanor të "Asistentit" e hapur në lartësi të plotë</translation>
+<translation id="4266054596873078491">Identifikohu në këtë sajt dhe në Chrome me "Llogarinë tënde të Google".</translation>
 <translation id="4269820728363426813">Kopjo adresën e lidhjes</translation>
 <translation id="4290281343757112331">Të shkarkohet më vonë më mirë?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Aktivizo kyçjen e ekranit te cilësimet e Android<ph name="END_LINK" /></translation>
@@ -790,6 +792,7 @@
 <translation id="5329858041417644019">Shfletuesi yt nuk është i menaxhuar</translation>
 <translation id="5339031667684712858">Sajtet që hoqe</translation>
 <translation id="5342314432463739672">Kërkesat për autorizim</translation>
+<translation id="53537532693258630">Sajtet që ke hequr do të shfaqen këtu</translation>
 <translation id="5355191726083956201">"Mbrojtja e përmirësuar" është aktive</translation>
 <translation id="5368227114232678694">Provo modalitetin "E fshehtë" për të shfletuar në mënyrë private në këtë pajisje</translation>
 <translation id="5375577065097716013">Kërko imazh me "Lenten e Google" <ph name="BEGIN_NEW" />E re<ph name="END_NEW" /></translation>
@@ -1496,6 +1499,7 @@
 <translation id="8993760627012879038">Hap një skedë të re në "Modalitetin e fshehtë"</translation>
 <translation id="8996847606757455498">Zgjidh një ofrues tjetër</translation>
 <translation id="8998729206196772491">Po identifikohesh me një llogari të menaxhuar nga <ph name="MANAGED_DOMAIN" /> dhe po i jep administratorit të saj kontroll mbi të dhënat e tua të Chrome. Duke dalë nga Chrome do të fshihen të dhënat e tua nga kjo pajisje, por do të mbeten të ruajtura në llogarinë tënde të Google.</translation>
+<translation id="9021388532480169802">Sajti u shtua</translation>
 <translation id="9022774213089566801">Të vizituara shpesh</translation>
 <translation id="9028914725102941583">Aktivizo sinkronizimin për të ndarë mes pajisjeve</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# video}other{# video}}</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb
index c15af803..9ea5b80 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb
@@ -508,6 +508,7 @@
 <translation id="3740525748616366977">Röstsökning är inte tillgängligt på enheten</translation>
 <translation id="3749259744154402564">Stöds inte</translation>
 <translation id="3771033907050503522">Inkognitoflikar</translation>
+<translation id="377124182565324804">Lägg till <ph name="SITE" /></translation>
 <translation id="3771290962915251154">Inställningen är inaktiverad eftersom föräldrakontroller används</translation>
 <translation id="3771694256347217732">Googles användarvillkor</translation>
 <translation id="3773856050682458546">Grundläggande data samt information om webbplatser du besöker och appar du använder</translation>
@@ -591,6 +592,7 @@
 <translation id="4256782883801055595">Licenser för öppen källkod</translation>
 <translation id="4262915912852657291"><ph name="BEGIN_BOLD" />Vilken data används:<ph name="END_BOLD" /> Webbhistoriken, där webbplatser som du besökt i Chrome på den här enheten registreras.</translation>
 <translation id="4263656433980196874">Användargränssnittet för samtycke till röstsökning med assistenten har öppnats över hela skärmen</translation>
+<translation id="4266054596873078491">Logga in på den här webbplatsen och i Chrome med ditt Google-konto.</translation>
 <translation id="4269820728363426813">Kopiera länkadress</translation>
 <translation id="4290281343757112331">Vill du ladda ned senare i stället?</translation>
 <translation id="4291407919474070700"><ph name="BEGIN_LINK" />Aktivera skärmlåset i Android-inställningar<ph name="END_LINK" /></translation>
@@ -791,6 +793,7 @@
 <translation id="5329858041417644019">Din webbläsare är inte hanterad</translation>
 <translation id="5339031667684712858">Webbplatser du har tagit bort</translation>
 <translation id="5342314432463739672">Behörighetsförfrågningar</translation>
+<translation id="53537532693258630">Webbplatser som du har tagit bort visas här</translation>
 <translation id="5355191726083956201">Förbättrat skydd är aktiverat</translation>
 <translation id="5368227114232678694">Testa inkognitoläget om du vill surfa privat på enheten</translation>
 <translation id="5375577065097716013">Bildsökning med Google Lens <ph name="BEGIN_NEW" />Ny<ph name="END_NEW" /></translation>
@@ -1497,6 +1500,7 @@
 <translation id="8993760627012879038">Öppna en ny flik i inkognitoläge</translation>
 <translation id="8996847606757455498">Välj en annan leverantör</translation>
 <translation id="8998729206196772491">Du håller på att logga in med ett konto som hanteras av <ph name="MANAGED_DOMAIN" />, vilket ger administratören kontroll över data i Chrome. Din data kopplas permanent till det här kontot. Om du loggar ut från Chrome raderas all din data från enheten, men den lagras fortfarande i Google-kontot.</translation>
+<translation id="9021388532480169802">Webbplatsen har lagts till</translation>
 <translation id="9022774213089566801">Mest besökta</translation>
 <translation id="9028914725102941583">Aktivera synkronisering om du vill dela mellan enheter</translation>
 <translation id="9041669420854607037">{FILE_COUNT,plural, =1{# video}other{# videor}}</translation>
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index c726c4e..458af71 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -2819,13 +2819,7 @@
 
 void Browser::UpdateWindowForLoadingStateChanged(content::WebContents* source,
                                                  bool should_show_loading_ui) {
-  if (base::FeatureList::IsEnabled(features::kStopRenderingLoadingAnimation)) {
-    auto* browser_view = source->GetPrimaryMainFrame()->GetView();
-    window_->UpdateLoadingAnimations(browser_view->IsShowing() &&
-                                     tab_strip_model_->TabsAreLoading());
-  } else {
-    window_->UpdateLoadingAnimations(tab_strip_model_->TabsAreLoading());
-  }
+  window_->UpdateLoadingAnimations(tab_strip_model_->TabsAreLoading());
   window_->UpdateTitleBar();
 
   WebContents* selected_contents = tab_strip_model_->GetActiveWebContents();
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc
index 5eedc39..359620d 100644
--- a/chrome/browser/ui/ui_features.cc
+++ b/chrome/browser/ui/ui_features.cc
@@ -308,8 +308,4 @@
 
 #endif
 
-// Reduce resource usage when view is hidden by not rendering loading animation.
-const base::Feature kStopRenderingLoadingAnimation{
-    "StopRenderingLoadingAnimation", base::FEATURE_DISABLED_BY_DEFAULT};
-
 }  // namespace features
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h
index aca8959..2a177528 100644
--- a/chrome/browser/ui/ui_features.h
+++ b/chrome/browser/ui/ui_features.h
@@ -208,8 +208,6 @@
 extern const base::Feature kWin10TabSearchCaptionButton;
 #endif
 
-extern const base::Feature kStopRenderingLoadingAnimation;
-
 }  // namespace features
 
 #endif  // CHROME_BROWSER_UI_UI_FEATURES_H_
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
index 61539f7..c45ee7ce 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
@@ -112,17 +112,6 @@
 
   // If either of mode or state changes, we might need to change UI.
   ui_info_ = model_->GetBubbleUIInfo();
-
-  // This should only be logged once per download, so only for change in modes
-  // to warning.
-  if (!mode_unchanged && is_download_warning(mode)) {
-    const auto danger_type = model_->GetDangerType();
-    const auto file_path = model_->GetTargetFilePath();
-    bool is_https = model_->GetURL().SchemeIs(url::kHttpsScheme);
-    bool has_user_gesture = model_->HasUserGesture();
-    RecordDangerousDownloadWarningShown(danger_type, file_path, is_https,
-                                        has_user_gesture);
-  }
 }
 
 void DownloadBubbleRowView::AddedToWidget() {
@@ -476,6 +465,14 @@
 }
 
 void DownloadBubbleRowView::OnDownloadUpdated() {
+  // This should only be logged once per download.
+  if (is_download_warning(download::GetDesiredDownloadItemMode(model_.get())) &&
+      !model_->WasUIWarningShown()) {
+    model_->SetWasUIWarningShown(true);
+    RecordDangerousDownloadWarningShown(
+        model_->GetDangerType(), model_->GetTargetFilePath(),
+        model_->GetURL().SchemeIs(url::kHttpsScheme), model_->HasUserGesture());
+  }
   UpdateBubbleUIInfo();
   UpdateLabels();
   LoadIcon();
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 5acc434..bb25f03 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1421,10 +1421,6 @@
   }
 }
 
-bool BrowserView::IsLoadingAnimationRunningForTesting() const {
-  return loading_animation_timer_.IsRunning();
-}
-
 void BrowserView::SetStarredState(bool is_starred) {
   PageActionIconView* star_icon =
       toolbar_button_provider_->GetPageActionIconView(
@@ -2199,16 +2195,6 @@
   browser()->extension_window_controller()->NotifyWindowBoundsChanged();
 }
 
-void BrowserView::OnWidgetVisibilityChanged(views::Widget* widget,
-                                            bool visible) {
-  if (!base::FeatureList::IsEnabled(features::kStopRenderingLoadingAnimation)) {
-    return;
-  }
-
-  UpdateLoadingAnimations(visible &&
-                          browser_->tab_strip_model()->TabsAreLoading());
-}
-
 void BrowserView::TouchModeChanged() {
   MaybeInitializeWebUITabStrip();
   MaybeShowWebUITabStripIPH();
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 3595906..f4b503d 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -148,8 +148,6 @@
   // (and hide immediately).
   static void SetDisableRevealerDelayForTesting(bool disable);
 
-  bool IsLoadingAnimationRunningForTesting() const;
-
   // Returns a Browser instance of this view.
   Browser* browser() { return browser_.get(); }
   const Browser* browser() const { return browser_.get(); }
@@ -629,7 +627,6 @@
   void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
   void OnWidgetBoundsChanged(views::Widget* widget,
                              const gfx::Rect& new_bounds) override;
-  void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override;
 
   // views::ClientView:
   views::CloseRequestResult OnWindowCloseRequested() override;
diff --git a/chrome/browser/ui/views/frame/browser_view_unittest.cc b/chrome/browser/ui/views/frame/browser_view_unittest.cc
index d8c8d17..7ea6fc93 100644
--- a/chrome/browser/ui/views/frame/browser_view_unittest.cc
+++ b/chrome/browser/ui/views/frame/browser_view_unittest.cc
@@ -9,10 +9,8 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/layout_constants.h"
-#include "chrome/browser/ui/tabs/tab_activity_simulator.h"
 #include "chrome/browser/ui/tabs/tab_enums.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
 #include "chrome/browser/ui/views/frame/browser_view_layout.h"
 #include "chrome/browser/ui/views/frame/tab_strip_region_view.h"
@@ -26,8 +24,6 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "components/version_info/channel.h"
-#include "content/public/test/navigation_simulator.h"
-#include "content/public/test/web_contents_tester.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/scrollbar_size.h"
@@ -39,26 +35,6 @@
 
 namespace {
 
-// Class for BrowserView unit tests for the loading animation feature.
-// Creates a Browser with a |features_list| where kStopRenderingLoadingAnimation
-// is enabled before setting GPU thread.
-class BrowserViewTestWithStopRenderingLoadingAnimation
-    : public TestWithBrowserView {
- public:
-  BrowserViewTestWithStopRenderingLoadingAnimation() {
-    feature_list_.InitAndEnableFeature(
-        features::kStopRenderingLoadingAnimation);
-  }
-
-  BrowserViewTestWithStopRenderingLoadingAnimation(
-      const BrowserViewTestWithStopRenderingLoadingAnimation&) = delete;
-  BrowserViewTestWithStopRenderingLoadingAnimation& operator=(
-      const BrowserViewTestWithStopRenderingLoadingAnimation&) = delete;
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
 // Tab strip bounds depend on the window frame sizes.
 gfx::Point ExpectedTabStripRegionOrigin(BrowserView* browser_view) {
   gfx::Rect tabstrip_bounds(browser_view->frame()->GetBoundsForTabStripRegion(
@@ -469,51 +445,3 @@
   EXPECT_NE(nullptr, browser()->window());
   EXPECT_EQ(nullptr, BrowserView::GetBrowserViewForBrowser(browser()));
 }
-
-// Tests Feature to ensure that the loading animation is not rendered after the
-// window changes to hidden.
-TEST_F(BrowserViewTestWithStopRenderingLoadingAnimation,
-       LoadingAnimationNotRenderedWhenWindowHidden) {
-  TabActivitySimulator tab_activity_simulator;
-  content::WebContents* web_contents =
-      tab_activity_simulator.AddWebContentsAndNavigate(
-          browser()->tab_strip_model(), GURL("about:blank"));
-
-  auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
-      GURL("about:blank"), web_contents);
-  navigation->SetKeepLoading(true);
-
-  browser_view()->GetWidget()->Show();
-
-  EXPECT_TRUE(browser()->tab_strip_model()->TabsAreLoading());
-  EXPECT_TRUE(browser_view()->IsLoadingAnimationRunningForTesting());
-
-  browser_view()->GetWidget()->Hide();
-
-  EXPECT_TRUE(browser()->tab_strip_model()->TabsAreLoading());
-  EXPECT_FALSE(browser_view()->IsLoadingAnimationRunningForTesting());
-}
-
-// Tests Feature to ensure that the loading animation is rendered after the
-// window changes from hidden to visible.
-TEST_F(BrowserViewTestWithStopRenderingLoadingAnimation,
-       LoadingAnimationRenderedWhenWindowVisible) {
-  TabActivitySimulator tab_activity_simulator;
-  content::WebContents* web_contents =
-      tab_activity_simulator.AddWebContentsAndNavigate(
-          browser()->tab_strip_model(), GURL("about:blank"));
-
-  auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
-      GURL("about:blank"), web_contents);
-  navigation->SetKeepLoading(true);
-
-  browser_view()->GetWidget()->Hide();
-
-  EXPECT_TRUE(browser()->tab_strip_model()->TabsAreLoading());
-  EXPECT_FALSE(browser_view()->IsLoadingAnimationRunningForTesting());
-
-  browser_view()->GetWidget()->Show();
-
-  EXPECT_TRUE(browser()->tab_strip_model()->TabsAreLoading());
-  EXPECT_TRUE(browser_view()->IsLoadingAnimationRunningForTesting());
-}
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 1ee5e73..f12e9228 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1655488705-a8d059e1c77d5391c62a9153e09caf1a9bb1b754.profdata
+chrome-linux-main-1655595102-6337048a43042b369bca63d5a3cd5be3fdd037f9.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 0dc6482..b066f3b 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1655488705-b4be757613e1b3e238b09a6f0d908398060bdf93.profdata
+chrome-mac-arm-main-1655553312-bd120514348dc38cec864f7ba3421ef78f9b636b.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 4dbf69cb..84672650 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1655488705-4acb856423b136f51305aa7cbee124a7d1f32422.profdata
+chrome-mac-main-1655595102-e7bc83bd1c464322cead9112ae440b787292cfc5.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 94edd47..c9f6588 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1655499543-52af2873e2fd92539c1b043b0a55c99b239fdfbf.profdata
+chrome-win32-main-1655607154-4a5d1f741bc5fea067f45b3fbe7a6bdbadc538c6.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index b4885eb..53ff0aee 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1655499543-61fefae39aa4d09ed380819c4114e0aa3dc658a5.profdata
+chrome-win64-main-1655607154-4506c33eb2f9703f2db9b464680177782a9419ab.profdata
diff --git a/chrome/updater/app/server/win/com_classes_legacy.cc b/chrome/updater/app/server/win/com_classes_legacy.cc
index 3f1b35ca..22a3a1b3 100644
--- a/chrome/updater/app/server/win/com_classes_legacy.cc
+++ b/chrome/updater/app/server/win/com_classes_legacy.cc
@@ -691,22 +691,7 @@
     substitutions.push_back(substitution_string.value());
   }
 
-  absl::optional<std::wstring> command_line = FormatCommandLine(substitutions);
-  if (!command_line)
-    return E_INVALIDARG;
-
-  STARTUPINFOW si = {sizeof(si)};
-  PROCESS_INFORMATION pi = {0};
-  if (!::CreateProcess(executable_.value().c_str(), &(*command_line)[0],
-                       nullptr, nullptr, FALSE, CREATE_NO_WINDOW, nullptr,
-                       nullptr, &si, &pi)) {
-    return HRESULTFromLastError();
-  }
-
-  ::CloseHandle(pi.hThread);
-
-  process_ = base::Process(pi.hProcess);
-  return process_.IsValid() ? S_OK : E_UNEXPECTED;
+  return ExecuteAppCommand(executable_, parameters_, substitutions, process_);
 }
 
 STDMETHODIMP LegacyAppCommandWebImpl::GetTypeInfoCount(UINT*) {
diff --git a/chrome/updater/win/win_util.cc b/chrome/updater/win/win_util.cc
index 8ad2fef..87a5106 100644
--- a/chrome/updater/win/win_util.cc
+++ b/chrome/updater/win/win_util.cc
@@ -927,6 +927,37 @@
              : CompareOSVersionsInternal(os_version, kOSTypeMask, oper);
 }
 
+HRESULT StartProcess(const base::FilePath& executable,
+                     const std::wstring& command_line,
+                     base::Process& process) {
+  if (executable.empty() || process.IsValid()) {
+    return E_UNEXPECTED;
+  }
+
+  if (!executable.IsAbsolute())
+    return E_INVALIDARG;
+
+  STARTUPINFOW si = {sizeof(si)};
+  PROCESS_INFORMATION pi = {0};
+  std::wstring parameters = command_line;
+
+  // In contrast to the following call to `::CreateProcess`,
+  // `base::Process::LaunchProcess` passes the `executable` in the
+  // `lpCommandLine` parameter to `::CreateProcess`, which uses the search path
+  // for path resolution of `executable`.
+  if (!::CreateProcess(executable.value().c_str(), &parameters[0], nullptr,
+                       nullptr, FALSE, CREATE_NO_WINDOW, nullptr, nullptr, &si,
+                       &pi)) {
+    return HRESULTFromLastError();
+  }
+
+  ::CloseHandle(pi.hThread);
+
+  process = base::Process(pi.hProcess);
+  CHECK(process.IsValid());
+  return S_OK;
+}
+
 HRESULT GetAppCommandFormatComponents(UpdaterScope scope,
                                       const std::wstring& command_format,
                                       base::FilePath& executable,
@@ -972,4 +1003,16 @@
   return formatted_command_line;
 }
 
+HRESULT ExecuteAppCommand(const base::FilePath& executable,
+                          const std::vector<std::wstring>& parameters,
+                          const std::vector<std::wstring>& substitutions,
+                          base::Process& process) {
+  const absl::optional<std::wstring> command_line =
+      FormatAppCommandLine(parameters, substitutions);
+  if (!command_line)
+    return E_INVALIDARG;
+
+  return StartProcess(executable, command_line.value(), process);
+}
+
 }  // namespace updater
diff --git a/chrome/updater/win/win_util.h b/chrome/updater/win/win_util.h
index 6711e7d..8eecc2c 100644
--- a/chrome/updater/win/win_util.h
+++ b/chrome/updater/win/win_util.h
@@ -266,6 +266,12 @@
 // call to `::GetVersionEx` or `::RtlGetVersion`.
 bool CompareOSVersions(const OSVERSIONINFOEX& os, BYTE oper);
 
+// Starts a process with separate `executable` and `command_line` components.
+// `executable` needs to be an absolute path.
+HRESULT StartProcess(const base::FilePath& executable,
+                     const std::wstring& command_line,
+                     base::Process& process);
+
 // Separates a command line in `command_format` into an `executable` and
 // `parameters`. `executable` needs to be an absolute path, and additionally
 // needs to be under %programfiles% for System `scope`. Parameters on the
@@ -291,6 +297,12 @@
     const std::vector<std::wstring>& parameters,
     const std::vector<std::wstring>& substitutions);
 
+// Helper method that calls `FormatAppCommandLine` and then `StartProcess`.
+HRESULT ExecuteAppCommand(const base::FilePath& executable,
+                          const std::vector<std::wstring>& parameters,
+                          const std::vector<std::wstring>& substitutions,
+                          base::Process& process);
+
 }  // namespace updater
 
 #endif  // CHROME_UPDATER_WIN_WIN_UTIL_H_
diff --git a/chrome/updater/win/win_util_unittest.cc b/chrome/updater/win/win_util_unittest.cc
index 41cd47e..52633ce 100644
--- a/chrome/updater/win/win_util_unittest.cc
+++ b/chrome/updater/win/win_util_unittest.cc
@@ -13,11 +13,14 @@
 
 #include "base/command_line.h"
 #include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/path_service.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/test_timeouts.h"
 #include "chrome/updater/test_scope.h"
+#include "chrome/updater/unittest_util_win.h"
 #include "chrome/updater/updater_branding.h"
 #include "chrome/updater/updater_version.h"
 #include "chrome/updater/win/test/test_executables.h"
@@ -440,4 +443,31 @@
   }
 }
 
+TEST(WinUtil, ExecuteAppCommand) {
+  base::CommandLine cmd_exe_command_line(base::CommandLine::NO_PROGRAM);
+  base::ScopedTempDir temp_programfiles_dir;
+  SetupCmdExe(GetTestScope(), cmd_exe_command_line, temp_programfiles_dir);
+
+  const struct {
+    const std::vector<std::wstring> input;
+    const std::vector<std::wstring> substitutions;
+    const int expected_exit_code;
+  } test_cases[] = {
+      {{L"/c", L"exit 7"}, {}, 7},
+      {{L"/c", L"exit %1"}, {L"5420"}, 5420},
+  };
+
+  for (const auto& test_case : test_cases) {
+    base::Process process;
+    ASSERT_HRESULT_SUCCEEDED(
+        ExecuteAppCommand(cmd_exe_command_line.GetProgram(), test_case.input,
+                          test_case.substitutions, process));
+
+    int exit_code = 0;
+    EXPECT_TRUE(process.WaitForExitWithTimeout(
+        TestTimeouts::action_max_timeout(), &exit_code));
+    EXPECT_EQ(exit_code, test_case.expected_exit_code);
+  }
+}
+
 }  // namespace updater
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index eb6d602..d915366 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-104-5060.22-1654508750-benchmark-104.0.5112.12-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-104-5060.22-1654508750-benchmark-104.0.5112.15-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index 407e4d004..6957be5c 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-104-5060.37-1655113479-benchmark-104.0.5112.12-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-104-5060.37-1655113479-benchmark-104.0.5112.15-r1-redacted.afdo.xz
diff --git a/chromeos/strings/chromeos_strings_am.xtb b/chromeos/strings/chromeos_strings_am.xtb
index 3f604df..c585fea 100644
--- a/chromeos/strings/chromeos_strings_am.xtb
+++ b/chromeos/strings/chromeos_strings_am.xtb
@@ -103,6 +103,7 @@
 <translation id="1745577949879301685">ምስሎችን መጫን አልተቻለም። የአውታረ መረብ ግንኙነትዎን ይፈትሹ ወይም ምስሎቹን እንደገና ለመጫን ይሞክሩ።</translation>
 <translation id="1751249301761991853">የግል</translation>
 <translation id="1753496554272155572">ከልጣፍ ቅድመ-እይታ ይውጡ</translation>
+<translation id="1755556344721611131">የምርመራ መተግበሪያ</translation>
 <translation id="175763766237925754">ጥሩ (<ph name="SIGNAL_STRENGTH" />)</translation>
 <translation id="1758018619400202187">EAP-TLS</translation>
 <translation id="1759842336958782510">Chrome</translation>
diff --git a/chromeos/strings/chromeos_strings_as.xtb b/chromeos/strings/chromeos_strings_as.xtb
index 168a180e3..6e1fcc3 100644
--- a/chromeos/strings/chromeos_strings_as.xtb
+++ b/chromeos/strings/chromeos_strings_as.xtb
@@ -720,6 +720,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; Google Searchত ফলাফল চাবলৈ ছাৰ্চ আৰু স্পেচ টিপক।</translation>
 <translation id="7343649194310845056">নেটৱৰ্ক ডিভাইচ</translation>
 <translation id="7359657277149375382">ফাইলৰ প্রকাৰ</translation>
+<translation id="73631062356239394">ডায়েগন’ষ্টিক্সৰ ডেটা শ্বেয়াৰ কৰক</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU</translation>
 <translation id="7397270852490618635">পাতল ৰঙৰ থীম অফ কৰক</translation>
@@ -925,6 +926,7 @@
 <translation id="9149391708638971077">মেম’ৰি পৰীক্ষা চলাওক</translation>
 <translation id="9173638680043580060">এক মিনিটতকৈ কম সময় বাকী আছে</translation>
 <translation id="917720651393141712">পৰীক্ষা কৰক</translation>
+<translation id="9188992814426075118">আপোনাৰ কীব’ৰ্ডে স্বয়ংক্ৰিয়ভাৱে আপোনাৰ ৱালপেপাৰ মিলাব পাৰে</translation>
 <translation id="9204237731135241582">Android এপৰ পৰা গে’টৱে’ সংযোগ কৰিব নোৱাৰি</translation>
 <translation id="9211490828691860325">আটাইবোৰ ডেস্ক</translation>
 <translation id="922179502584117429">বৰ্তমানৰ সংস্কৰণ <ph name="VERSION_NUMBER" /> পুৰণি হৈছে</translation>
diff --git a/chromeos/strings/chromeos_strings_de.xtb b/chromeos/strings/chromeos_strings_de.xtb
index be1affca..f4d076cf 100644
--- a/chromeos/strings/chromeos_strings_de.xtb
+++ b/chromeos/strings/chromeos_strings_de.xtb
@@ -103,6 +103,7 @@
 <translation id="1745577949879301685">Bilder konnten nicht geladen werden. Prüfe die Netzwerkverbindung oder versuch noch einmal, die Bilder zu laden.</translation>
 <translation id="1751249301761991853">Personalisierung</translation>
 <translation id="1753496554272155572">Hintergrundvorschau beenden</translation>
+<translation id="1755556344721611131">Diagnose-App</translation>
 <translation id="175763766237925754">Gut (<ph name="SIGNAL_STRENGTH" />)</translation>
 <translation id="1758018619400202187">EAP-TLS</translation>
 <translation id="1759842336958782510">Chrome</translation>
diff --git a/chromeos/strings/chromeos_strings_es.xtb b/chromeos/strings/chromeos_strings_es.xtb
index bedc7f3c..786c83b4 100644
--- a/chromeos/strings/chromeos_strings_es.xtb
+++ b/chromeos/strings/chromeos_strings_es.xtb
@@ -103,6 +103,7 @@
 <translation id="1745577949879301685">No se han podido cargar las imágenes. Revisa tu conexión de red o prueba a cargar las imágenes de nuevo.</translation>
 <translation id="1751249301761991853">Personalizar</translation>
 <translation id="1753496554272155572">Salir de la vista previa de fondo de pantalla</translation>
+<translation id="1755556344721611131">Aplicación Diagnóstico</translation>
 <translation id="175763766237925754">Buena (<ph name="SIGNAL_STRENGTH" />)</translation>
 <translation id="1758018619400202187">EAP-TLS</translation>
 <translation id="1759842336958782510">Chrome</translation>
@@ -719,6 +720,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; pulsa Buscar y la barra espaciadora para ver el resultado en la Búsqueda de Google.</translation>
 <translation id="7343649194310845056">Dispositivos de red</translation>
 <translation id="7359657277149375382">Tipo de archivo</translation>
+<translation id="73631062356239394">Compartir datos de diagnóstico</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU</translation>
 <translation id="7397270852490618635">Desactivar tema claro</translation>
@@ -924,6 +926,7 @@
 <translation id="9149391708638971077">Realizar prueba de memoria</translation>
 <translation id="9173638680043580060">Queda menos de 1 minuto</translation>
 <translation id="917720651393141712">Prueba</translation>
+<translation id="9188992814426075118">Tu teclado puede combinar automáticamente con tu fondo de pantalla</translation>
 <translation id="9204237731135241582">No se puede contactar con la pasarela desde aplicaciones Android</translation>
 <translation id="9211490828691860325">Todos los escritorios</translation>
 <translation id="922179502584117429">La versión actual (<ph name="VERSION_NUMBER" />) está desactualizada</translation>
diff --git a/chromeos/strings/chromeos_strings_fr-CA.xtb b/chromeos/strings/chromeos_strings_fr-CA.xtb
index 7c9047e..65097cd6 100644
--- a/chromeos/strings/chromeos_strings_fr-CA.xtb
+++ b/chromeos/strings/chromeos_strings_fr-CA.xtb
@@ -720,6 +720,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; Appuyez simultanément sur le bouton de recherche et la barre d'espacement pour afficher les résultats dans la recherche Google.</translation>
 <translation id="7343649194310845056">Appareils réseau</translation>
 <translation id="7359657277149375382">Type de fichier</translation>
+<translation id="73631062356239394">Partager les données de diagnostics</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">UGS</translation>
 <translation id="7397270852490618635">Désactiver le thème clair</translation>
@@ -925,6 +926,7 @@
 <translation id="9149391708638971077">Exécuter le test de mémoire</translation>
 <translation id="9173638680043580060">Il reste moins d'une minute</translation>
 <translation id="917720651393141712">Test</translation>
+<translation id="9188992814426075118">Votre clavier peut automatiquement s'agencer à votre fond d'écran</translation>
 <translation id="9204237731135241582">Impossible de communiquer avec la passerelle à partir d'applications Android</translation>
 <translation id="9211490828691860325">Tous les bureaux</translation>
 <translation id="922179502584117429">La version actuelle (<ph name="VERSION_NUMBER" />) est obsolète</translation>
diff --git a/chromeos/strings/chromeos_strings_fr.xtb b/chromeos/strings/chromeos_strings_fr.xtb
index de5635c..699ddac 100644
--- a/chromeos/strings/chromeos_strings_fr.xtb
+++ b/chromeos/strings/chromeos_strings_fr.xtb
@@ -720,6 +720,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" /> ; <ph name="RESULT_TEXT" /> ; Appuyez sur "Rechercher" et sur "Espace" pour voir le résultat dans la recherche Google.</translation>
 <translation id="7343649194310845056">Appareils sur le réseau</translation>
 <translation id="7359657277149375382">Type de fichier</translation>
+<translation id="73631062356239394">Partager les données de diagnostic</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">Code SKU</translation>
 <translation id="7397270852490618635">Annuler le thème clair</translation>
@@ -925,6 +926,7 @@
 <translation id="9149391708638971077">Lancer le test de mémoire</translation>
 <translation id="9173638680043580060">Moins d'une minute restante</translation>
 <translation id="917720651393141712">Tester</translation>
+<translation id="9188992814426075118">Votre clavier peut être automatiquement assorti à votre fond d'écran</translation>
 <translation id="9204237731135241582">Impossible de contacter la passerelle depuis les applis Android</translation>
 <translation id="9211490828691860325">Tous les bureaux</translation>
 <translation id="922179502584117429">La version <ph name="VERSION_NUMBER" /> actuellement installée est obsolète</translation>
diff --git a/chromeos/strings/chromeos_strings_gl.xtb b/chromeos/strings/chromeos_strings_gl.xtb
index aec9920..42783fe 100644
--- a/chromeos/strings/chromeos_strings_gl.xtb
+++ b/chromeos/strings/chromeos_strings_gl.xtb
@@ -720,6 +720,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; preme Buscar e Espazo para ver o resultado na Busca de Google.</translation>
 <translation id="7343649194310845056">Dispositivos de rede</translation>
 <translation id="7359657277149375382">Tipo de ficheiro</translation>
+<translation id="73631062356239394">Compartir datos de diagnóstico</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">Número de referencia (SKU)</translation>
 <translation id="7397270852490618635">Quitar tema claro</translation>
@@ -925,6 +926,7 @@
 <translation id="9149391708638971077">Realizar proba de memoria</translation>
 <translation id="9173638680043580060">Queda menos dun minuto</translation>
 <translation id="917720651393141712">Probar</translation>
+<translation id="9188992814426075118">O teclado pode combinar automaticamente co teu fondo de pantalla</translation>
 <translation id="9204237731135241582">Non se puido establecer contacto coa pasarela desde aplicacións Android</translation>
 <translation id="9211490828691860325">Todos os ordenadores</translation>
 <translation id="922179502584117429">A versión actual (<ph name="VERSION_NUMBER" />) está desactualizada</translation>
diff --git a/chromeos/strings/chromeos_strings_hy.xtb b/chromeos/strings/chromeos_strings_hy.xtb
index 62a0813c..64e764f4 100644
--- a/chromeos/strings/chromeos_strings_hy.xtb
+++ b/chromeos/strings/chromeos_strings_hy.xtb
@@ -720,6 +720,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />։ Արդյունքը Google Որոնման մեջ տեսնելու համար սեղմեք «Որոնում» + բացատ։</translation>
 <translation id="7343649194310845056">Ցանցային սարքեր</translation>
 <translation id="7359657277149375382">Ֆայլի տեսակ</translation>
+<translation id="73631062356239394">Ուղարկել դիագնոստիկ տվյալներ</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU</translation>
 <translation id="7397270852490618635">Անջատել բաց թեման</translation>
@@ -925,6 +926,7 @@
 <translation id="9149391708638971077">Փորձարկել հիշողությունը</translation>
 <translation id="9173638680043580060">Մնացել է մեկ րոպեից քիչ</translation>
 <translation id="917720651393141712">Ստուգում</translation>
+<translation id="9188992814426075118">Ստեղնաշարը կարող է ավտոմատ կերպով հարմարեցվել պաստառին</translation>
 <translation id="9204237731135241582">Չհաջողվեց կապ հաստատել անցախուցի հետ Android հավելվածներից</translation>
 <translation id="9211490828691860325">Բոլոր աշխատասեղանները</translation>
 <translation id="922179502584117429">Ընթացիկ տարբերակը (<ph name="VERSION_NUMBER" />) արդիական չէ</translation>
diff --git a/chromeos/strings/chromeos_strings_kk.xtb b/chromeos/strings/chromeos_strings_kk.xtb
index 23bc7601..0f7869d 100644
--- a/chromeos/strings/chromeos_strings_kk.xtb
+++ b/chromeos/strings/chromeos_strings_kk.xtb
@@ -719,6 +719,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; Нәтижені Google Search-тен көру үшін іздеу және бос орын пернелерін бірге басыңыз.</translation>
 <translation id="7343649194310845056">Желілік құрылғылар</translation>
 <translation id="7359657277149375382">Файл түрі</translation>
+<translation id="73631062356239394">Диагностика деректерін бөлісу</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU нөмірі</translation>
 <translation id="7397270852490618635">Жарық режимді өшіру</translation>
@@ -924,6 +925,7 @@
 <translation id="9149391708638971077">Жад тексерісін іске қосу</translation>
 <translation id="9173638680043580060">Бір минутқа жетпейтін уақыт қалды.</translation>
 <translation id="917720651393141712">Тексеру</translation>
+<translation id="9188992814426075118">Пернетақта тұсқағазды автоматты түрде сәйкестендіре алады.</translation>
 <translation id="9204237731135241582">Android қолданбаларынан шлюзге қосылу мүмкін емес.</translation>
 <translation id="9211490828691860325">Барлық жұмыс үстелдері</translation>
 <translation id="922179502584117429">Қазіргі <ph name="VERSION_NUMBER" /> нұсқасы ескірген.</translation>
diff --git a/chromeos/strings/chromeos_strings_ky.xtb b/chromeos/strings/chromeos_strings_ky.xtb
index b5ce96b..07848ce 100644
--- a/chromeos/strings/chromeos_strings_ky.xtb
+++ b/chromeos/strings/chromeos_strings_ky.xtb
@@ -721,6 +721,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; Google Издөөдөгү натыйжаларды көрүү үчүн Издөө жана Боштук баскычтарын басыңыз.</translation>
 <translation id="7343649194310845056">Тармак түзмөктөрү</translation>
 <translation id="7359657277149375382">Файлдын түрү</translation>
+<translation id="73631062356239394">Мүчүлүштүктөрдү аныктоо маалыматын бөлүшүү</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU</translation>
 <translation id="7397270852490618635">Жарык теманы өчүрүү</translation>
@@ -926,6 +927,7 @@
 <translation id="9149391708638971077">Эстутумду сыноо</translation>
 <translation id="9173638680043580060">Бир мүнөткө жетпеген убакыт калды</translation>
 <translation id="917720651393141712">Сыноо</translation>
+<translation id="9188992814426075118">Баскычтобуңуз тушкагазга автоматтык түрдө туураланышы мүмкүн</translation>
 <translation id="9204237731135241582">Android колдонмолорунан шлюзга туташпай жатат</translation>
 <translation id="9211490828691860325">Бардык иш такталар</translation>
 <translation id="922179502584117429">Учурдагы <ph name="VERSION_NUMBER" /> версиясы эскирип калган</translation>
diff --git a/chromeos/strings/chromeos_strings_lo.xtb b/chromeos/strings/chromeos_strings_lo.xtb
index 2970caa..1ce349ec 100644
--- a/chromeos/strings/chromeos_strings_lo.xtb
+++ b/chromeos/strings/chromeos_strings_lo.xtb
@@ -723,6 +723,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; ກົດຊອກຫາພ້ອມກັບຍະຫວ່າງເພື່ອເບິ່ງຜົນການຊອກຫາໃນ Google ຊອກຫາ.</translation>
 <translation id="7343649194310845056">ອຸປະກອນເຄືອຂ່າຍ</translation>
 <translation id="7359657277149375382">ປະເພດໄຟລ໌</translation>
+<translation id="73631062356239394">ແບ່ງປັນຂໍ້ມູນການວິນິໄສ</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU</translation>
 <translation id="7397270852490618635">ປິດຮູບແບບສີສັນແຈ້ງ</translation>
@@ -928,6 +929,7 @@
 <translation id="9149391708638971077">ດຳເນີນການທົດສອບຄວາມຈຳ</translation>
 <translation id="9173638680043580060">ເຫຼືອບໍ່ຮອດໜຶ່ງນາທີ</translation>
 <translation id="917720651393141712">ທົດສອບ</translation>
+<translation id="9188992814426075118">ແປ້ນພິມຂອງທ່ານສາມາດຈັບຄູ່ກັບຮູບພື້ນຫຼັງຂອງທ່ານໄດ້ອັດຕະໂນມັດ</translation>
 <translation id="9204237731135241582">ບໍ່ສາມາດຕິດຕໍ່ຫາເກດເວຈາກແອັບ Android ໄດ້</translation>
 <translation id="9211490828691860325">ໂຕະທັງໝົດ</translation>
 <translation id="922179502584117429">ເວີຊັນປັດຈຸບັນ <ph name="VERSION_NUMBER" /> ແມ່ນເກົ່າແລ້ວ</translation>
diff --git a/chromeos/strings/chromeos_strings_lt.xtb b/chromeos/strings/chromeos_strings_lt.xtb
index 1fb0747f..395e3ccc 100644
--- a/chromeos/strings/chromeos_strings_lt.xtb
+++ b/chromeos/strings/chromeos_strings_lt.xtb
@@ -103,6 +103,7 @@
 <translation id="1745577949879301685">Nepavyko įkelti vaizdų. Patikrinkite tinklo ryšį arba pabandykite dar kartą įkelti vaizdus.</translation>
 <translation id="1751249301761991853">Suasmeninimas</translation>
 <translation id="1753496554272155572">Išeiti iš ekrano fono peržiūros</translation>
+<translation id="1755556344721611131">Diagnostikos programa</translation>
 <translation id="175763766237925754">Geras (<ph name="SIGNAL_STRENGTH" />)</translation>
 <translation id="1758018619400202187">EAP-TLS</translation>
 <translation id="1759842336958782510">Chrome</translation>
diff --git a/chromeos/strings/chromeos_strings_ms.xtb b/chromeos/strings/chromeos_strings_ms.xtb
index 7e8c5fbf..2537befb 100644
--- a/chromeos/strings/chromeos_strings_ms.xtb
+++ b/chromeos/strings/chromeos_strings_ms.xtb
@@ -103,6 +103,7 @@
 <translation id="1745577949879301685">Tidak dapat memuatkan imej. Semak sambungan rangkaian anda atau cuba muatkan imej sekali lagi.</translation>
 <translation id="1751249301761991853">Peribadi</translation>
 <translation id="1753496554272155572">Keluar pratonton kertas dinding</translation>
+<translation id="1755556344721611131">Apl diagnostik</translation>
 <translation id="175763766237925754">Baik (<ph name="SIGNAL_STRENGTH" />)</translation>
 <translation id="1758018619400202187">EAP-TLS</translation>
 <translation id="1759842336958782510">Chrome</translation>
@@ -720,6 +721,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; Tekan Cari dan Ruang untuk melihat hasil carian dalam Google Search.</translation>
 <translation id="7343649194310845056">Peranti Rangkaian</translation>
 <translation id="7359657277149375382">Jenis fail</translation>
+<translation id="73631062356239394">Kongsi data diagnostik</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU</translation>
 <translation id="7397270852490618635">Matikan tema cerah</translation>
@@ -925,6 +927,7 @@
 <translation id="9149391708638971077">Jalankan Ujian memori</translation>
 <translation id="9173638680043580060">Kurang seminit lagi</translation>
 <translation id="917720651393141712">Ujian</translation>
+<translation id="9188992814426075118">Papan kekunci anda dapat memadankan kertas dinding anda secara automatik</translation>
 <translation id="9204237731135241582">Tidak dapat menghubungi get laluan daripada apl Android</translation>
 <translation id="9211490828691860325">Semua meja</translation>
 <translation id="922179502584117429">Versi semasa <ph name="VERSION_NUMBER" /> sudah lapuk</translation>
diff --git a/chromeos/strings/chromeos_strings_my.xtb b/chromeos/strings/chromeos_strings_my.xtb
index 1e9799c..dfa707df 100644
--- a/chromeos/strings/chromeos_strings_my.xtb
+++ b/chromeos/strings/chromeos_strings_my.xtb
@@ -103,6 +103,7 @@
 <translation id="1745577949879301685">ပုံများဖွင့်၍ မရပါ။ ကွန်ရက်ချိတ်ဆက်မှုကို စစ်ဆေးပါ (သို့) ပုံများကို ထပ်ဖွင့်ကြည့်ပါ။</translation>
 <translation id="1751249301761991853">ကိုယ်ပိုင်</translation>
 <translation id="1753496554272155572">နောက်ခံအစမ်းကြည့်ရှုခြင်းမှ ထွက်ရန်</translation>
+<translation id="1755556344721611131">Diagnostics အက်ပ်</translation>
 <translation id="175763766237925754">ကောင်း (<ph name="SIGNAL_STRENGTH" />)</translation>
 <translation id="1758018619400202187">EAP-TLS</translation>
 <translation id="1759842336958782510">Chrome</translation>
diff --git a/chromeos/strings/chromeos_strings_ne.xtb b/chromeos/strings/chromeos_strings_ne.xtb
index bb74a08..6c8a664 100644
--- a/chromeos/strings/chromeos_strings_ne.xtb
+++ b/chromeos/strings/chromeos_strings_ne.xtb
@@ -103,6 +103,7 @@
 <translation id="1745577949879301685">फोटोहरू लोड गर्न सकिएन। आफ्नो नेटवर्क कनेक्सन जाँच्नुहोस् वा ती फोटोहरू फेरि लोड गरी हेर्नुहोस्।</translation>
 <translation id="1751249301761991853">व्यक्तिगत</translation>
 <translation id="1753496554272155572">वालपेपरको प्रिभ्यूबाट बाहिरिनुहोस्</translation>
+<translation id="1755556344721611131">डाइग्नोस्टिक्स एप</translation>
 <translation id="175763766237925754">राम्रो (<ph name="SIGNAL_STRENGTH" />)</translation>
 <translation id="1758018619400202187">EAP-TLS</translation>
 <translation id="1759842336958782510">Chrome</translation>
diff --git a/chromeos/strings/chromeos_strings_or.xtb b/chromeos/strings/chromeos_strings_or.xtb
index 630caf9a..c9d41f3 100644
--- a/chromeos/strings/chromeos_strings_or.xtb
+++ b/chromeos/strings/chromeos_strings_or.xtb
@@ -103,6 +103,7 @@
 <translation id="1745577949879301685">ଇମେଜଗୁଡ଼ିକୁ ଲୋଡ କରାଯାଇପାରିଲା ନାହିଁ। ଆପଣଙ୍କ ନେଟୱାର୍କ କନେକ୍ସନ ଯାଞ୍ଚ କରନ୍ତୁ କିମ୍ବା ପୁଣି ଇମେଜଗୁଡ଼ିକୁ ଲୋଡ କରିବା ପାଇଁ ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="1751249301761991853">ବ୍ୟକ୍ତିଗତ</translation>
 <translation id="1753496554272155572">ୱାଲପେପର ପ୍ରିଭ୍ୟୁରୁ ବାହାରି ଯାଆନ୍ତୁ</translation>
+<translation id="1755556344721611131">Diagnostics ଆପ</translation>
 <translation id="175763766237925754">ଭଲ (<ph name="SIGNAL_STRENGTH" />)</translation>
 <translation id="1758018619400202187">EAP-TLS</translation>
 <translation id="1759842336958782510">Chrome</translation>
diff --git a/chromeos/strings/chromeos_strings_ru.xtb b/chromeos/strings/chromeos_strings_ru.xtb
index e8d69b17..f1007937 100644
--- a/chromeos/strings/chromeos_strings_ru.xtb
+++ b/chromeos/strings/chromeos_strings_ru.xtb
@@ -720,6 +720,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; Чтобы посмотреть результат в Google Поиске, нажмите "Поиск + Пробел".</translation>
 <translation id="7343649194310845056">Сетевые устройства</translation>
 <translation id="7359657277149375382">Тип файла</translation>
+<translation id="73631062356239394">Поделиться данными диагностики</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU</translation>
 <translation id="7397270852490618635">Выключить светлую тему</translation>
@@ -925,6 +926,7 @@
 <translation id="9149391708638971077">Запустить проверку памяти</translation>
 <translation id="9173638680043580060">Осталось меньше минуты…</translation>
 <translation id="917720651393141712">Проверить</translation>
+<translation id="9188992814426075118">Цвет клавиатуры может автоматически подстраиваться под цвет обоев.</translation>
 <translation id="9204237731135241582">Не удается связаться со шлюзом в приложениях для Android.</translation>
 <translation id="9211490828691860325">Все рабочие столы</translation>
 <translation id="922179502584117429">Текущая версия <ph name="VERSION_NUMBER" /> устарела</translation>
diff --git a/chromeos/strings/chromeos_strings_sq.xtb b/chromeos/strings/chromeos_strings_sq.xtb
index dad68135..6e5668d8 100644
--- a/chromeos/strings/chromeos_strings_sq.xtb
+++ b/chromeos/strings/chromeos_strings_sq.xtb
@@ -719,6 +719,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />; <ph name="RESULT_TEXT" />; Shtyp "Kërko" plus "Hapësirë" për ta shikuar rezultatin në "Kërko në Google".</translation>
 <translation id="7343649194310845056">Pajisjet e rrjetit</translation>
 <translation id="7359657277149375382">Lloji i skedarit</translation>
+<translation id="73631062356239394">Ndaj të dhënat diagnostikuese</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU</translation>
 <translation id="7397270852490618635">Çaktivizo temën e ndriçuar</translation>
@@ -924,6 +925,7 @@
 <translation id="9149391708638971077">Ekzekuto testin e memories</translation>
 <translation id="9173638680043580060">Ka mbetur më pak se një minutë</translation>
 <translation id="917720651393141712">Provë</translation>
+<translation id="9188992814426075118">Tastiera jote mund të përputhet automatikisht me imazhin e sfondit</translation>
 <translation id="9204237731135241582">Portëkalimi nuk mund të kontaktohet nga aplikacionet për Android</translation>
 <translation id="9211490828691860325">Të gjitha tavolinat e punës</translation>
 <translation id="922179502584117429">Versioni aktual; <ph name="VERSION_NUMBER" /> është i papërditësuar</translation>
diff --git a/chromeos/strings/chromeos_strings_sv.xtb b/chromeos/strings/chromeos_strings_sv.xtb
index 2ef1a31..3a57bf5 100644
--- a/chromeos/strings/chromeos_strings_sv.xtb
+++ b/chromeos/strings/chromeos_strings_sv.xtb
@@ -720,6 +720,7 @@
 <translation id="7343581795491695942"><ph name="QUERY_TEXT" />: <ph name="RESULT_TEXT" />. Om du trycker på Sök och blanksteg visas resultatet på Google Sök.</translation>
 <translation id="7343649194310845056">Nätverksenheter</translation>
 <translation id="7359657277149375382">Filtyp</translation>
+<translation id="73631062356239394">Dela diagnostikdata</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7378553660733179982">SKU</translation>
 <translation id="7397270852490618635">Inaktivera ljust tema</translation>
@@ -925,6 +926,7 @@
 <translation id="9149391708638971077">Kör minnestest</translation>
 <translation id="9173638680043580060">Mindre än en minut kvar</translation>
 <translation id="917720651393141712">Testa</translation>
+<translation id="9188992814426075118">Tangentbordet kan matcha bakgrunden automatiskt</translation>
 <translation id="9204237731135241582">Det gick inte att kontakta gateway från Android-appar</translation>
 <translation id="9211490828691860325">Alla skrivbord</translation>
 <translation id="922179502584117429">Nuvarande version <ph name="VERSION_NUMBER" /> är inte uppdaterad</translation>
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index 58e7809..4159b4f 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "10.15",
-  "log_list_timestamp": "2022-06-17T12:54:21Z",
+  "version": "10.16",
+  "log_list_timestamp": "2022-06-18T12:53:42Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/ntp_tiles/popular_sites_impl.cc b/components/ntp_tiles/popular_sites_impl.cc
index e2dcf668..21cf92f 100644
--- a/components/ntp_tiles/popular_sites_impl.cc
+++ b/components/ntp_tiles/popular_sites_impl.cc
@@ -228,7 +228,7 @@
   absl::optional<base::Value> sites = base::JSONReader::Read(
       ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
           IDR_DEFAULT_POPULAR_SITES_JSON));
-  for (base::Value& site : sites.value().GetList())
+  for (base::Value& site : sites->GetList())
     site.GetDict().Set("baked_in", true);
 
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
@@ -238,7 +238,7 @@
         IDR_DEFAULT_POPULAR_SITES_ICON2, IDR_DEFAULT_POPULAR_SITES_ICON3,
         IDR_DEFAULT_POPULAR_SITES_ICON4, IDR_DEFAULT_POPULAR_SITES_ICON5,
         IDR_DEFAULT_POPULAR_SITES_ICON6, IDR_DEFAULT_POPULAR_SITES_ICON7}) {
-    SetDefaultResourceForSite(index++, icon_resource, sites.GetList());
+    SetDefaultResourceForSite(index++, icon_resource, sites->GetList());
   }
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
   return std::move(sites.value());
diff --git a/components/strings/components_strings_ky.xtb b/components/strings/components_strings_ky.xtb
index e576710..2d2b1eb 100644
--- a/components/strings/components_strings_ky.xtb
+++ b/components/strings/components_strings_ky.xtb
@@ -1252,7 +1252,7 @@
 <translation id="4349365535725594680">Купуя мазмун бөлүшүлбөй жатат</translation>
 <translation id="4350629523305688469">Көп функционалдуу түпкүч</translation>
 <translation id="4351060348582610152"><ph name="ORIGIN" /> сайты жакын жердеги Bluetooth түзмөктөрүн скандаганы жатат. Төмөнкү түзмөктөр табылды:</translation>
-<translation id="4351175281479794167">Текшерүү кодун киргизиңиз</translation>
+<translation id="4351175281479794167">Ырастоо кодун киргизиңиз</translation>
 <translation id="4356973930735388585">Бул сайттагы бүлдүргүчтөр түзмөгүңүздөгү маалыматыңызды (мисалы, сүрөттөр, сырсөздөр, билдирүүлөр жана насыя карталары) уурдап же жок кыла турган коркунучтуу программаларды орнотууга аракет кылышы мүмкүн.</translation>
 <translation id="4358059973562876591">Сиз көрсөткөн үлгүлөрдү колдонууга болбойт, анткени DnsOverHttpsMode саясатында ката кетти.</translation>
 <translation id="4358461427845829800">Төлөм ыкмаларын башкаруу...</translation>
@@ -2787,7 +2787,7 @@
 <translation id="8718314106902482036">Төлөм аягына чыккан жок</translation>
 <translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, издөө сунушу</translation>
 <translation id="8719528812645237045">Муштум менен өйдө жакка эки жолу уруу</translation>
-<translation id="8723535127346307411">Текшерүү кодун киргизиңиз</translation>
+<translation id="8723535127346307411">Ырастоо кодун киргизиңиз</translation>
 <translation id="8725066075913043281">Кайра аракет кылып көрүү</translation>
 <translation id="8726549941689275341">Барактын өлчөмү:</translation>
 <translation id="8730621377337864115">Бүттү</translation>
diff --git a/content/browser/direct_sockets/direct_sockets_tcp_browsertest.cc b/content/browser/direct_sockets/direct_sockets_tcp_browsertest.cc
index 639e960a..24ab3f9 100644
--- a/content/browser/direct_sockets/direct_sockets_tcp_browsertest.cc
+++ b/content/browser/direct_sockets/direct_sockets_tcp_browsertest.cc
@@ -266,10 +266,28 @@
     return tcp_server_socket_;
   }
 
+  raw_ptr<content::test::AsyncJsRunner> GetAsyncJsRunner() const {
+    return runner_.get();
+  }
+
+  void ConnectJsSocket(int port = 0) const {
+    const std::string open_socket = JsReplace(
+        R"(
+          socket = new TCPSocket($1, $2);
+          await socket.connection;
+        )",
+        kLocalhostAddress, port);
+
+    ASSERT_TRUE(
+        EvalJs(shell(), content::test::WrapAsync(open_socket)).value.is_none());
+  }
+
  protected:
   void SetUpOnMainThread() override {
     ContentBrowserTest::SetUpOnMainThread();
     ASSERT_TRUE(NavigateToURL(shell(), GetTestPageURL()));
+    runner_ =
+        std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
   }
 
   void SetUp() override {
@@ -297,10 +315,12 @@
   base::test::ScopedFeatureList feature_list_;
   mojo::Remote<network::mojom::MdnsResponder> mdns_responder_;
   mojo::Remote<network::mojom::TCPServerSocket> tcp_server_socket_;
+
+  std::unique_ptr<content::test::AsyncJsRunner> runner_;
 };
 
 IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, OpenTcp_Success) {
-  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
+  ASSERT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
 
   const int listening_port = StartTcpServer();
   const std::string script =
@@ -312,7 +332,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, OpenTcp_Success_Global) {
-  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
+  ASSERT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
 
   const int listening_port = StartTcpServer();
   const std::string script =
@@ -330,7 +350,7 @@
 #define MAYBE_OpenTcp_MDNS OpenTcp_MDNS
 #endif
 IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, MAYBE_OpenTcp_MDNS) {
-  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
+  ASSERT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
 
   const int listening_port = StartTcpServer();
   const std::string name = CreateMDNSHostName();
@@ -461,22 +481,17 @@
   MockTcpNetworkContext mock_network_context;
   DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
 
-  const std::string open_socket = JsReplace(
-      R"(
-        socket = new TCPSocket($1, 0);
-        await socket.connection;
-      )",
-      kLocalhostAddress);
+  ConnectJsSocket();
 
-  ASSERT_TRUE(
-      EvalJs(shell(), content::test::WrapAsync(open_socket)).value.is_none());
+  const std::string async_script =
+      "readTcpOnError(socket, /*expected_read_success=*/false);";
+  auto future = GetAsyncJsRunner()->RunScript(async_script);
 
-  auto runner =
-      std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
-  const std::string async_script = "readTcpOnError(socket);";
-  auto future = runner->RunScript(async_script);
-
-  mock_network_context.get_observer()->OnReadError(net::ERR_NOT_IMPLEMENTED);
+  {
+    // Simulate pipe shutdown on read error. Read requests must reject.
+    mock_network_context.get_observer()->OnReadError(net::ERR_NOT_IMPLEMENTED);
+    mock_network_context.get_consumer_complement().reset();
+  }
 
   EXPECT_THAT(future->Get(), ::testing::HasSubstr("readTcpOnError succeeded."));
 }
@@ -485,22 +500,18 @@
   MockTcpNetworkContext mock_network_context;
   DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
 
-  const std::string open_socket = JsReplace(
-      R"(
-        socket = new TCPSocket($1, 0);
-        await socket.connection;
-      )",
-      kLocalhostAddress);
+  ConnectJsSocket();
 
-  ASSERT_TRUE(
-      EvalJs(shell(), content::test::WrapAsync(open_socket)).value.is_none());
+  const std::string async_script =
+      "readTcpOnError(socket, /*expected_read_success=*/true);";
+  auto future = GetAsyncJsRunner()->RunScript(async_script);
 
-  auto runner =
-      std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
-  const std::string async_script = "readTcpOnError(socket);";
-  auto future = runner->RunScript(async_script);
-
-  mock_network_context.get_consumer_complement().reset();
+  {
+    // Simulate pipe shutdown on peer closed. Read requests must resolve with
+    // done = true.
+    mock_network_context.get_observer()->OnReadError(net::OK);
+    mock_network_context.get_consumer_complement().reset();
+  }
 
   EXPECT_THAT(future->Get(), ::testing::HasSubstr("readTcpOnError succeeded."));
 }
@@ -509,47 +520,16 @@
   MockTcpNetworkContext mock_network_context;
   DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
 
-  const std::string open_socket = JsReplace(
-      R"(
-        socket = new TCPSocket($1, 0);
-        await socket.connection;
-      )",
-      kLocalhostAddress);
+  ConnectJsSocket();
 
-  ASSERT_TRUE(
-      EvalJs(shell(), content::test::WrapAsync(open_socket)).value.is_none());
-
-  auto runner =
-      std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
   const std::string async_script = "writeTcpOnError(socket);";
-  auto future = runner->RunScript(async_script);
+  auto future = GetAsyncJsRunner()->RunScript(async_script);
 
-  mock_network_context.get_observer()->OnWriteError(net::ERR_NOT_IMPLEMENTED);
-
-  EXPECT_THAT(future->Get(),
-              ::testing::HasSubstr("writeTcpOnError succeeded."));
-}
-
-IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, WriteTcpOnPipeError) {
-  MockTcpNetworkContext mock_network_context;
-  DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
-
-  const std::string open_socket = JsReplace(
-      R"(
-        socket = new TCPSocket($1, 0);
-        await socket.connection;
-      )",
-      kLocalhostAddress);
-
-  ASSERT_TRUE(
-      EvalJs(shell(), content::test::WrapAsync(open_socket)).value.is_none());
-
-  auto runner =
-      std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
-  const std::string async_script = "writeTcpOnError(socket);";
-  auto future = runner->RunScript(async_script);
-
-  mock_network_context.get_producer_complement().reset();
+  {
+    // Simulate pipe shutdown on write error.
+    mock_network_context.get_observer()->OnWriteError(net::ERR_NOT_IMPLEMENTED);
+    mock_network_context.get_producer_complement().reset();
+  }
 
   EXPECT_THAT(future->Get(),
               ::testing::HasSubstr("writeTcpOnError succeeded."));
@@ -560,25 +540,75 @@
   MockTcpNetworkContext mock_network_context;
   DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
 
-  const std::string open_socket = JsReplace(
-      R"(
-        socket = new TCPSocket($1, 0);
-        await socket.connection;
-      )",
-      kLocalhostAddress);
+  ConnectJsSocket();
 
-  ASSERT_TRUE(
-      EvalJs(shell(), content::test::WrapAsync(open_socket)).value.is_none());
-
-  auto runner =
-      std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
   const std::string async_script = "readWriteTcpOnError(socket);";
-  auto future = runner->RunScript(async_script);
+  auto future = GetAsyncJsRunner()->RunScript(async_script);
 
   mock_network_context.get_observer().reset();
+  mock_network_context.get_consumer_complement().reset();
+  mock_network_context.get_producer_complement().reset();
 
   EXPECT_THAT(future->Get(),
               ::testing::HasSubstr("readWriteTcpOnError succeeded."));
 }
 
+IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest,
+                       BarrierCallbackFiresWithErrorOnReadWriteError) {
+  MockTcpNetworkContext mock_network_context;
+  DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
+
+  ConnectJsSocket();
+
+  const std::string async_script =
+      "waitForClosedPromise(socket, /*expected_closed_result=*/false);";
+  auto future = GetAsyncJsRunner()->RunScript(async_script);
+
+  {
+    mock_network_context.get_observer()->OnReadError(net::ERR_UNEXPECTED);
+    mock_network_context.get_consumer_complement().reset();
+    mock_network_context.get_producer_complement().reset();
+    mock_network_context.get_observer()->OnWriteError(net::ERR_UNEXPECTED);
+  }
+
+  EXPECT_THAT(future->Get(),
+              ::testing::HasSubstr("waitForClosedPromise succeeded."));
+}
+
+IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest,
+                       BarrierCallbackFiresWithOkOnReaderAndWriterClose) {
+  MockTcpNetworkContext mock_network_context;
+  DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
+
+  ConnectJsSocket();
+
+  const std::string async_script =
+      "waitForClosedPromise(socket, /*expected_closed_result=*/true, "
+      "/*cancel_reader=*/true, /*close_writer=*/true);";
+  auto future = GetAsyncJsRunner()->RunScript(async_script);
+
+  EXPECT_THAT(future->Get(),
+              ::testing::HasSubstr("waitForClosedPromise succeeded."));
+}
+
+IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest,
+                       BarrierCallbackFiresWithOkOnPeerAndWriterClose) {
+  MockTcpNetworkContext mock_network_context;
+  DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
+
+  ConnectJsSocket();
+
+  const std::string async_script =
+      "waitForClosedPromise(socket, /*expected_closed_result=*/true, "
+      "/*cancel_reader=*/false, /*close_writer=*/true);";
+  auto future = GetAsyncJsRunner()->RunScript(async_script);
+
+  // Simulate peer closed event.
+  mock_network_context.get_observer()->OnReadError(net::OK);
+  mock_network_context.get_consumer_complement().reset();
+
+  EXPECT_THAT(future->Get(),
+              ::testing::HasSubstr("waitForClosedPromise succeeded."));
+}
+
 }  // namespace content
diff --git a/content/browser/direct_sockets/direct_sockets_udp_browsertest.cc b/content/browser/direct_sockets/direct_sockets_udp_browsertest.cc
index f3531376..b9acbea 100644
--- a/content/browser/direct_sockets/direct_sockets_udp_browsertest.cc
+++ b/content/browser/direct_sockets/direct_sockets_udp_browsertest.cc
@@ -59,10 +59,28 @@
     return browser_context()->GetDefaultStoragePartition()->GetNetworkContext();
   }
 
+  raw_ptr<content::test::AsyncJsRunner> GetAsyncJsRunner() const {
+    return runner_.get();
+  }
+
+  void ConnectJsSocket(int port = 0) const {
+    const std::string open_socket = JsReplace(
+        R"(
+          socket = new UDPSocket($1, $2);
+          await socket.connection;
+        )",
+        kLocalhostAddress, port);
+
+    ASSERT_TRUE(
+        EvalJs(shell(), content::test::WrapAsync(open_socket)).value.is_none());
+  }
+
  protected:
   void SetUpOnMainThread() override {
     ContentBrowserTest::SetUpOnMainThread();
     EXPECT_TRUE(NavigateToURL(shell(), GetTestPageURL()));
+    runner_ =
+        std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
   }
 
   void SetUp() override {
@@ -111,6 +129,8 @@
   ScopedContentBrowserClientSetting setting{&client_};
   base::test::ScopedFeatureList feature_list_;
   mojo::Remote<network::mojom::UDPSocket> server_socket_;
+
+  std::unique_ptr<content::test::AsyncJsRunner> runner_;
 };
 
 IN_PROC_BROWSER_TEST_F(DirectSocketsUdpBrowserTest, CloseUdp) {
@@ -163,7 +183,6 @@
 
 IN_PROC_BROWSER_TEST_F(DirectSocketsUdpBrowserTest, SendUdpAfterClose) {
   const int32_t kRequiredBytes = 1;
-
   const std::string script = JsReplace("sendUdpAfterClose($1, $2, {}, $3)",
                                        kLocalhostAddress, 993, kRequiredBytes);
 
@@ -197,8 +216,6 @@
 
   const uint16_t local_port = EvalJs(shell(), open_socket).ExtractInt();
 
-  auto runner =
-      std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
   const std::string async_read = content::test::WrapAsync(JsReplace(
       R"(
         let { readable } = await socket.connection;
@@ -206,7 +223,7 @@
         return await readLoop(reader, $1);
       )",
       static_cast<int>(kRequiredBytes)));
-  auto future = runner->RunScript(async_read);
+  auto future = GetAsyncJsRunner()->RunScript(async_read);
 
   // With a client socket listening in the javascript code, we can finally start
   // sending out data.
@@ -253,7 +270,7 @@
       JsReplace("readUdpAfterStreamClose($1, $2, {})",
                 server_address.ToStringWithoutPort(), server_address.port());
 
-  EXPECT_EQ("readUdpAferSocketClose succeeded.", EvalJs(shell(), script));
+  EXPECT_EQ("readUdpAferStreamClose succeeded.", EvalJs(shell(), script));
 }
 
 IN_PROC_BROWSER_TEST_F(DirectSocketsUdpBrowserTest, CloseWithActiveReader) {
@@ -265,7 +282,7 @@
       CreateUDPServerSocket(listener_receiver.BindNewPipeAndPassRemote());
 
   const std::string open_socket =
-      JsReplace("closeUdpWithLockedReadable($1, $2)",
+      JsReplace("closeUdpWithLockedReadable($1, $2, /*unlock=*/false)",
                 server_address.ToStringWithoutPort(), server_address.port());
 
   EXPECT_THAT(EvalJs(shell(), open_socket).ExtractString(),
@@ -282,7 +299,7 @@
       CreateUDPServerSocket(listener_receiver.BindNewPipeAndPassRemote());
 
   const std::string open_socket =
-      JsReplace("closeUdpWithLockedReadable($1, $2, true)",
+      JsReplace("closeUdpWithLockedReadable($1, $2, /*unlock=*/true)",
                 server_address.ToStringWithoutPort(), server_address.port());
 
   EXPECT_THAT(EvalJs(shell(), open_socket).ExtractString(),
@@ -293,20 +310,10 @@
   content::test::MockNetworkContext mock_network_context;
   DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
 
-  const std::string open_socket = JsReplace(
-      R"(
-        socket = new UDPSocket($1, 0);
-        await socket.connection;
-      )",
-      kLocalhostAddress);
+  ConnectJsSocket();
 
-  ASSERT_TRUE(
-      EvalJs(shell(), content::test::WrapAsync(open_socket)).value.is_none());
-
-  auto runner =
-      std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
   const std::string async_read = "readWriteUdpOnError(socket);";
-  auto future = runner->RunScript(async_read);
+  auto future = GetAsyncJsRunner()->RunScript(async_read);
 
   // MockNetworkContext owns the MockUDPSocket and therefore outlives it.
   mock_network_context.get_udp_socket()->SetAdditionalSendCallback(
@@ -324,15 +331,7 @@
   content::test::MockNetworkContext mock_network_context;
   DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
 
-  const std::string open_socket = JsReplace(
-      R"(
-        socket = new UDPSocket($1, 0);
-        await socket.connection;
-      )",
-      kLocalhostAddress);
-
-  ASSERT_TRUE(
-      EvalJs(shell(), content::test::WrapAsync(open_socket)).value.is_none());
+  ConnectJsSocket();
 
   // MockNetworkContext owns the MockUDPSocket and therefore outlives it.
   mock_network_context.get_udp_socket()->SetAdditionalSendCallback(
@@ -342,10 +341,8 @@
           },
           &mock_network_context));
 
-  auto runner =
-      std::make_unique<content::test::AsyncJsRunner>(shell()->web_contents());
   const std::string script = "readWriteUdpOnError(socket)";
-  auto future = runner->RunScript(script);
+  auto future = GetAsyncJsRunner()->RunScript(script);
 
   EXPECT_THAT(future->Get(),
               ::testing::HasSubstr("readWriteUdpOnError succeeded"));
diff --git a/content/test/data/direct_sockets/tcp.js b/content/test/data/direct_sockets/tcp.js
index 32f82c9..ec4989866 100644
--- a/content/test/data/direct_sockets/tcp.js
+++ b/content/test/data/direct_sockets/tcp.js
@@ -111,14 +111,14 @@
   return writer.write(encoder.encode(value)).then(() => true, () => false);
 }
 
-async function readTcpOnError(socket) {
+async function readTcpOnError(socket, expected_read_success) {
   try {
     let { readable } = await socket.connection;
 
     let reader = readable.getReader();
 
     let read_request_success = await read(reader);
-    if (!read_request_success) {
+    if (read_request_success === expected_read_success) {
       return 'readTcpOnError succeeded.';
     } else {
       throw new TypeError(`read_request_success = ${read_request_success}`);
@@ -162,3 +162,30 @@
     return 'readWriteTcpOnError failed: ' + error;
   }
 }
+
+async function waitForClosedPromise(socket, expected_closed_result, cancel_reader = false, close_writer = false) {
+  try {
+    let { readable, writable } = await socket.connection;
+
+    let reader = readable.getReader();
+    let writer = writable.getWriter();
+
+    if (cancel_reader) {
+      reader.cancel();
+    }
+
+    if (close_writer) {
+      writer.close();
+    }
+
+    const closed_result = await socket.closed.then(() => true, () => false);
+
+    if (closed_result === expected_closed_result) {
+      return 'waitForClosedPromise succeeded.';
+    } else {
+      throw new TypeError(`closed_result = ${closed_result}, expected_close_result = ${expected_closed_result}`);
+    }
+  } catch (error) {
+    return 'waitForClosedPromise failed: ' + error;
+  }
+}
diff --git a/content/test/data/direct_sockets/udp.js b/content/test/data/direct_sockets/udp.js
index dc6162c7..d3afc86a 100644
--- a/content/test/data/direct_sockets/udp.js
+++ b/content/test/data/direct_sockets/udp.js
@@ -76,48 +76,53 @@
   }
 }
 
-async function readUdpAfterSocketClose(address, port, options) {
+async function readUdpAfterSocketClose(address, port) {
   try {
-    let udpSocket = new UDPSocket(address, port, options);
-    let { readable } = await udpSocket.connection;
+    let udpSocket = new UDPSocket(address, port);
+    let { readable, writable } = await udpSocket.connection;
     let reader = readable.getReader();
-    await udpSocket.close({ force: true });
-    let { value, done } = await reader.read();
-    if (!done) {
-      return 'Stream is not closed!';
-    }
-    return 'readUdpAferSocketClose succeeded.';
-  } catch (error) {
-    return ('readUdpAfterSocketClose failed: ' + error);
-  }
-}
-
-async function readUdpAfterStreamClose(address, port, options) {
-  try {
-    let udpSocket = new UDPSocket(address, port, options);
-    let { readable } = await udpSocket.connection;
-    let reader = readable.getReader();
+    let writer = writable.getWriter();
+    let rp = reader.read().catch(() => {});
     await reader.cancel();
-    let { value, done } = await reader.read();
-    if (!done) {
-      return 'Stream is not closed!';
-    }
+    await writer.abort();
+    await rp;
     return 'readUdpAferSocketClose succeeded.';
   } catch (error) {
     return ('readUdpAfterSocketClose failed: ' + error);
   }
 }
 
-async function closeUdpWithLockedReadable(address, port, force = false) {
+async function readUdpAfterStreamClose(address, port) {
+  try {
+    let udpSocket = new UDPSocket(address, port);
+    let { readable } = await udpSocket.connection;
+    let reader = readable.getReader();
+    let rp = reader.read().catch(() => {});
+    await reader.cancel();
+    let { value, done } = await rp;
+    if (!done) {
+      return 'Stream is not closed!';
+    }
+    return 'readUdpAferStreamClose succeeded.';
+  } catch (error) {
+    return ('readUdpAfterStreamClose failed: ' + error);
+  }
+}
+
+async function closeUdpWithLockedReadable(address, port, unlock = false) {
   try {
     let udpSocket = new UDPSocket(address, port);
     let { readable } = await udpSocket.connection;
 
     let reader = readable.getReader();
 
-    await udpSocket.close({ force });
+    if (unlock) {
+      reader.releaseLock();
+    }
 
-    if (force) {
+    await udpSocket.close();
+
+    if (unlock) {
       await udpSocket.closed;
     }
 
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_as.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_as.xtb
index c9c0dfc..63c15fd 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_as.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_as.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromiumএ আপোনাৰ পাছৱর্ডসমূহ পৰীক্ষা কৰিব নোৱাৰিলে। আপোনাৰ ইণ্টাৰনেট সংযোগ পৰীক্ষা কৰি চাওক।</translation>
 <translation id="3472200483164753384">Chromium Canaryত সমৰ্থিত নহয়</translation>
 <translation id="3567399274263440288">Chromium পাৰ্যমানে ব্যৱহাৰ কৰিবলৈ আপোনাৰ Google একাউণ্টটোৰ জৰিয়তে Chromiumত ছাইন ইন কৰক।</translation>
+<translation id="3619462831205197427">এইটো ছাইট, আপোনাৰ Google একাউণ্ট আৰু Chromiumত ছাইন ইন কৰক।</translation>
 <translation id="3639997914391704523">আপুনি নিজৰ Google একাউণ্টটোৰ জৰিয়তে ছাইন ইন কৰিলে Chromiumএ আপোনাৰ পাছৱর্ডসমূহ পৰীক্ষা কৰিব পাৰে।</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" />এ Chromium ব্যৱহাৰ কৰি আছিল আৰু এই ডিভাইচটোত বুকমাৰ্ক, পাছৱৰ্ড আৰু অন্য ছেটিং এৰি গৈছে।</translation>
 <translation id="3805899903892079518">আপোনাৰ ফট’ আৰু ভিডিঅ’সমূহত Chromiumৰ এক্সেছ নাই। iOS ছেটিং &gt; গোপনীয়তা &gt; ফট’-ত এক্সেছ সক্ষম কৰক।</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_es.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_es.xtb
index 28845010..2e870c79 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_es.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_es.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium no ha podido comprobar tus contraseñas. Revisa tu conexión a Internet.</translation>
 <translation id="3472200483164753384">No compatible con Chromium Canary</translation>
 <translation id="3567399274263440288">Para sacarle el máximo partido a Chromium, inicia sesión en Chromium con tu cuenta de Google.</translation>
+<translation id="3619462831205197427">Inicia sesión en este sitio, en tu cuenta de Google y en Chromium.</translation>
 <translation id="3639997914391704523">Chromium puede comprobar tus contraseñas cuando inicias sesión con tu cuenta de Google.</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> ha usado Chromium y ha dejado marcadores, contraseñas y otras configuraciones en este dispositivo.</translation>
 <translation id="3805899903892079518">Chromium no puede acceder a tus fotos y vídeos (para permitirlo, ve a Ajustes de iOS &gt; Privacidad &gt; Fotos).</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_fr-CA.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_fr-CA.xtb
index 89aae18..bd033f0 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_fr-CA.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_fr-CA.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium n'a pas pu vérifier vos mots de passe. Essayez de vérifier votre connexion Internet.</translation>
 <translation id="3472200483164753384">Fonctionnalité non prise en charge par Chromium Canary</translation>
 <translation id="3567399274263440288">Connectez-vous à Chromium avec votre compte Google pour en tirer le meilleur parti.</translation>
+<translation id="3619462831205197427">Connectez-vous à ce site, à votre compte Google et à Chromium.</translation>
 <translation id="3639997914391704523">Chromium peut vérifier vos mots de passe lorsque vous vous connectez avec votre compte Google.</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> utilisait Chromium et a laissé des favoris, des mots de passe et d'autres paramètres sur cet appareil.</translation>
 <translation id="3805899903892079518">Chromium n'a pas accès à vos photos ou vidéos. Activez l'accès dans Réglages iOS &gt; Confidentialité &gt; Photos.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_fr.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_fr.xtb
index 3a11e35..0c17245 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_fr.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_fr.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium n'est pas parvenu à vérifier vos mots de passe. Vérifiez votre connexion Internet.</translation>
 <translation id="3472200483164753384">Non disponible dans Chromium Canary</translation>
 <translation id="3567399274263440288">Pour profiter pleinement de Chromium, connectez-vous avec votre compte Google.</translation>
+<translation id="3619462831205197427">Connectez-vous à ce site, à votre compte Google et à Chromium.</translation>
 <translation id="3639997914391704523">Chromium peut vérifier vos mots de passe lorsque vous vous connectez avec votre compte Google.</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> utilisait Chromium et a laissé des favoris, des mots de passe et d'autres paramètres sur cet appareil.</translation>
 <translation id="3805899903892079518">Chromium n'a pas accès à vos photos ni à vos vidéos. Activez l'accès dans iOS via Réglages &gt; Confidentialité &gt; Photos.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_gl.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_gl.xtb
index 17aecb0..49b46d8 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_gl.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_gl.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium non puido comprobar os teus contrasinais. Verifica a conexión a Internet.</translation>
 <translation id="3472200483164753384">Non compatible en Chromium Canary</translation>
 <translation id="3567399274263440288">Para tirarlle o máximo partido a Chromium, inicia sesión coa túa Conta de Google en Chromium.</translation>
+<translation id="3619462831205197427">Inicia sesión neste sitio, na túa Conta de Google e en Chromium.</translation>
 <translation id="3639997914391704523">Chromium pode comprobar os teus contrasinais cando inicies sesión coa túa Conta de Google.</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> estivo usando Chromium e deixou os marcadores, os contrasinais e outras opcións de configuración neste dispositivo.</translation>
 <translation id="3805899903892079518">Chromium non ten acceso ás túas fotos nin aos teus vídeos. Activa o acceso en Configuración de iOS &gt; Privacidade &gt; Fotos.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_hy.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_hy.xtb
index 61b0ba65..409773b 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_hy.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_hy.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium-ին չհաջողվեց ստուգել ձեր գաղտնաբառերը։ Ստուգեք ինտերնետ կապը։</translation>
 <translation id="3472200483164753384">Չի աջակցվում Chromium Canary-ում</translation>
 <translation id="3567399274263440288">Chromium-ի բոլոր գործառույթներն օգտագործելու համար մտեք ձեր Google հաշիվ։</translation>
+<translation id="3619462831205197427">Մուտք գործեք այս կայքում, ձեր Google հաշիվ և Chromium։</translation>
 <translation id="3639997914391704523">Chromium-ը կարող է ստուգել ձեր գաղտնաբառերը, երբ մտնեք Google հաշիվ։</translation>
 <translation id="3650632991272923014">Օգտատերը (<ph name="USER_EMAIL1" />) օգտագործել է Chromium-ը, և այս սարքում պահպանվել են էջանիշներ, գաղտնաբառեր և այլ կարգավորումներ։</translation>
 <translation id="3805899903892079518">Chromium-ին հասանելի չեն ձեր լուսանկարները կամ տեսանյութերը: Անցեք iOS Կարգավորումներ &gt; Գաղտնիություն &gt; Լուսանկարներ (Settings &gt; Privacy &gt; Photos) և միացրեք մուտքի թույլտվությունը:</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_kk.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_kk.xtb
index 7605106..6936e8d 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_kk.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_kk.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium сіздің құпия сөздеріңізді тексере алмады. Интернет байланысын тексеріп көріңіз.</translation>
 <translation id="3472200483164753384">Chromium Canary-де қолдау көрсетілмейді.</translation>
 <translation id="3567399274263440288">Chromium-ді барынша пайдалану үшін оған Google аккаунтыңызбен кіріңіз.</translation>
+<translation id="3619462831205197427">Осы сайтқа, Google аккаунтыңызға және Chromium браузеріне кіріңіз.</translation>
 <translation id="3639997914391704523">Google аккаунтыңызбен кіргенде, Chromium сіздің құпия сөздеріңізді тексере алады.</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> Chromium браузерін қолданған еді, сондықтан осы құрылғыда оның бетбелгілері, құпия сөздері және басқа да параметрлері қалып қойды.</translation>
 <translation id="3805899903892079518">Chromium сурет пен бейнелерге кіре алмайды. "iOS параметрлері &gt; Құпиялылық &gt; Фотосуреттер" арқылы рұқсат беру қажет.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ky.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ky.xtb
index dfb3faa..52ec9f4 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_ky.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ky.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium сырсөздөрүңүздү текшере алган жок. Интернет байланышын текшерип көрүңүз.</translation>
 <translation id="3472200483164753384">Chromium Canary'де колдоого алынбайт</translation>
 <translation id="3567399274263440288">Chromium'дун бардык мүмкүнчүлүктөрүн пайдалануу үчүн Google аккаунтуңуз менен Chromium'га кириңиз.</translation>
+<translation id="3619462831205197427">Бул сайтка, Google аккаунтуңузга жана Chromium'га кириңиз.</translation>
 <translation id="3639997914391704523">Google аккаунтуңуз менен киргенде Chromium сырсөздөрүңүздү текшерет.</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> бул түзмөктө Chromium'ду колдонуп, кыстармаларды, сырсөздөрдү жана башка жөндөөлөрдү өчүрбөй калды.</translation>
 <translation id="3805899903892079518">Chromium сүрөттөрүңүздү же видеолоруңузду көрө албайт. Көрүү үчүн iOS Жөндөөлөрү &gt; Купуялык &gt; Сүрөттөргө өтүңүз.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_lo.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_lo.xtb
index c4ccfc6..fcaa3729 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_lo.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_lo.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium ບໍ່ສາມາດກວດລະຫັດຜ່ານຂອງທ່ານໄດ້. ລອງກວດເບິ່ງການເຊື່ອມຕໍ່ອິນເຕີເນັດຂອງທ່ານ.</translation>
 <translation id="3472200483164753384">ບໍ່ຮອງຮັບໃນ Chromium Canary</translation>
 <translation id="3567399274263440288">ເພື່ອໃຊ້ປະໂຫຍດສູງສຸດຈາກ Chromium, ໃຫ້ເຂົ້າສູ່ລະບົບຫາ Chromium ດ້ວຍບັນຊີ Google ຂອງທ່ານ.</translation>
+<translation id="3619462831205197427">ເຂົ້າສູ່ລະບົບເວັບໄຊນີ້, ບັນຊີ Google ຂອງທ່ານ ແລະ Chromium.</translation>
 <translation id="3639997914391704523">Chromium ສາມາດກວດເບິ່ງລະຫັດຜ່ານຂອງທ່ານ ເມື່ອທ່ານເຂົ້າສູ່ລະບົບດ້ວຍບັນຊີ Google ຂອງທ່ານໄດ້.</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> ກຳລັງໃຊ້ Chromium ຢູ່ ແລະ ເປີດບຸກມາກ, ລະຫັດຜ່ານ ແລະ ການຕັ້ງຄ່າອື່ນໆປະໄວ້ຢູ່ອຸປະກອນນີ້.</translation>
 <translation id="3805899903892079518">Chromium ບໍ່​ມີ​ການ​ເຂົ້າ​ເຖິງ​ຮູບຖ່າຍ ຫຼື ​ວິ​ດີ​ໂອ​ຂອງ​ທ່ານ. ເປີດ​ໃຊ້​ການ​ເຂົ້າເຖິງ​ຢູ່​ໃນ​ການ​ຕັ້ງ​ຄ່າ iOS &gt; Privacy &gt; Photos.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ms.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ms.xtb
index 2a5a612..1987a58 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_ms.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ms.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium tidak dapat menyemak kata laluan anda. Cuba periksa sambungan Internet anda.</translation>
 <translation id="3472200483164753384">Tidak disokong pada Chromium Canary</translation>
 <translation id="3567399274263440288">Untuk memanfaatkan Chromium sepenuhnya, log masuk ke Chromium dengan Google Account anda.</translation>
+<translation id="3619462831205197427">Log masuk ke laman ini, Akaun Google anda dan Chromium.</translation>
 <translation id="3639997914391704523">Chromium boleh menyemak kata laluan anda apabila anda log masuk menggunakan Akaun Google anda.</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> telah menggunakan Chromium dan membiarkan penanda halaman, kata laluan dan tetapan lain pada peranti ini.</translation>
 <translation id="3805899903892079518">Chromium tidak mempunyai akses kepada foto atau video anda. Dayakan akses dalam Tetapan iOS &gt; Privasi &gt; Foto.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_ru.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_ru.xtb
index 0e7d057f..9fc550b 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_ru.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_ru.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Не удается проверить пароли в браузере Chromium. Проверьте подключение к Интернету.</translation>
 <translation id="3472200483164753384">Проверка не поддерживается в Chromium Canary.</translation>
 <translation id="3567399274263440288">Чтобы пользоваться всеми возможностями браузера Chromium, войдите в аккаунт Google.</translation>
+<translation id="3619462831205197427">Войдите на этот сайт, в аккаунт Google и в Chromium.</translation>
 <translation id="3639997914391704523">Chromium сможет проверить ваши пароли, если вы войдете в аккаунт Google.</translation>
 <translation id="3650632991272923014">Пользователь <ph name="USER_EMAIL1" />, который работал с Chromium на этом устройстве, не удалил свои закладки, пароли и другие настройки</translation>
 <translation id="3805899903892079518">У Chromium нет доступа к вашим фото и видео. Чтобы предоставить его, нажмите "Настройки &gt; Конфиденциальность &gt; Фотографии".</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_sq.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_sq.xtb
index 52e53cb..ff4f1fd 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_sq.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_sq.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium nuk mund t'i kontrollonte fjalëkalimet e tua. Provo të kontrollosh lidhjen e internetit.</translation>
 <translation id="3472200483164753384">Nuk mbështetet në Chromium Canary</translation>
 <translation id="3567399274263440288">Për të marrë maksimumin nga Chromium, identifikohu në Chromium me "Llogarinë tënde të Google".</translation>
+<translation id="3619462831205197427">Identifikohu në këtë sajt, "Llogarinë tënde të Google" dhe Chromium.</translation>
 <translation id="3639997914391704523">Chromium mund t'i kontrollojë fjalëkalimet e tua kur të identifikohesh me "Llogarinë tënde të Google".</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> po përdorte Chromium dhe ka lënë faqeshënues, fjalëkalime dhe cilësime të tjera në këtë pajisje.</translation>
 <translation id="3805899903892079518">Chromium nuk ka qasje te fotografitë apo videot e tua. Aktivizo qasjen te Cilësimet e iOS &gt; Privatësia &gt; Fotografitë.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_chromium_strings_sv.xtb b/ios/chrome/app/strings/resources/ios_chromium_strings_sv.xtb
index a777cfd..6bc2894 100644
--- a/ios/chrome/app/strings/resources/ios_chromium_strings_sv.xtb
+++ b/ios/chrome/app/strings/resources/ios_chromium_strings_sv.xtb
@@ -45,6 +45,7 @@
 <translation id="3344973607274501920">Chromium kunde inte kontrollera dina lösenord. Testa att kontrollera internetanslutningen.</translation>
 <translation id="3472200483164753384">Stöds inte på Chromium Canary</translation>
 <translation id="3567399274263440288">Logga in i Chromium med Google-kontot så att du får ut mesta möjliga av programmet.</translation>
+<translation id="3619462831205197427">Logga in på den här webbplatsen, i ditt Google-konto och i Chromium.</translation>
 <translation id="3639997914391704523">Chromium kan kontrollera dina lösenord när du loggar in med Google-kontot.</translation>
 <translation id="3650632991272923014"><ph name="USER_EMAIL1" /> använde Chromium och har lämnat kvar bokmärken, lösenord och andra inställningar på enheten.</translation>
 <translation id="3805899903892079518">Chromium har inte åtkomst till dina foton eller videor. Aktivera åtkomst i iOS-inställningar &gt; Integritet &gt; Foton.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_as.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_as.xtb
index a4654e7..9c507e3 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_as.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_as.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">আপোনাৰ একাউণ্টসমূহ ৱেবলৈ আনি Chromeএ আপোনাৰ সময় ৰাহি কৰে। আপুনি ছেটিংসমূহ-ত একাউন্ট যোগ দিব বা আঁতৰাব পাৰে।</translation>
 <translation id="3282568296779691940">Chromeত ছাইন-ইন কৰক</translation>
 <translation id="3345341804167540816">সকলোতে Chrome ব্যৱহাৰ কৰক</translation>
+<translation id="3428998300753080128">এইটো ছাইট, আপোনাৰ Google একাউণ্ট আৰু Chromeত ছাইন ইন কৰক।</translation>
 <translation id="3522659714780527202">আপুনি Chrome ব্যৱহাৰ কৰা সকলো ডিভাইচৰ পৰা নিজৰ টেবসমূহ চাবলৈ ছিংক অন কৰক</translation>
 <translation id="3533694711092285624">ছেভ কৰা কোনো পাছৱৰ্ড নাই। আপুনি আপোনাৰ পাছৱর্ডসমূহ ছেভ কৰিলে Chromeএ সেইবোৰ পৰীক্ষা কৰিব পাৰে।</translation>
 <translation id="3641179212828090796">দ্ৰুতভাৱে ছাইন ইন কৰিবলৈ আপুনি Chromeত ছেভ কৰি থোৱা পাছৱৰ্ডটো ব্যৱহাৰ কৰক</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_es.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_es.xtb
index 0983fc32..eaeb746 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_es.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_es.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Chrome te permite llevar tus cuentas a la Web para ahorrar tiempo. Puedes añadirlas o quitarlas en los ajustes.</translation>
 <translation id="3282568296779691940">Iniciar sesión en Chrome</translation>
 <translation id="3345341804167540816">Usar Chrome en todas partes</translation>
+<translation id="3428998300753080128">Inicia sesión en este sitio, en tu cuenta de Google y en Chrome.</translation>
 <translation id="3522659714780527202">Activa la sincronización para ver tus pestañas dondequiera que uses Chrome</translation>
 <translation id="3533694711092285624">No hay ninguna contraseña guardada. Chrome puede comprobar tus contraseñas cuando las guardas.</translation>
 <translation id="3641179212828090796">Usa la contraseña que guardaste en Chrome para iniciar sesión más rápido</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_fr-CA.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_fr-CA.xtb
index f12867a3..9856ec1 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_fr-CA.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_fr-CA.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Chrome vous fait gagner du temps en mettant vos comptes sur le Web. Vous pouvez ajouter ou supprimer des comptes dans Paramètres.</translation>
 <translation id="3282568296779691940">Connexion à Chrome</translation>
 <translation id="3345341804167540816">Utiliser Chrome sur toutes les plateformes</translation>
+<translation id="3428998300753080128">Connectez-vous à ce site, à votre compte Google et à Chrome.</translation>
 <translation id="3522659714780527202">Pour voir vos onglets partout où vous utilisez Chrome, activez la synchronisation</translation>
 <translation id="3533694711092285624">Aucun mot de passe enregistré. Chrome ne peut vérifier vos mots de passe que si vous les enregistrez.</translation>
 <translation id="3641179212828090796">Utilisez le mot de passe que vous avez enregistré dans Chrome pour vous connecter plus rapidement</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_fr.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_fr.xtb
index 282384c89..6917f9c 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_fr.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_fr.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Chrome vous permet de gagner du temps en connectant vos comptes au Web. Vous pouvez ajouter ou supprimer des comptes dans la section "Paramètres".</translation>
 <translation id="3282568296779691940">Connectez-vous à Chrome</translation>
 <translation id="3345341804167540816">Utilisez Chrome où que vous soyez</translation>
+<translation id="3428998300753080128">Connectez-vous à ce site, à votre compte Google et à Chrome.</translation>
 <translation id="3522659714780527202">Pour retrouver vos onglets Chrome quel que soit l'appareil utilisé, activez la synchronisation</translation>
 <translation id="3533694711092285624">Aucun mot de passe enregistré. Chrome ne peut vérifier vos mots de passe que si vous les enregistrez.</translation>
 <translation id="3641179212828090796">Utiliser le mot de passe que vous avez enregistré dans Chrome pour vous connecter plus vite</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_gl.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_gl.xtb
index 754f909b..2cfd942 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_gl.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_gl.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Chrome fai que aforres tempo ao pasar as túas contas á web. Podes engadir ou eliminar contas en Configuración.</translation>
 <translation id="3282568296779691940">Iniciar sesión en Chrome</translation>
 <translation id="3345341804167540816">Usar Chrome en todas partes</translation>
+<translation id="3428998300753080128">Inicia sesión neste sitio, na túa Conta de Google e en Chrome.</translation>
 <translation id="3522659714780527202">Para ver as túas pestanas desde calquera dispositivo no que utilices Chrome, activa a sincronización</translation>
 <translation id="3533694711092285624">Non hai contrasinais gardados. Chrome pode comprobar os teus contrasinais cando os gardes.</translation>
 <translation id="3641179212828090796">Usa o contrasinal que gardaches en Chrome para iniciar sesión máis rápido</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_hy.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_hy.xtb
index 9283a57..068a42d 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_hy.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_hy.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Chrome-ը խնայում է ձեր ժամանակը՝ ձեր հաշիվները հասանելի դարձնելով համացանցում: Կարգավորումներում կարող եք ավելացնել կամ հեռացնել հաշիվներ:</translation>
 <translation id="3282568296779691940">Մուտք գործել Chrome</translation>
 <translation id="3345341804167540816">Օգտագործեք Chrome-ն ամենուրեք</translation>
+<translation id="3428998300753080128">Մուտք գործեք այս կայքում, ձեր Google հաշիվ և Chrome։</translation>
 <translation id="3522659714780527202">Chrome-ն օգտագործելիս ձեր բոլոր ներդիրները տեսնելու համար միացրեք համաժամացումը։</translation>
 <translation id="3533694711092285624">Պահված գաղտնաբառեր չկան։ Chrome-ը կարող է ստուգել ձեր գաղտնաբառերը, երբ պահում եք դրանք։</translation>
 <translation id="3641179212828090796">Ավելի արագ մուտք գործելու համար օգտագործեք Chrome-ում ձեր պահած գաղտնաբառը</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_kk.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_kk.xtb
index 73536ba5..dab2531 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_kk.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_kk.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Chrome браузері аккаунттарыңызды вебке алып келу арқылы уақыт үнемдейді. "Параметрлер" бөлімінде аккаунттарды енгізуге немесе өшіруге болады.</translation>
 <translation id="3282568296779691940">Chrome жүйесіне кіру</translation>
 <translation id="3345341804167540816">Chrome қолданбасын барлық жерде қолдану</translation>
+<translation id="3428998300753080128">Осы сайтқа, Google аккаунтыңызға және Chrome браузеріне кіріңіз.</translation>
 <translation id="3522659714780527202">Chrome браузерін пайдаланатын кез келген жерден қойындыларды көру үшін синхрондауды қосыңыз.</translation>
 <translation id="3533694711092285624">Ешқандай құпия сөз сақталмаған. Құпия сөздер сақталған кезде, Chrome оларды тексере алады.</translation>
 <translation id="3641179212828090796">Жылдамырақ кіру үшін Chrome-да сақталған құпия сөзді пайдаланыңыз.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ky.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ky.xtb
index b72188ad..e54474d 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ky.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ky.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Аккаунттарыңызды желеге жайгаштыруу менен Chrome убакытыңызды үнөмдөйт. Аккаунттарды Жөндөөлөрдөн кошуп же алып салсаңыз болот.</translation>
 <translation id="3282568296779691940">Chrome'го кириңиз</translation>
 <translation id="3345341804167540816">Бүт жерде Chrome колдонуңуз</translation>
+<translation id="3428998300753080128">Бул сайтка, Google аккаунтуңузга жана Chrome'го кириңиз.</translation>
 <translation id="3522659714780527202">Chrome колдонулган түзмөктөрдүн баарындагы өтмөктөрүңүздү көрүү үчүн шайкештирүүнү күйгүзүңүз</translation>
 <translation id="3533694711092285624">Сакталган сырсөздөр жок. Сырсөздөрүңүздү сактаганда Chrome аларды текшере алат.</translation>
 <translation id="3641179212828090796">Аккаунтка тезирээк кирүү үчүн Chrome'го сакталган сырсөздү колдонуңуз</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_lo.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_lo.xtb
index a2597a61..c1bc4764 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_lo.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_lo.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Chrome ຊ່ວຍທ່ານປະຢັດເວລາໂດຍການນຳເອົາບັນຊີຂອງທ່ານມາສູ່ເວັບ. ທ່ານສາມາດເພີ່ມ ຫຼື ລຶບບັນຊີອອກໄດ້ໃນການຕັ້ງຄ່າ.</translation>
 <translation id="3282568296779691940">ລົງຊື່ເຂົ້າ​ໃຊ້ Chrome</translation>
 <translation id="3345341804167540816">ໃຊ້ Chrome ຢູ່​ທຸກ​ບ່ອນ</translation>
+<translation id="3428998300753080128">ເຂົ້າສູ່ລະບົບເວັບໄຊນີ້, ບັນຊີ Google ຂອງທ່ານ ແລະ Chrome.</translation>
 <translation id="3522659714780527202">ເພື່ອເຫັນແຖບຂອງທ່ານຈາກທຸກບ່ອນທີ່ທ່ານໃຊ້ Chrome, ກະລຸນາເປີດການຊິ້ງຂໍ້ມູນ</translation>
 <translation id="3533694711092285624">ບໍ່ມີລະຫັດຜ່ານທີ່ບັນທຶກໄວ້. Chrome ສາມາດກວດເບິ່ງລະຫັດຜ່ານຂອງທ່ານເມື່ອທ່ານບັນທຶກພວກມັນໄວ້.</translation>
 <translation id="3641179212828090796">ໃຊ້ລະຫັດຜ່ານທີ່ທ່ານບັນທຶກໄວ້ໃນ Chrome ເພື່ອເຂົ້າສູ່ລະບົບໄດ້ໄວຂຶ້ນ</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ms.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ms.xtb
index b056e775..9a494b8 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ms.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ms.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Chrome menjimatkan masa anda dengan membawa akaun anda ke web. Anda boleh menambahkan atau mengalih keluar akaun dalam Tetapan.</translation>
 <translation id="3282568296779691940">Log masuk ke Chrome</translation>
 <translation id="3345341804167540816">Gunakan Chrome Everywhere</translation>
+<translation id="3428998300753080128">Log masuk ke laman ini, Akaun Google anda dan Chrome.</translation>
 <translation id="3522659714780527202">Untuk melihat tab anda daripada mana-mana tempat anda menggunakan Chrome, hidupkan penyegerakan</translation>
 <translation id="3533694711092285624">Tiada kata laluan yang disimpan. Chrome boleh menyemak kata laluan anda yang disimpan.</translation>
 <translation id="3641179212828090796">Gunakan kata laluan yang anda simpan dalam Chrome untuk log masuk dengan lebih pantas</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ru.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ru.xtb
index f9ab790..30772894 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ru.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ru.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Чтобы сэкономить ваше время, Chrome будет использовать аккаунты, сохраненные на вашем устройстве. Добавить или удалить их можно в настройках.</translation>
 <translation id="3282568296779691940">Войти в Chrome</translation>
 <translation id="3345341804167540816">Возьмите Chrome с собой</translation>
+<translation id="3428998300753080128">Войдите на этот сайт, в аккаунт Google и в Chrome.</translation>
 <translation id="3522659714780527202">Чтобы ваши вкладки всегда были доступны вам при работе с Chrome, включите синхронизацию.</translation>
 <translation id="3533694711092285624">Сохраненных паролей нет. Чтобы браузер Chrome мог проверять пароли, сохраните их.</translation>
 <translation id="3641179212828090796">Воспользуйтесь сохраненным в Chrome паролем для быстрого входа</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sq.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sq.xtb
index 7591b96..9a4e68f62 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sq.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sq.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Chrome të kursen kohë duke i sjellë llogaritë e  tua në ueb. Mund të shtosh ose të heqësh llogari te "Cilësimet".</translation>
 <translation id="3282568296779691940">Identifikohu në Chrome</translation>
 <translation id="3345341804167540816">Përdor Chrome kudo</translation>
+<translation id="3428998300753080128">Identifikohu në këtë sajt, "Llogarinë tënde të Google" dhe Chrome.</translation>
 <translation id="3522659714780527202">Për të parë skedat e tua nga çdo vend ku përdor Chrome, aktivizo sinkronizimin</translation>
 <translation id="3533694711092285624">Nuk ka asnjë fjalëkalim të ruajtur. Chrome mund t'i kontrollojë fjalëkalimet e tua kur ti i ruan ato.</translation>
 <translation id="3641179212828090796">Përdor fjalëkalimin që ruajte në Chrome për t'u identifikuar më shpejt</translation>
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sv.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sv.xtb
index 7337b8f0..0ece8d4d 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_sv.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_sv.xtb
@@ -39,6 +39,7 @@
 <translation id="3196546062792660320">Med Chrome sparar du tid genom att dina konton blir tillgängliga på nätet. Du kan lägga till och ta bort konton i inställningarna.</translation>
 <translation id="3282568296779691940">Logga in i Chrome</translation>
 <translation id="3345341804167540816">Använd Chrome överallt</translation>
+<translation id="3428998300753080128">Logga in på den här webbplatsen, i ditt Google-konto och i Chrome.</translation>
 <translation id="3522659714780527202">Aktivera synkronisering om du vill ha samma flikar tillgängliga på alla enheter där du använder Chrome</translation>
 <translation id="3533694711092285624">Det finns inga sparade lösenord. Chrome kan bara kontrollera dina lösenord om du sparar dem.</translation>
 <translation id="3641179212828090796">Logga in snabbare med lösenordet du sparade i Chrome</translation>
diff --git a/media/gpu/vaapi/vaapi_unittest.cc b/media/gpu/vaapi/vaapi_unittest.cc
index 226be8f..49d569a 100644
--- a/media/gpu/vaapi/vaapi_unittest.cc
+++ b/media/gpu/vaapi/vaapi_unittest.cc
@@ -57,6 +57,7 @@
     {AV1PROFILE_PROFILE_MAIN, VAProfileAV1Profile0},
 #if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
     {HEVCPROFILE_MAIN, VAProfileHEVCMain},
+    {HEVCPROFILE_MAIN_STILL_PICTURE, VAProfileHEVCMain},
     {HEVCPROFILE_MAIN10, VAProfileHEVCMain10},
 #endif  // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
   };
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index d0b49a19..38c78bb 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -597,6 +597,7 @@
         // {AV1PROFILE_PROFILE_HIGH, VAProfileAV1Profile1},
 #if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
           {HEVCPROFILE_MAIN, VAProfileHEVCMain},
+          {HEVCPROFILE_MAIN_STILL_PICTURE, VAProfileHEVCMain},
           {HEVCPROFILE_MAIN10, VAProfileHEVCMain10},
 #endif  // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
   });
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 050dc1b6..ced6589 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -8361,7 +8361,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8412,15 +8412,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8446,7 +8446,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8871,7 +8871,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8922,15 +8922,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8956,7 +8956,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 84e6e52c..139d31b 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -46491,7 +46491,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46542,15 +46542,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46576,7 +46576,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47001,7 +47001,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47052,15 +47052,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47086,7 +47086,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47515,7 +47515,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47566,15 +47566,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47600,7 +47600,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48025,7 +48025,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48076,15 +48076,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48110,7 +48110,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48607,7 +48607,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48658,15 +48658,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48692,7 +48692,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49117,7 +49117,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49168,15 +49168,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49202,7 +49202,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49699,7 +49699,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49750,15 +49750,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49784,7 +49784,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50209,7 +50209,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.57"
+              "revision": "version:103.0.5060.58"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50260,15 +50260,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50294,7 +50294,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.12"
+              "revision": "version:104.0.5112.16"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 5c8aa18..7964ade4 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -493,16 +493,16 @@
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M104/out/Release',
-      '--impl-version=104'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=104',
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -510,10 +510,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.12'
+          'revision': 'version:104.0.5112.16',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
@@ -534,7 +534,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.57',
+          'revision': 'version:103.0.5060.58',
         }
       ],
     },
@@ -637,16 +637,16 @@
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M104/out/Release',
-      '--impl-version=104'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=104',
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -654,10 +654,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.12'
+          'revision': 'version:104.0.5112.16',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
@@ -678,7 +678,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.57',
+          'revision': 'version:103.0.5060.58',
         }
       ],
     },
@@ -781,16 +781,16 @@
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
-      '--client-version=104'
+      '--client-version=104',
     ],
     'identifier': 'with_client_from_104',
     'swarming': {
@@ -798,10 +798,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.12'
+          'revision': 'version:104.0.5112.16',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
@@ -822,7 +822,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.57',
+          'revision': 'version:103.0.5060.58',
         }
       ],
     },
diff --git a/third_party/blink/public/common/media/video_capture.h b/third_party/blink/public/common/media/video_capture.h
index a408b88..33f4f1f 100644
--- a/third_party/blink/public/common/media/video_capture.h
+++ b/third_party/blink/public/common/media/video_capture.h
@@ -46,6 +46,9 @@
     std::vector<scoped_refptr<media::VideoFrame>> scaled_video_frames,
     base::TimeTicks estimated_capture_time)>;
 
+// Callback for delivering dropped frame notifications.
+using VideoCaptureNotifyFrameDroppedCB = base::RepeatingClosure;
+
 using VideoCaptureDeviceFormatsCB =
     base::OnceCallback<void(const media::VideoCaptureFormats&)>;
 
diff --git a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
index e8eeb17..33f8619d 100644
--- a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
+++ b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
@@ -86,6 +86,7 @@
   void AddTrack(MediaStreamVideoTrack* track,
                 const VideoTrackAdapterSettings& track_adapter_settings,
                 const VideoCaptureDeliverFrameCB& frame_callback,
+                const VideoCaptureNotifyFrameDroppedCB& dropped_callback,
                 const EncodedVideoFrameCB& encoded_frame_callback,
                 const VideoTrackSettingsCallback& settings_callback,
                 const VideoTrackFormatCallback& format_callback,
@@ -357,20 +358,9 @@
   State state_;
 
   struct PendingTrackInfo {
-    PendingTrackInfo(
-        MediaStreamVideoTrack* track,
-        const VideoCaptureDeliverFrameCB& frame_callback,
-        const EncodedVideoFrameCB& encoded_frame_callback,
-        const VideoTrackSettingsCallback& settings_callback,
-        const VideoTrackFormatCallback& format_callback,
-        std::unique_ptr<VideoTrackAdapterSettings> adapter_settings,
-        ConstraintsOnceCallback callback);
-    PendingTrackInfo(PendingTrackInfo&& other);
-    PendingTrackInfo& operator=(PendingTrackInfo&& other);
-    ~PendingTrackInfo();
-
     MediaStreamVideoTrack* track;
     VideoCaptureDeliverFrameCB frame_callback;
+    VideoCaptureNotifyFrameDroppedCB notify_frame_dropped_callback;
     EncodedVideoFrameCB encoded_frame_callback;
     VideoTrackSettingsCallback settings_callback;
     VideoTrackFormatCallback format_callback;
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index 47aeb60..adb6b091 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -2679,8 +2679,6 @@
 # we need to compile in the same way as would happen when current_os="android".
 if (target_os != "android") {
   generated_dictionary_sources_in_modules += [
-    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_socket_close_options.cc",
-    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_socket_close_options.h",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_socket_connection.cc",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_socket_connection.h",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_socket_options.cc",
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index fe081d2d..22d678e 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -88,8 +88,32 @@
 class ShouldCompleteScope;
 class AttemptToEndForbiddenScope;
 
+bool ThreadedPreloadScannerEnabled() {
+  // Cache the feature value since checking for each parser regresses some micro
+  // benchmarks.
+  static const bool kEnabled =
+      base::FeatureList::IsEnabled(features::kThreadedPreloadScanner);
+  return kEnabled;
+}
+
+bool TimedParserBudgetEnabled() {
+  // Cache the feature value since checking for each parser regresses some micro
+  // benchmarks.
+  static const bool kEnabled =
+      base::FeatureList::IsEnabled(features::kTimedHTMLParserBudget);
+  return kEnabled;
+}
+
+bool PrecompileInlineScriptsEnabled() {
+  // Cache the feature value since checking for each parser regresses some micro
+  // benchmarks.
+  static const bool kEnabled =
+      base::FeatureList::IsEnabled(features::kPrecompileInlineScripts);
+  return kEnabled;
+}
+
 Thread* GetPreloadScannerThread() {
-  DCHECK(base::FeatureList::IsEnabled(features::kThreadedPreloadScanner));
+  DCHECK(ThreadedPreloadScannerEnabled());
 
   // The preload scanner relies on parsing CSS, which requires creating garbage
   // collected objects. This means the thread the scanning runs on must be GC
@@ -117,7 +141,7 @@
 };
 
 PreloadProcessingMode GetPreloadProcessingMode() {
-  if (!base::FeatureList::IsEnabled(features::kThreadedPreloadScanner))
+  if (!ThreadedPreloadScannerEnabled())
     return PreloadProcessingMode::kNone;
 
   static const base::FeatureParam<PreloadProcessingMode>::Option
@@ -504,7 +528,7 @@
                      ? Thread::Current()->Scheduler()
                      : nullptr) {
   // Make sure the preload scanner thread will be ready when needed.
-  if (background_scanning_enabled_ && !task_runner_state_->IsSynchronous())
+  if (ThreadedPreloadScannerEnabled() && !task_runner_state_->IsSynchronous())
     GetPreloadScannerThread();
 
   // Report metrics for async document parsing or forced synchronous parsing.
@@ -774,7 +798,7 @@
           : 1e7;
 
   base::TimeDelta timed_budget;
-  if (timed_parser_budget_enabled_)
+  if (TimedParserBudgetEnabled())
     timed_budget = GetTimedBudget(task_runner_state_->TimesYielded());
 
   base::ElapsedTimer chunk_parsing_timer_;
@@ -793,7 +817,7 @@
       // to yield at some point soon, especially if we're in "extended budget"
       // mode. So reduce the budget back to at most the default.
       budget = std::min(budget, kDefaultMaxTokenizationBudget);
-      if (timed_parser_budget_enabled_) {
+      if (TimedParserBudgetEnabled()) {
         timed_budget = std::min(timed_budget, chunk_parsing_timer_.Elapsed() +
                                                   GetDefaultTimedBudget());
       }
@@ -814,7 +838,7 @@
       DCHECK(base::FeatureList::IsEnabled(
                  features::kDeferBeginMainFrameDuringLoading) ||
              scheduler_->DontDeferBeginMainFrame());
-      if (timed_parser_budget_enabled_)
+      if (TimedParserBudgetEnabled())
         should_yield = chunk_parsing_timer_.Elapsed() >= timed_budget;
       else
         should_yield = budget <= 0 && scheduler_->DontDeferBeginMainFrame();
@@ -1387,7 +1411,7 @@
     // If background scanning is enabled, the main document scanner is used when
     // the parser is paused, for prefetch documents, or if preload scanning is
     // disabled in tests (HTMLPreloadScanner internally handles this setting).
-    DCHECK(!background_scanning_enabled_ || IsPaused() ||
+    DCHECK(!ThreadedPreloadScannerEnabled() || IsPaused() ||
            GetDocument()->IsPrefetchOnly() ||
            !IsPreloadScanningEnabled(GetDocument()));
   }
@@ -1470,7 +1494,7 @@
 }
 
 void HTMLDocumentParser::ScanInBackground(const String& source) {
-  if (background_scanning_enabled_ && preloader_ &&
+  if (ThreadedPreloadScannerEnabled() && preloader_ &&
       !task_runner_state_->IsSynchronous() && GetDocument()->Url().IsValid() &&
       // TODO(crbug.com/1329535): Support scanning prefetch documents in the
       // background.
@@ -1494,7 +1518,7 @@
     return;
   }
 
-  if (!base::FeatureList::IsEnabled(features::kPrecompileInlineScripts))
+  if (!PrecompileInlineScriptsEnabled())
     return;
 
   DCHECK(!background_scanner_);
@@ -1521,7 +1545,7 @@
 }
 
 void HTMLDocumentParser::FlushPendingPreloads() {
-  DCHECK(background_scanning_enabled_);
+  DCHECK(ThreadedPreloadScannerEnabled());
   if (IsDetached() || !preloader_)
     return;
 
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.h b/third_party/blink/renderer/core/html/parser/html_document_parser.h
index e1cf872..6cc1606 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.h
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.h
@@ -225,8 +225,6 @@
   std::unique_ptr<HTMLPreloadScanner> insertion_preload_scanner_;
   WTF::SequenceBound<BackgroundHTMLScanner> background_script_scanner_;
   WTF::SequenceBound<HTMLPreloadScanner> background_scanner_;
-  const bool background_scanning_enabled_ =
-      base::FeatureList::IsEnabled(features::kThreadedPreloadScanner);
 
   scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
 
@@ -246,9 +244,6 @@
   Vector<std::unique_ptr<PendingPreloadData>> pending_preload_data_
       GUARDED_BY(pending_preload_lock_);
 
-  const bool timed_parser_budget_enabled_ =
-      base::FeatureList::IsEnabled(features::kTimedHTMLParserBudget);
-
   ThreadScheduler* scheduler_;
 };
 
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_offset.h b/third_party/blink/renderer/core/layout/geometry/logical_offset.h
index cc48a9d..dd494af 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_offset.h
@@ -26,8 +26,13 @@
   constexpr LogicalOffset(LayoutUnit inline_offset, LayoutUnit block_offset)
       : inline_offset(inline_offset), block_offset(block_offset) {}
 
+  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
+  // or int. Use explicit LayoutUnit constructor for each parameter instead.
+  LogicalOffset(float, float) = delete;
+
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
-  inline LogicalOffset(int inline_offset, int block_offset);
+  // 'constexpr' is to let compiler detect incorrect usages in production code.
+  constexpr LogicalOffset(int inline_offset, int block_offset);
 
   LayoutUnit inline_offset;
   LayoutUnit block_offset;
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_rect.h b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
index df6a5f4..fe1c94b 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_rect.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
@@ -28,11 +28,16 @@
                         LayoutUnit block_size)
       : offset(inline_offset, block_offset), size(inline_size, block_size) {}
 
+  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
+  // or int. Use explicit LayoutUnit constructor for each parameter instead.
+  LogicalRect(float, float, float, float) = delete;
+
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
-  inline LogicalRect(int inline_offset,
-                     int block_offset,
-                     int inline_size,
-                     int block_size);
+  // 'constexpr' is to let compiler detect usage from production code.
+  constexpr LogicalRect(int inline_offset,
+                        int block_offset,
+                        int inline_size,
+                        int block_size);
 
   constexpr explicit LogicalRect(const LayoutRect& source)
       : LogicalRect({source.X(), source.Y()},
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_size.h b/third_party/blink/renderer/core/layout/geometry/logical_size.h
index beff8464..e952b385 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_size.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_size.h
@@ -24,8 +24,13 @@
   constexpr LogicalSize(LayoutUnit inline_size, LayoutUnit block_size)
       : inline_size(inline_size), block_size(block_size) {}
 
+  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
+  // or int. Use explicit LayoutUnit constructor for each parameter instead.
+  LogicalSize(float, float) = delete;
+
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
-  inline LogicalSize(int inline_size, int block_size);
+  // 'constexpr' is to let compiler detect usage from production code.
+  constexpr LogicalSize(int inline_size, int block_size);
 
   // Use ToPhysicalSize to convert to a physical size.
 
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_offset.h b/third_party/blink/renderer/core/layout/geometry/physical_offset.h
index 96a6624..2ffc06a 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_offset.h
@@ -31,8 +31,14 @@
   constexpr PhysicalOffset(LayoutUnit left, LayoutUnit top)
       : left(left), top(top) {}
 
+  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
+  // or int. Use explicit LayoutUnit constructor for each parameter, or use
+  // FromPointFFloor etc. instead.
+  PhysicalOffset(float, float) = delete;
+
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
-  inline PhysicalOffset(int left, int top);
+  // 'constexpr' is to let compiler detect usage from production code.
+  constexpr PhysicalOffset(int left, int top);
 
   LayoutUnit left;
   LayoutUnit top;
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_rect.h b/third_party/blink/renderer/core/layout/geometry/physical_rect.h
index 697ff55..6c1c426 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_rect.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_rect.h
@@ -41,8 +41,14 @@
                          LayoutUnit height)
       : offset(left, top), size(width, height) {}
 
+  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
+  // or int. Use explicit LayoutUnit constructor for each parameter, or use
+  // EnclosingRect() or FastAndLossyFromRectF() instead.
+  PhysicalRect(float, float, float, float) = delete;
+
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
-  inline PhysicalRect(int left, int top, int width, int height);
+  // 'constexpr' is to let compiler detect usage from production code.
+  constexpr PhysicalRect(int left, int top, int width, int height);
 
   PhysicalOffset offset;
   PhysicalSize size;
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_size.h b/third_party/blink/renderer/core/layout/geometry/physical_size.h
index 6842445..e50df6b 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_size.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_size.h
@@ -29,8 +29,14 @@
   constexpr PhysicalSize(LayoutUnit width, LayoutUnit height)
       : width(width), height(height) {}
 
+  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
+  // or int. Use explicit LayoutUnit constructor for each parameter, or use
+  // FromSizeF*() instead.
+  PhysicalSize(float, float) = delete;
+
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
-  inline PhysicalSize(int width, int height);
+  // 'constexpr' is to let compiler detect usage from production code.
+  constexpr PhysicalSize(int width, int height);
 
   LayoutUnit width;
   LayoutUnit height;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc
index 96041df..43cef79 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc
@@ -170,14 +170,16 @@
 
     // TODO(ethavar): Compute automatic repetitions for subgridded axes as
     // described in https://drafts.csswg.org/css-grid-2/#auto-repeat.
-
     auto subgridded_items = subgrid.ConstructGridItems(&subgrid_placement_data);
-    grid_items.ReserveCapacity(grid_items.Size() + subgridded_items.Size());
 
     const wtf_size_t column_start_line = current_item.StartLine(kForColumns);
     const wtf_size_t row_start_line = current_item.StartLine(kForRows);
 
-    for (auto subgridded_item : subgridded_items.item_data) {
+    // Don't use |current_item| after we reserve the new capacity; the reference
+    // becomes invalid because |grid_items| is reallocated.
+    grid_items.ReserveCapacity(grid_items.Size() + subgridded_items.Size());
+
+    for (auto& subgridded_item : subgridded_items.item_data) {
       subgridded_item.is_subgridded_to_parent_grid = true;
 
       subgridded_item.resolved_position.columns.Translate(column_start_line);
diff --git a/third_party/blink/renderer/core/testing/core_unit_test_helper.h b/third_party/blink/renderer/core/testing/core_unit_test_helper.h
index f13775fb..b939383 100644
--- a/third_party/blink/renderer/core/testing/core_unit_test_helper.h
+++ b/third_party/blink/renderer/core/testing/core_unit_test_helper.h
@@ -164,20 +164,20 @@
 
 // These constructors are for convenience of tests to construct these geometries
 // from integers.
-inline LogicalOffset::LogicalOffset(int inline_offset, int block_offset)
+constexpr LogicalOffset::LogicalOffset(int inline_offset, int block_offset)
     : inline_offset(inline_offset), block_offset(block_offset) {}
-inline LogicalSize::LogicalSize(int inline_size, int block_size)
+constexpr LogicalSize::LogicalSize(int inline_size, int block_size)
     : inline_size(inline_size), block_size(block_size) {}
-inline LogicalRect::LogicalRect(int inline_offset,
-                                int block_offset,
-                                int inline_size,
-                                int block_size)
+constexpr LogicalRect::LogicalRect(int inline_offset,
+                                   int block_offset,
+                                   int inline_size,
+                                   int block_size)
     : offset(inline_offset, block_offset), size(inline_size, block_size) {}
-inline PhysicalOffset::PhysicalOffset(int left, int top)
+constexpr PhysicalOffset::PhysicalOffset(int left, int top)
     : left(left), top(top) {}
-inline PhysicalSize::PhysicalSize(int width, int height)
+constexpr PhysicalSize::PhysicalSize(int width, int height)
     : width(width), height(height) {}
-inline PhysicalRect::PhysicalRect(int left, int top, int width, int height)
+constexpr PhysicalRect::PhysicalRect(int left, int top, int width, int height)
     : offset(left, top), size(width, height) {}
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/DEPS b/third_party/blink/renderer/modules/DEPS
index 49f8e82..28b93d1 100644
--- a/third_party/blink/renderer/modules/DEPS
+++ b/third_party/blink/renderer/modules/DEPS
@@ -56,6 +56,10 @@
         "+base/allocator/partition_allocator/partition_root.h",
     ],
     ".*_stream_wrapper.cc": [
-        "+net/base/ip_endpoint.h"
-    ]
+        "+net/base/ip_endpoint.h",
+    ],
+    ".*socket.cc": [
+        "+base/barrier_callback.h",
+        "+base/functional/identity.h",
+    ],
 }
diff --git a/third_party/blink/renderer/modules/direct_sockets/socket.cc b/third_party/blink/renderer/modules/direct_sockets/socket.cc
index 8264924b..5f7af74 100644
--- a/third_party/blink/renderer/modules/direct_sockets/socket.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/socket.cc
@@ -10,6 +10,8 @@
 #include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -59,16 +61,38 @@
   return ScriptPromise(script_state, closed_.Get(script_state->GetIsolate()));
 }
 
-ScriptPromise Socket::close(ScriptState* script_state,
-                            const SocketCloseOptions* options,
-                            ExceptionState& exception_state) {
-  Close(options, exception_state);
-  if (exception_state.HadException()) {
+ScriptPromise Socket::close(ScriptState*, ExceptionState& exception_state) {
+  if (!Initialized()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                      "Socket is not properly initialized.");
     return ScriptPromise();
-  } else {
-    DCHECK(Closed());
-    return ScriptPromise::CastUndefined(script_state);
   }
+
+  if (Closed()) {
+    return closed(script_state_);
+  }
+
+  if (readable_stream_wrapper_->Locked() ||
+      writable_stream_wrapper_->Locked()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                      "Close called on locked streams.");
+    return ScriptPromise();
+  }
+
+  auto* reason = MakeGarbageCollected<DOMException>(
+      DOMExceptionCode::kAbortError, "Stream closed.");
+
+  auto readable_cancel = readable_stream_wrapper_->Readable()->cancel(
+      script_state_, ScriptValue::From(script_state_, reason), exception_state);
+  DCHECK(!exception_state.HadException()) << exception_state.Message();
+  readable_cancel.MarkAsHandled();
+
+  auto writable_abort = writable_stream_wrapper_->Writable()->abort(
+      script_state_, ScriptValue::From(script_state_, reason), exception_state);
+  DCHECK(!exception_state.HadException()) << exception_state.Message();
+  writable_abort.MarkAsHandled();
+
+  return closed(script_state_);
 }
 
 Socket::Socket(ScriptState* script_state)
diff --git a/third_party/blink/renderer/modules/direct_sockets/socket.h b/third_party/blink/renderer/modules/direct_sockets/socket.h
index db22ca71..a3d1f01b 100644
--- a/third_party/blink/renderer/modules/direct_sockets/socket.h
+++ b/third_party/blink/renderer/modules/direct_sockets/socket.h
@@ -19,7 +19,6 @@
 
 namespace blink {
 
-class SocketCloseOptions;
 class ScriptPromise;
 class ExceptionState;
 
@@ -29,14 +28,17 @@
   // IDL definitions
   virtual ScriptPromise connection(ScriptState*) const;
   virtual ScriptPromise closed(ScriptState*) const;
-  virtual ScriptPromise close(ScriptState*,
-                              const SocketCloseOptions*,
-                              ExceptionState&);
+  // Calls readable.cancel() and writable.abort() given that they're not locked
+  // or rejects otherwise.
+  virtual ScriptPromise close(ScriptState*, ExceptionState&);
 
  public:
   explicit Socket(ScriptState*);
   ~Socket() override;
 
+  Socket(const Socket&) = delete;
+  Socket& operator=(const Socket&) = delete;
+
   static bool CheckContextAndPermissions(ScriptState*, ExceptionState&);
   static DOMException* CreateDOMExceptionFromNetErrorCode(int32_t net_error);
 
@@ -47,8 +49,6 @@
   // Connects DirectSocketsServiceMojoRemote.
   void ConnectService();
 
-  virtual void Close(const SocketCloseOptions*, ExceptionState&) = 0;
-
   bool Closed() const;
   bool Initialized() const;
   bool HasPendingActivity() const;
@@ -62,6 +62,7 @@
   void Trace(Visitor*) const override;
 
  protected:
+  // Handler for |service_| errors.
   virtual void OnServiceConnectionError() = 0;
 
   const Member<ScriptState> script_state_;
diff --git a/third_party/blink/renderer/modules/direct_sockets/socket_options.idl b/third_party/blink/renderer/modules/direct_sockets/socket_options.idl
index a8182798..e7dd8c56 100644
--- a/third_party/blink/renderer/modules/direct_sockets/socket_options.idl
+++ b/third_party/blink/renderer/modules/direct_sockets/socket_options.idl
@@ -20,8 +20,4 @@
 
 dictionary UDPSocketOptions : SocketOptions {
   [EnforceRange] unsigned short readableStreamBufferSize;
-};
-
-dictionary SocketCloseOptions {
-  boolean force;
 };
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/direct_sockets/stream_wrapper.cc b/third_party/blink/renderer/modules/direct_sockets/stream_wrapper.cc
index b664398..2ab52eb 100644
--- a/third_party/blink/renderer/modules/direct_sockets/stream_wrapper.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/stream_wrapper.cc
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
+#include "third_party/blink/renderer/core/dom/abort_signal.h"
 #include "third_party/blink/renderer/core/dom/events/event_target_impl.h"
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
 #include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
@@ -11,6 +13,7 @@
 #include "third_party/blink/renderer/core/streams/writable_stream.h"
 #include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 
 namespace blink {
@@ -20,14 +23,6 @@
 
 StreamWrapper::~StreamWrapper() = default;
 
-ScriptValue StreamWrapper::CreateException(ScriptState* script_state,
-                                           DOMExceptionCode code,
-                                           const String& message) {
-  return ScriptValue(script_state->GetIsolate(),
-                     V8ThrowDOMException::CreateOrEmpty(
-                         script_state->GetIsolate(), code, message));
-}
-
 void StreamWrapper::Trace(Visitor* visitor) const {
   visitor->Trace(script_state_);
 }
@@ -100,6 +95,13 @@
   return ScriptPromise::CastUndefined(script_state);
 }
 
+ScriptPromise ReadableStreamWrapper::UnderlyingSource::Cancel(
+    ScriptState* script_state,
+    ScriptValue) {
+  readable_stream_wrapper_->CloseStream();
+  return ScriptPromise::CastUndefined(script_state);
+}
+
 void ReadableStreamWrapper::UnderlyingSource::Trace(Visitor* visitor) const {
   visitor->Trace(readable_stream_wrapper_);
   UnderlyingSourceBase::Trace(visitor);
@@ -113,6 +115,24 @@
     ScriptState* script_state,
     WritableStreamDefaultController*,
     ExceptionState&) {
+  class AbortAlgorithm final : public AbortSignal::Algorithm {
+   public:
+    explicit AbortAlgorithm(WritableStreamWrapper* writable_stream_wrapper)
+        : writable_stream_wrapper_(writable_stream_wrapper) {}
+
+    void Run() override { writable_stream_wrapper_->OnAbortSignal(); }
+
+    void Trace(Visitor* visitor) const override {
+      visitor->Trace(writable_stream_wrapper_);
+      Algorithm::Trace(visitor);
+    }
+
+   private:
+    Member<WritableStreamWrapper> writable_stream_wrapper_;
+  };
+
+  Controller()->signal()->AddAlgorithm(
+      MakeGarbageCollected<AbortAlgorithm>(GetWritableStreamWrapper()));
   return ScriptPromise::CastUndefined(script_state);
 }
 
@@ -124,9 +144,16 @@
   return writable_stream_wrapper_->Write(chunk, exception_state);
 }
 
+ScriptPromise WritableStreamWrapper::UnderlyingSink::close(
+    ScriptState* script_state,
+    ExceptionState&) {
+  writable_stream_wrapper_->CloseStream();
+  return ScriptPromise::CastUndefined(script_state);
+}
+
 ScriptPromise WritableStreamWrapper::UnderlyingSink::abort(
     ScriptState* script_state,
-    ScriptValue reason,
+    ScriptValue,
     ExceptionState& exception_state) {
   return close(script_state, exception_state);
 }
diff --git a/third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h b/third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h
index 4531474..2b1748e9 100644
--- a/third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h
+++ b/third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h
@@ -37,28 +37,26 @@
 
 class MODULES_EXPORT StreamWrapper : public GarbageCollectedMixin {
  public:
+  using CloseOnceCallback = base::OnceCallback<void(bool error)>;
+
   enum class State { kOpen, kAborted, kClosed };
 
   explicit StreamWrapper(ScriptState*);
-  virtual ~StreamWrapper() = 0;
+  virtual ~StreamWrapper();
 
   State GetState() const { return state_; }
   ScriptState* GetScriptState() const { return script_state_; }
 
   virtual bool Locked() const = 0;
 
-  virtual void CloseStream(bool error) = 0;
-  virtual void CloseSocket(bool error) { NOTIMPLEMENTED(); }
+  virtual void CloseStream() = 0;
+  virtual void ErrorStream(int32_t error_code) = 0;
 
   void Trace(Visitor* visitor) const override;
 
  protected:
   void SetState(State state) { state_ = state; }
 
-  static ScriptValue CreateException(ScriptState*,
-                                     DOMExceptionCode,
-                                     const String& message);
-
  private:
   const Member<ScriptState> script_state_;
   State state_ = State::kOpen;
@@ -98,18 +96,24 @@
   WritableStream* Writable() const { return writable_; }
   bool Locked() const override;
 
-  // Implements UnderlyingSink::write(...)
-  virtual ScriptPromise Write(ScriptValue, ExceptionState&) = 0;
-
   // Checks whether there's a write in progress.
   virtual bool HasPendingWrite() const { return false; }
-
   void Trace(Visitor*) const override;
 
  protected:
   class UnderlyingSink;
   void InitSinkAndWritable(UnderlyingSink*, size_t high_water_mark);
 
+  // Intercepts signal from WritableStream::abort(...) and processes it out
+  // of order (without waiting for queued writes to complete first).
+  // Note that UnderlyingSink::abort(...) will be called right afterwards --
+  // therefore normally it's sufficient to reject the pending promise (and the
+  // rest will be handled by the controller).
+  virtual void OnAbortSignal() = 0;
+
+  // Implements UnderlyingSink::write(...)
+  virtual ScriptPromise Write(ScriptValue, ExceptionState&) = 0;
+
   WritableStreamDefaultController* Controller() const;
 
  private:
@@ -123,7 +127,7 @@
 
   ScriptPromise Start(ScriptState*) override;
   ScriptPromise pull(ScriptState*) override;
-  ScriptPromise Cancel(ScriptState*, ScriptValue reason) override = 0;
+  ScriptPromise Cancel(ScriptState*, ScriptValue reason) override;
 
   void Trace(Visitor*) const override;
 
@@ -148,7 +152,7 @@
                       ScriptValue chunk,
                       WritableStreamDefaultController*,
                       ExceptionState&) override;
-  ScriptPromise close(ScriptState*, ExceptionState&) override = 0;
+  ScriptPromise close(ScriptState*, ExceptionState&) override;
   ScriptPromise abort(ScriptState*,
                       ScriptValue reason,
                       ExceptionState&) override;
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.cc b/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.cc
index e571b5b4..de03ad1 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.cc
@@ -4,10 +4,15 @@
 
 #include "third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.h"
 
+#include "base/check.h"
 #include "base/containers/span.h"
+#include "base/notreached.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
 #include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
 #include "third_party/blink/renderer/core/streams/underlying_source_base.h"
@@ -23,29 +28,9 @@
 
 namespace blink {
 
-// An implementation of UnderlyingSourceBase that forwards all operations to the
-// TCPReadableStreamWrapper object that created it.
-class TCPReadableStreamWrapper::TCPUnderlyingSource final
-    : public ReadableStreamWrapper::UnderlyingSource {
- public:
-  TCPUnderlyingSource(ScriptState* script_state,
-                      TCPReadableStreamWrapper* readable_stream_wrapper)
-      : ReadableStreamWrapper::UnderlyingSource(script_state,
-                                                readable_stream_wrapper) {}
-
-  ScriptPromise Cancel(ScriptState* script_state, ScriptValue reason) override {
-    GetReadableStreamWrapper()->CloseSocket(/*error=*/false);
-    return ScriptPromise::CastUndefined(script_state);
-  }
-
-  void Trace(Visitor* visitor) const override {
-    ReadableStreamWrapper::UnderlyingSource::Trace(visitor);
-  }
-};
-
 TCPReadableStreamWrapper::TCPReadableStreamWrapper(
     ScriptState* script_state,
-    base::OnceCallback<void(bool)> on_close,
+    CloseOnceCallback on_close,
     mojo::ScopedDataPipeConsumerHandle handle)
     : ReadableStreamWrapper(script_state),
       on_close_(std::move(on_close)),
@@ -57,34 +42,26 @@
       MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
       WTF::BindRepeating(&TCPReadableStreamWrapper::OnHandleReady,
                          WrapWeakPersistent(this)));
+
   close_watcher_.Watch(
       data_pipe_.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
       MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
-      WTF::BindRepeating(&TCPReadableStreamWrapper::OnPeerClosed,
+      WTF::BindRepeating(&TCPReadableStreamWrapper::OnHandleReset,
                          WrapWeakPersistent(this)));
 
-  // Set queuing strategy of default behavior with a high water mark of 1.
+  // Set queuing strategy of default behavior with a high water mark of 0.
   InitSourceAndReadable(
-      /*source=*/MakeGarbageCollected<TCPUnderlyingSource>(script_state, this),
-      /*high_water_mark=*/1);
-}
-
-void TCPReadableStreamWrapper::CloseSocket(bool error) {
-  if (on_close_) {
-    std::move(on_close_).Run(error);
-  }
-  DCHECK_NE(GetState(), State::kOpen);
+      /*source=*/MakeGarbageCollected<UnderlyingSource>(script_state, this),
+      /*high_water_mark=*/0);
 }
 
 void TCPReadableStreamWrapper::Trace(Visitor* visitor) const {
+  visitor->Trace(pending_exception_);
   ReadableStreamWrapper::Trace(visitor);
 }
 
 void TCPReadableStreamWrapper::OnHandleReady(MojoResult result,
                                              const mojo::HandleSignalsState&) {
-  DVLOG(1) << "TCPReadableStreamWrapper::OnHandleReady() this=" << this
-           << " result=" << result;
-
   switch (result) {
     case MOJO_RESULT_OK:
       Pull();
@@ -99,31 +76,11 @@
   }
 }
 
-void TCPReadableStreamWrapper::OnPeerClosed(MojoResult result,
-                                            const mojo::HandleSignalsState&) {
-  DVLOG(1) << "TCPReadableStreamWrapper::OnPeerClosed() this=" << this
-           << " result=" << result;
-
-  DCHECK_EQ(result, MOJO_RESULT_OK);
-  DCHECK_EQ(GetState(), State::kOpen);
-
-  CloseSocket(/*error=*/true);
-}
-
 void TCPReadableStreamWrapper::Pull() {
   if (!GetScriptState()->ContextIsValid())
     return;
 
-  DVLOG(1) << "TCPReadableStreamWrapper::Pull() this=" << this
-           << " in_two_phase_read_=" << in_two_phase_read_
-           << " read_pending_=" << read_pending_;
-
-  // Protect against re-entrancy.
-  if (in_two_phase_read_) {
-    read_pending_ = true;
-    return;
-  }
-  DCHECK(!read_pending_);
+  DCHECK(data_pipe_);
 
   const void* buffer = nullptr;
   uint32_t buffer_num_bytes = 0;
@@ -131,19 +88,12 @@
                                           MOJO_BEGIN_READ_DATA_FLAG_NONE);
   switch (result) {
     case MOJO_RESULT_OK: {
-      in_two_phase_read_ = true;
-      // Push() may re-enter this method via TCPUnderlyingSource::pull().
       Push(base::make_span(static_cast<const uint8_t*>(buffer),
                            buffer_num_bytes),
            {});
-      data_pipe_->EndReadData(buffer_num_bytes);
-      in_two_phase_read_ = false;
-      if (read_pending_) {
-        read_pending_ = false;
-        // pull() will not be called when another pull() is in progress, so the
-        // maximum recursion depth is 1.
-        Pull();
-      }
+      result = data_pipe_->EndReadData(buffer_num_bytes);
+      DCHECK_EQ(result, MOJO_RESULT_OK);
+
       break;
     }
 
@@ -152,7 +102,7 @@
       return;
 
     case MOJO_RESULT_FAILED_PRECONDITION:
-      // This will be handled by close_watcher_.
+      // Will be handled by |close_watcher_|.
       return;
 
     default:
@@ -169,37 +119,99 @@
   return true;
 }
 
-void TCPReadableStreamWrapper::CloseStream(bool error) {
+void TCPReadableStreamWrapper::CloseStream() {
   if (GetState() != State::kOpen) {
     return;
   }
-  SetState(error ? State::kAborted : State::kClosed);
+  SetState(State::kClosed);
 
-  if (error) {
-    ScriptState::Scope scope(GetScriptState());
-    Controller()->Error(CreateException(
-        GetScriptState(), DOMExceptionCode::kNetworkError, "Error."));
-  } else {
-    Controller()->Close();
+  // If close request came from reader.cancel(), the internal state of the
+  // stream is already set to closed. Therefore we don't have to do anything
+  // with the controller.
+  if (!data_pipe_) {
+    // This is a rare case indicating that reader.cancel() interrupted the
+    // OnReadError() call where the pipe already got reset, but the
+    // corresponding IPC hasn't yet arrived. The simplest way is to abort
+    // CloseStream by setting state to Open and allow the IPC to finish the
+    // job.
+    SetState(State::kOpen);
+    return;
   }
 
-  on_close_.Reset();
-
   ResetPipe();
+  std::move(on_close_).Run(/*error=*/false);
+  return;
+}
+
+void TCPReadableStreamWrapper::ErrorStream(int32_t error_code) {
+  if (GetState() != State::kOpen) {
+    return;
+  }
+  graceful_peer_shutdown_ = (error_code == net::OK);
+
+  if (graceful_peer_shutdown_) {
+    SetState(State::kClosed);
+    if (!data_pipe_) {
+      Controller()->Close();
+      std::move(on_close_).Run(/*error=*/false);
+    }
+    return;
+  }
+
+  SetState(State::kAborted);
+
+  auto* exception = MakeGarbageCollected<DOMException>(
+      DOMExceptionCode::kNetworkError, String{"Stream aborted by the remote: " +
+                                              net::ErrorToString(error_code)});
+
+  if (data_pipe_) {
+    pending_exception_ = exception;
+    return;
+  }
+
+  Controller()->Error(exception);
+  std::move(on_close_).Run(/*error=*/true);
 }
 
 void TCPReadableStreamWrapper::ResetPipe() {
-  DVLOG(1) << "TCPReadableStreamWrapper::ResetPipe() this=" << this;
-
   read_watcher_.Cancel();
   close_watcher_.Cancel();
   data_pipe_.reset();
 }
 
 void TCPReadableStreamWrapper::Dispose() {
-  DVLOG(1) << "TCPReadableStreamWrapper::Dispose() this=" << this;
+  ResetPipe();
+}
+
+void TCPReadableStreamWrapper::OnHandleReset(MojoResult result,
+                                             const mojo::HandleSignalsState&) {
+#if DCHECK_IS_ON()
+  DCHECK_EQ(result, MOJO_RESULT_OK);
+  DCHECK(data_pipe_);
+  DCHECK(on_close_);
+  DCHECK(!(pending_exception_ && graceful_peer_shutdown_));
+  if (pending_exception_ || graceful_peer_shutdown_) {
+    DCHECK_NE(GetState(), State::kOpen);
+  } else {
+    DCHECK_EQ(GetState(), State::kOpen);
+  }
+#endif
 
   ResetPipe();
+
+  if (pending_exception_) {
+    Controller()->Error(pending_exception_);
+
+    SetState(State::kAborted);
+    std::move(on_close_).Run(/*error=*/true);
+
+    pending_exception_ = nullptr;
+  } else if (graceful_peer_shutdown_) {
+    Controller()->Close();
+
+    SetState(State::kClosed);
+    std::move(on_close_).Run(/*error=*/false);
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.h b/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.h
index 00c794fe..6a012df4 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.h
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.h
@@ -7,13 +7,16 @@
 
 #include "base/callback.h"
 #include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/handle_signals_state.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/heap/prefinalizer.h"
 #include "third_party/blink/renderer/platform/heap/visitor.h"
 
@@ -27,53 +30,44 @@
 
  public:
   TCPReadableStreamWrapper(ScriptState*,
-                           base::OnceCallback<void(bool)> on_close,
+                           CloseOnceCallback,
                            mojo::ScopedDataPipeConsumerHandle);
 
-  void CloseSocket(bool error) override;
-  void CloseStream(bool error) override;
-
+  // ReadableStreamWrapper:
   void Pull() override;
   bool Push(base::span<const uint8_t> data,
             const absl::optional<net::IPEndPoint>&) override;
-
+  void CloseStream() override;
+  void ErrorStream(int32_t error_code) override;
   void Trace(Visitor*) const override;
 
  private:
-  class TCPUnderlyingSource;
-
   // Called when |data_pipe_| becomes readable or errored.
   void OnHandleReady(MojoResult, const mojo::HandleSignalsState&);
 
-  // Called when |data_pipe_| is closed.
-  void OnPeerClosed(MojoResult, const mojo::HandleSignalsState&);
+  // Called when |data_pipe_| gets reset.
+  void OnHandleReset(MojoResult, const mojo::HandleSignalsState&);
 
-  // Errors or closes |readable_| and resets |data_pipe_|.
-  void CloseOrErrorStreamAbortAndReset(bool error);
-
-  // Resets |data_pipe_| and clears the watchers.
+  // Resets |data_pipe_| and clears the watcher.
   void ResetPipe();
 
   // Prepares the object for destruction.
   void Dispose();
 
-  base::OnceCallback<void(bool)> on_close_;
+  CloseOnceCallback on_close_;
 
   mojo::ScopedDataPipeConsumerHandle data_pipe_;
 
   // Only armed when we need to read something.
   mojo::SimpleWatcher read_watcher_;
 
-  // Always armed to detect close.
+  // Always armed to detect pipe close.
   mojo::SimpleWatcher close_watcher_;
 
-  // Indicates if we are currently performing a two-phase read from the pipe and
-  // so can't start another read.
-  bool in_two_phase_read_ = false;
+  // Indicates whether peer closed gracefully (EOF).
+  bool graceful_peer_shutdown_ = false;
 
-  // Indicates if we need to perform another read after the current one
-  // completes.
-  bool read_pending_ = false;
+  Member<DOMException> pending_exception_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper_unittest.cc b/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper_unittest.cc
index e52c816..357ed7a 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper_unittest.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper_unittest.cc
@@ -4,12 +4,16 @@
 
 #include "third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.h"
 
+#include "base/callback_helpers.h"
 #include "base/test/mock_callback.h"
+#include "net/base/net_errors.h"
 #include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
+#include "third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
@@ -18,7 +22,6 @@
 namespace {
 
 using ::testing::ElementsAre;
-using ::testing::StrictMock;
 
 // The purpose of this class is to ensure that the data pipe is reset before the
 // V8TestingScope is destroyed, so that the TCPReadableStreamWrapper object
@@ -51,11 +54,13 @@
     auto* script_state = scope.GetScriptState();
     stream_wrapper_ = MakeGarbageCollected<TCPReadableStreamWrapper>(
         script_state,
-        base::BindOnce(&StreamCreator::Close, base::Unretained(this)),
+        WTF::Bind(&StreamCreator::Close, WrapWeakPersistent(this)),
         std::move(data_pipe_consumer));
     return stream_wrapper_;
   }
 
+  void ResetPipe() { data_pipe_producer_.reset(); }
+
   void WriteToPipe(Vector<uint8_t> data) {
     uint32_t num_bytes = data.size();
     EXPECT_EQ(data_pipe_producer_->WriteData(data.data(), &num_bytes,
@@ -64,8 +69,6 @@
     EXPECT_EQ(num_bytes, data.size());
   }
 
-  void ClosePipe() { data_pipe_producer_.reset(); }
-
   // Copies the contents of a v8::Value containing a Uint8Array to a Vector.
   static Vector<uint8_t> ToVector(V8TestingScope& scope,
                                   v8::Local<v8::Value> v8value) {
@@ -121,11 +124,14 @@
     return ret;
   }
 
-  void Close(bool error) { stream_wrapper_->CloseStream(error); }
+  bool CloseCalledWith(bool error) const { return close_called_with_ == error; }
 
   void Trace(Visitor* visitor) const { visitor->Trace(stream_wrapper_); }
 
  private:
+  void Close(bool error) { close_called_with_ = error; }
+
+  absl::optional<bool> close_called_with_;
   mojo::ScopedDataPipeProducerHandle data_pipe_producer_;
   Member<TCPReadableStreamWrapper> stream_wrapper_;
 };
@@ -182,7 +188,14 @@
   EXPECT_THAT(result.value, ElementsAre('A'));
 }
 
-TEST(TCPReadableStreamWrapperTest, TriggerOnAborted) {
+class TCPReadableStreamWrapperCloseTest : public testing::TestWithParam<bool> {
+};
+
+INSTANTIATE_TEST_SUITE_P(/**/,
+                         TCPReadableStreamWrapperCloseTest,
+                         testing::Bool());
+
+TEST_P(TCPReadableStreamWrapperCloseTest, TriggerClose) {
   V8TestingScope scope;
 
   auto* stream_creator = MakeGarbageCollected<StreamCreator>();
@@ -197,13 +210,120 @@
 
   test::RunPendingTasks();
   stream_creator->WriteToPipe({'A'});
-  // Trigger OnAborted() on purpose.
-  stream_creator->ClosePipe();
+
+  bool graceful = GetParam();
+
+  // 1. OnReadError(...) is called.
+  tcp_readable_stream_wrapper->ErrorStream(graceful ? net::OK
+                                                    : net::ERR_UNEXPECTED);
+
+  // 2. pipe reset event arrives.
+  stream_creator->ResetPipe();
+  test::RunPendingTasks();
+
   tester.WaitUntilSettled();
 
   ASSERT_TRUE(tester.IsFulfilled());
   ASSERT_EQ(tcp_readable_stream_wrapper->GetState(),
-            StreamWrapper::State::kAborted);
+            graceful ? StreamWrapper::State::kClosed
+                     : StreamWrapper::State::kAborted);
+}
+
+TEST_P(TCPReadableStreamWrapperCloseTest, TriggerCloseInReverseOrder) {
+  V8TestingScope scope;
+
+  auto* stream_creator = MakeGarbageCollected<StreamCreator>();
+  auto* tcp_readable_stream_wrapper = stream_creator->Create(scope);
+
+  auto* script_state = scope.GetScriptState();
+  auto* reader =
+      tcp_readable_stream_wrapper->Readable()->GetDefaultReaderForTesting(
+          script_state, ASSERT_NO_EXCEPTION);
+  ScriptPromise read_promise = reader->read(script_state, ASSERT_NO_EXCEPTION);
+  ScriptPromiseTester tester(script_state, read_promise);
+
+  test::RunPendingTasks();
+  stream_creator->WriteToPipe({'A'});
+
+  bool graceful = GetParam();
+
+  // 1. pipe reset event arrives.
+  stream_creator->ResetPipe();
+  test::RunPendingTasks();
+
+  // 2. OnReadError(...) is called.
+  tcp_readable_stream_wrapper->ErrorStream(graceful ? net::OK
+                                                    : net::ERR_UNEXPECTED);
+  tester.WaitUntilSettled();
+
+  ASSERT_TRUE(stream_creator->CloseCalledWith(!graceful));
+
+  ASSERT_TRUE(tester.IsFulfilled());
+  ASSERT_EQ(tcp_readable_stream_wrapper->GetState(),
+            graceful ? StreamWrapper::State::kClosed
+                     : StreamWrapper::State::kAborted);
+}
+
+TEST_P(TCPReadableStreamWrapperCloseTest, ErrorCancelReset) {
+  V8TestingScope scope;
+
+  auto* stream_creator = MakeGarbageCollected<StreamCreator>();
+  auto* tcp_readable_stream_wrapper = stream_creator->Create(scope);
+
+  auto* script_state = scope.GetScriptState();
+
+  bool graceful = GetParam();
+
+  // 1. OnReadError(...) is called.
+  tcp_readable_stream_wrapper->ErrorStream(graceful ? net::OK
+                                                    : net::ERR_UNEXPECTED);
+
+  // 2. readable.cancel() is called.
+  auto tester = ScriptPromiseTester(
+      script_state, tcp_readable_stream_wrapper->Readable()->cancel(
+                        script_state, ASSERT_NO_EXCEPTION));
+  tester.WaitUntilSettled();
+  ASSERT_TRUE(tester.IsFulfilled());
+
+  // 3. pipe reset event arrives.
+  stream_creator->ResetPipe();
+  test::RunPendingTasks();
+
+  ASSERT_EQ(tcp_readable_stream_wrapper->GetState(),
+            graceful ? StreamWrapper::State::kClosed
+                     : StreamWrapper::State::kAborted);
+}
+
+TEST_P(TCPReadableStreamWrapperCloseTest, ResetCancelError) {
+  V8TestingScope scope;
+
+  auto* stream_creator = MakeGarbageCollected<StreamCreator>();
+  auto* tcp_readable_stream_wrapper = stream_creator->Create(scope);
+
+  auto* script_state = scope.GetScriptState();
+
+  bool graceful = GetParam();
+
+  // 1. pipe reset event arrives.
+  stream_creator->ResetPipe();
+  test::RunPendingTasks();
+
+  // 2. readable.cancel() is called.
+  auto tester = ScriptPromiseTester(
+      script_state, tcp_readable_stream_wrapper->Readable()->cancel(
+                        script_state, ASSERT_NO_EXCEPTION));
+  tester.WaitUntilSettled();
+  ASSERT_TRUE(tester.IsFulfilled());
+
+  // 3. OnReadError(...) is called.
+  tcp_readable_stream_wrapper->ErrorStream(graceful ? net::OK
+                                                    : net::ERR_UNEXPECTED);
+
+  stream_creator->ResetPipe();
+
+  ASSERT_EQ(tcp_readable_stream_wrapper->GetState(),
+            graceful ? StreamWrapper::State::kClosed
+                     : StreamWrapper::State::kAborted);
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_socket.cc b/third_party/blink/renderer/modules/direct_sockets/tcp_socket.cc
index 358c9609..d66d081 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_socket.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_socket.cc
@@ -4,12 +4,16 @@
 
 #include "third_party/blink/renderer/modules/direct_sockets/tcp_socket.h"
 
+#include "base/barrier_callback.h"
+#include "base/functional/identity.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/notreached.h"
+#include "base/ranges/algorithm.h"
 #include "net/base/net_errors.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_socket_close_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_tcp_socket_connection.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_tcp_socket_options.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -18,10 +22,13 @@
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
 #include "third_party/blink/renderer/core/streams/writable_stream.h"
 #include "third_party/blink/renderer/modules/direct_sockets/direct_sockets_service_mojo_remote.h"
+#include "third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 
@@ -159,14 +166,14 @@
                      mojo::ScopedDataPipeConsumerHandle receive_stream,
                      mojo::ScopedDataPipeProducerHandle send_stream) {
   if (result == net::OK && peer_addr) {
+    auto close_callback = base::BarrierCallback<bool>(
+        /*num_callbacks=*/2,
+        WTF::Bind(&TCPSocket::OnBothStreamsClosed, WrapWeakPersistent(this)));
+
     readable_stream_wrapper_ = MakeGarbageCollected<TCPReadableStreamWrapper>(
-        script_state_,
-        WTF::Bind(&TCPSocket::CloseInternal, WrapWeakPersistent(this)),
-        std::move(receive_stream));
+        script_state_, close_callback, std::move(receive_stream));
     writable_stream_wrapper_ = MakeGarbageCollected<TCPWritableStreamWrapper>(
-        script_state_,
-        WTF::Bind(&TCPSocket::CloseInternal, WrapWeakPersistent(this)),
-        std::move(send_stream));
+        script_state_, close_callback, std::move(send_stream));
 
     auto* connection = TCPSocketConnection::Create();
 
@@ -212,9 +219,12 @@
 }
 
 void TCPSocket::OnSocketConnectionError() {
-  if (Initialized()) {
-    CloseInternal(/*error=*/true);
+  if (!Initialized()) {
+    return;
   }
+
+  readable_stream_wrapper_->ErrorStream(net::ERR_CONNECTION_ABORTED);
+  writable_stream_wrapper_->ErrorStream(net::ERR_CONNECTION_ABORTED);
 }
 
 void TCPSocket::OnServiceConnectionError() {
@@ -226,19 +236,13 @@
 }
 
 void TCPSocket::OnReadError(int32_t net_error) {
-  if (net_error > 0 || net_error == net::Error::ERR_IO_PENDING) {
-    return;
-  }
-
-  readable_stream_wrapper_->CloseStream(/*error=*/true);
+  // |net_error| equal to net::OK means EOF -- in this case the
+  // stream is not really errored but rather closed gracefully.
+  readable_stream_wrapper_->ErrorStream(net_error);
 }
 
 void TCPSocket::OnWriteError(int32_t net_error) {
-  if (net_error > 0 || net_error == net::Error::ERR_IO_PENDING) {
-    return;
-  }
-
-  writable_stream_wrapper_->CloseStream(/*error=*/true);
+  writable_stream_wrapper_->ErrorStream(net_error);
 }
 
 void TCPSocket::Trace(Visitor* visitor) const {
@@ -254,42 +258,16 @@
   return Socket::HasPendingActivity();
 }
 
-void TCPSocket::Close(const SocketCloseOptions* options,
-                      ExceptionState& exception_state) {
-  if (!Initialized()) {
-    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
-                                      "Socket is not properly initialized.");
-    return;
-  }
+void TCPSocket::OnBothStreamsClosed(std::vector<bool> args) {
+  DCHECK_EQ(args.size(), 2U);
+  // At least one callback was invoked with error = true.
+  bool error = base::ranges::any_of(args, base::identity());
 
-  if (Closed()) {
-    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
-                                      "Socket is already closed or errored.");
-    return;
-  }
-
-  if (!options->hasForce() || !options->force()) {
-    if (readable_stream_wrapper_->Locked() ||
-        writable_stream_wrapper_->Locked()) {
-      exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
-                                        "Close called on locked streams.");
-      return;
-    }
-  }
-
-  CloseInternal(/*error=*/false);
-  DCHECK(Closed());
-}
-
-void TCPSocket::CloseInternal(bool error) {
   tcp_socket_.reset();
   socket_observer_.reset();
 
   CloseServiceAndResetFeatureHandle();
   ResolveOrRejectClosed(error);
-
-  readable_stream_wrapper_->CloseStream(error);
-  writable_stream_wrapper_->CloseStream(error);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_socket.h b/third_party/blink/renderer/modules/direct_sockets/tcp_socket.h
index 2110a0d4..161bbc0 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_socket.h
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_socket.h
@@ -56,26 +56,10 @@
                            const TCPSocketOptions*,
                            ExceptionState&);
 
-  // Socket:
-  ScriptPromise connection(ScriptState* script_state) const override {
-    return Socket::connection(script_state);
-  }
-  ScriptPromise closed(ScriptState* script_state) const override {
-    return Socket::closed(script_state);
-  }
-  ScriptPromise close(ScriptState* script_state,
-                      const SocketCloseOptions* options,
-                      ExceptionState& exception_state) override {
-    return Socket::close(script_state, options, exception_state);
-  }
-
  public:
   explicit TCPSocket(ScriptState*);
   ~TCPSocket() override;
 
-  TCPSocket(const TCPSocket&) = delete;
-  TCPSocket& operator=(const TCPSocket&) = delete;
-
   // Validates options and calls
   // DirectSocketsServiceMojoRemote::OpenTcpSocket(...) with Init(...) passed as
   // callback.
@@ -111,15 +95,14 @@
   void OnReadError(int32_t net_error) override;
   void OnWriteError(int32_t net_error) override;
 
-  void Close(const SocketCloseOptions*, ExceptionState&) override;
-  void CloseInternal(bool error);
+  void OnBothStreamsClosed(std::vector<bool> args);
 
   HeapMojoRemote<network::mojom::blink::TCPConnectedSocket> tcp_socket_;
   HeapMojoReceiver<network::mojom::blink::SocketObserver, TCPSocket>
       socket_observer_;
 
   FRIEND_TEST_ALL_PREFIXES(TCPSocketTest, OnSocketObserverConnectionError);
-  FRIEND_TEST_ALL_PREFIXES(TCPSocketTest, OnReadError);
+  FRIEND_TEST_ALL_PREFIXES(TCPSocketCloseTest, OnErrorOrClose);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_socket.idl b/third_party/blink/renderer/modules/direct_sockets/tcp_socket.idl
index 4b9d796b..b86c511 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_socket.idl
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_socket.idl
@@ -17,5 +17,5 @@
   [CallWith=ScriptState] readonly attribute Promise<void> closed;
 
   [CallWith=ScriptState, RaisesException, Measure]
-  Promise<void> close(optional SocketCloseOptions options = {});
+  Promise<void> close();
 };
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_socket_unittest.cc b/third_party/blink/renderer/modules/direct_sockets/tcp_socket_unittest.cc
index 1721384f..b662a52 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_socket_unittest.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_socket_unittest.cc
@@ -11,10 +11,13 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_socket_close_options.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/streams/readable_stream.h"
+#include "third_party/blink/renderer/core/streams/writable_stream.h"
+#include "third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h"
 #include "third_party/blink/renderer/modules/direct_sockets/tcp_readable_stream_wrapper.h"
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
@@ -41,8 +44,7 @@
   auto* tcp_socket = MakeGarbageCollected<TCPSocket>(script_state);
 
   auto close_promise =
-      tcp_socket->close(script_state, blink::SocketCloseOptions::Create(),
-                        scope.GetExceptionState());
+      tcp_socket->close(script_state, scope.GetExceptionState());
 
   ASSERT_TRUE(scope.GetExceptionState().HadException());
   EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
@@ -66,8 +68,7 @@
   ASSERT_TRUE(connection_tester.IsRejected());
 
   auto close_promise =
-      tcp_socket->close(script_state, blink::SocketCloseOptions::Create(),
-                        scope.GetExceptionState());
+      tcp_socket->close(script_state, scope.GetExceptionState());
 
   ASSERT_TRUE(scope.GetExceptionState().HadException());
   EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
@@ -83,17 +84,18 @@
   auto connection_promise = tcp_socket->connection(script_state);
   ScriptPromiseTester connection_tester(script_state, connection_promise);
 
-  auto [_, consumer] = CreateDataPipe();
+  auto [consumer_complement, consumer] = CreateDataPipe();
+  auto [producer, producer_complement] = CreateDataPipe();
   tcp_socket->Init(net::OK, net::IPEndPoint{net::IPAddress::IPv4Localhost(), 0},
                    net::IPEndPoint{net::IPAddress::IPv4Localhost(), 0},
-                   std::move(consumer), mojo::ScopedDataPipeProducerHandle());
+                   std::move(consumer), std::move(producer));
 
   connection_tester.WaitUntilSettled();
   ASSERT_TRUE(connection_tester.IsFulfilled());
 
   auto close_promise =
-      tcp_socket->close(script_state, blink::SocketCloseOptions::Create(),
-                        scope.GetExceptionState());
+      tcp_socket->close(script_state, scope.GetExceptionState());
+  test::RunPendingTasks();
   ASSERT_FALSE(scope.GetExceptionState().HadException());
 }
 
@@ -106,10 +108,11 @@
   auto connection_promise = tcp_socket->connection(script_state);
   ScriptPromiseTester connection_tester(script_state, connection_promise);
 
-  auto [_, consumer] = CreateDataPipe();
+  auto [consumer_complement, consumer] = CreateDataPipe();
+  auto [producer, producer_complement] = CreateDataPipe();
   tcp_socket->Init(net::OK, net::IPEndPoint{net::IPAddress::IPv4Localhost(), 0},
                    net::IPEndPoint{net::IPAddress::IPv4Localhost(), 0},
-                   std::move(consumer), mojo::ScopedDataPipeProducerHandle());
+                   std::move(consumer), std::move(producer));
 
   connection_tester.WaitUntilSettled();
   ASSERT_TRUE(connection_tester.IsFulfilled());
@@ -120,12 +123,19 @@
   // Trigger OnSocketObserverConnectionError().
   auto observer = tcp_socket->GetTCPSocketObserver();
   observer.reset();
+  consumer_complement.reset();
+  producer_complement.reset();
 
   closed_tester.WaitUntilSettled();
   ASSERT_TRUE(closed_tester.IsRejected());
 }
 
-TEST(TCPSocketTest, OnReadError) {
+class TCPSocketCloseTest
+    : public testing::TestWithParam<std::tuple<bool, bool>> {};
+
+TEST_P(TCPSocketCloseTest, OnErrorOrClose) {
+  auto [read_error, write_error] = GetParam();
+
   V8TestingScope scope;
 
   auto* script_state = scope.GetScriptState();
@@ -134,10 +144,11 @@
   auto connection_promise = tcp_socket->connection(script_state);
   ScriptPromiseTester connection_tester(script_state, connection_promise);
 
-  auto [_, consumer] = CreateDataPipe();
+  auto [consumer_complement, consumer] = CreateDataPipe();
+  auto [producer, producer_complement] = CreateDataPipe();
   tcp_socket->Init(net::OK, net::IPEndPoint{net::IPAddress::IPv4Localhost(), 0},
                    net::IPEndPoint{net::IPAddress::IPv4Localhost(), 0},
-                   std::move(consumer), mojo::ScopedDataPipeProducerHandle());
+                   std::move(consumer), std::move(producer));
 
   connection_tester.WaitUntilSettled();
   ASSERT_TRUE(connection_tester.IsFulfilled());
@@ -145,10 +156,48 @@
   ScriptPromiseTester closed_tester(script_state,
                                     tcp_socket->closed(script_state));
 
-  tcp_socket->OnReadError(net::ERR_UNEXPECTED);
+  if (read_error) {
+    tcp_socket->OnReadError(net::ERR_UNEXPECTED);
+    consumer_complement.reset();
+    test::RunPendingTasks();
+  } else {
+    auto* readable = tcp_socket->readable_stream_wrapper_->Readable();
+    auto cancel = ScriptPromiseTester(
+        script_state, readable->cancel(script_state, ASSERT_NO_EXCEPTION));
+    cancel.WaitUntilSettled();
+    ASSERT_TRUE(cancel.IsFulfilled());
+  }
 
   ASSERT_EQ(tcp_socket->readable_stream_wrapper_->GetState(),
-            StreamWrapper::State::kAborted);
+            read_error ? StreamWrapper::State::kAborted
+                       : StreamWrapper::State::kClosed);
+
+  if (write_error) {
+    tcp_socket->OnWriteError(net::ERR_UNEXPECTED);
+    producer_complement.reset();
+    test::RunPendingTasks();
+  } else {
+    auto* writable = tcp_socket->writable_stream_wrapper_->Writable();
+    auto abort = ScriptPromiseTester(
+        script_state, writable->abort(script_state, ASSERT_NO_EXCEPTION));
+    abort.WaitUntilSettled();
+    ASSERT_TRUE(abort.IsFulfilled());
+  }
+
+  ASSERT_EQ(tcp_socket->writable_stream_wrapper_->GetState(),
+            write_error ? StreamWrapper::State::kAborted
+                        : StreamWrapper::State::kClosed);
+
+  closed_tester.WaitUntilSettled();
+  if (!read_error && !write_error) {
+    ASSERT_TRUE(closed_tester.IsFulfilled());
+  } else {
+    ASSERT_TRUE(closed_tester.IsRejected());
+  }
 }
 
+INSTANTIATE_TEST_SUITE_P(/**/,
+                         TCPSocketCloseTest,
+                         testing::Combine(testing::Bool(), testing::Bool()));
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.cc b/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.cc
index eb080b7..25200215 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.cc
@@ -4,10 +4,15 @@
 
 #include "third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h"
 
+#include "base/notreached.h"
+#include "mojo/public/cpp/system/handle_signals_state.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "net/base/net_errors.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
+#include "third_party/blink/renderer/core/dom/abort_signal.h"
 #include "third_party/blink/renderer/core/dom/events/event_target_impl.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
@@ -26,24 +31,6 @@
 
 namespace blink {
 
-// An implementation of UnderlyingSinkBase that forwards all operations to the
-// TCPWritableStreamWrapper object that created it.
-class TCPWritableStreamWrapper::TCPUnderlyingSink final
-    : public WritableStreamWrapper::UnderlyingSink {
- public:
-  explicit TCPUnderlyingSink(TCPWritableStreamWrapper* writable_stream_wrapper)
-      : WritableStreamWrapper::UnderlyingSink(writable_stream_wrapper) {}
-
-  ScriptPromise close(ScriptState* script_state, ExceptionState&) override {
-    GetWritableStreamWrapper()->CloseSocket(/*error=*/false);
-    return ScriptPromise::CastUndefined(script_state);
-  }
-
-  void Trace(Visitor* visitor) const override {
-    WritableStreamWrapper::UnderlyingSink::Trace(visitor);
-  }
-};
-
 TCPWritableStreamWrapper::CachedDataBuffer::CachedDataBuffer(
     v8::Isolate* isolate,
     const uint8_t* data,
@@ -68,7 +55,7 @@
 
 TCPWritableStreamWrapper::TCPWritableStreamWrapper(
     ScriptState* script_state,
-    base::OnceCallback<void(bool)> on_close,
+    CloseOnceCallback on_close,
     mojo::ScopedDataPipeProducerHandle handle)
     : WritableStreamWrapper(script_state),
       on_close_(std::move(on_close)),
@@ -80,26 +67,19 @@
       MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
       WTF::BindRepeating(&TCPWritableStreamWrapper::OnHandleReady,
                          WrapWeakPersistent(this)));
+
   close_watcher_.Watch(
       data_pipe_.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
       MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
-      WTF::BindRepeating(&TCPWritableStreamWrapper::OnPeerClosed,
+      WTF::BindRepeating(&TCPWritableStreamWrapper::OnHandleReset,
                          WrapWeakPersistent(this)));
 
   // Set the CountQueueingStrategy's high water mark as 1 to make the logic of
   // |WriteOrCacheData| much simpler
-  InitSinkAndWritable(/*sink=*/MakeGarbageCollected<TCPUnderlyingSink>(this),
+  InitSinkAndWritable(/*sink=*/MakeGarbageCollected<UnderlyingSink>(this),
                       /*high_water_mark=*/1);
 }
 
-void TCPWritableStreamWrapper::CloseSocket(bool error) {
-  if (on_close_) {
-    DCHECK_EQ(GetState(), State::kOpen);
-    std::move(on_close_).Run(error);
-  }
-  DCHECK_NE(GetState(), State::kOpen);
-}
-
 bool TCPWritableStreamWrapper::HasPendingWrite() const {
   return !!write_promise_resolver_;
 }
@@ -111,9 +91,6 @@
 
 void TCPWritableStreamWrapper::OnHandleReady(MojoResult result,
                                              const mojo::HandleSignalsState&) {
-  DVLOG(1) << "TCPWritableStreamWrapper::OnHandleReady() this=" << this
-           << " result=" << result;
-
   switch (result) {
     case MOJO_RESULT_OK:
       WriteCachedData();
@@ -128,21 +105,22 @@
   }
 }
 
-void TCPWritableStreamWrapper::OnPeerClosed(MojoResult result,
-                                            const mojo::HandleSignalsState&) {
-  DVLOG(1) << "TCPWritableStreamWrapper::OnPeerClosed() this=" << this
-           << " result=" << result;
-
+void TCPWritableStreamWrapper::OnHandleReset(MojoResult result,
+                                             const mojo::HandleSignalsState&) {
   DCHECK_EQ(result, MOJO_RESULT_OK);
-  DCHECK_EQ(GetState(), State::kOpen);
+  ResetPipe();
+}
 
-  CloseSocket(/*error=*/true);
+void TCPWritableStreamWrapper::OnAbortSignal() {
+  if (write_promise_resolver_) {
+    write_promise_resolver_->Reject(
+        Controller()->signal()->reason(GetScriptState()));
+    write_promise_resolver_ = nullptr;
+  }
 }
 
 ScriptPromise TCPWritableStreamWrapper::Write(ScriptValue chunk,
                                               ExceptionState& exception_state) {
-  DVLOG(1) << "TCPWritableStreamWrapper::Write() this=" << this;
-
   // There can only be one call to write() in progress at a time.
   DCHECK(!write_promise_resolver_);
   DCHECK_EQ(0u, offset_);
@@ -161,15 +139,16 @@
   DCHECK(buffer_source);
 
   DOMArrayPiece array_piece(buffer_source);
-  return WriteOrCacheData({array_piece.Bytes(), array_piece.ByteLength()});
+  return WriteOrCacheData({array_piece.Bytes(), array_piece.ByteLength()},
+                          exception_state);
 }
 
 // Attempt to write |data|. Cache anything that could not be written
 // synchronously. Arrange for the cached data to be written asynchronously.
 ScriptPromise TCPWritableStreamWrapper::WriteOrCacheData(
-    base::span<const uint8_t> data) {
-  DVLOG(1) << "TCPWritableStreamWrapper::WriteOrCacheData() this=" << this
-           << " data=(" << data.data() << ", " << data.size() << ")";
+    base::span<const uint8_t> data,
+    ExceptionState& exception_state) {
+  DCHECK(data_pipe_);
   size_t written = WriteDataSynchronously(data);
 
   if (written == data.size())
@@ -177,22 +156,14 @@
 
   DCHECK_LT(written, data.size());
 
-  if (!data_pipe_) {
-    ScriptState::Scope scope(GetScriptState());
-    return ScriptPromise::Reject(
-        GetScriptState(),
-        CreateException(GetScriptState(), DOMExceptionCode::kInvalidStateError,
-                        "Pipe is disconnected."));
-  }
-
   DCHECK(!cached_data_);
   cached_data_ = std::make_unique<CachedDataBuffer>(
       GetScriptState()->GetIsolate(), data.data() + written,
       data.size() - written);
   DCHECK_EQ(offset_, 0u);
   write_watcher_.ArmOrNotify();
-  write_promise_resolver_ =
-      MakeGarbageCollected<ScriptPromiseResolver>(GetScriptState());
+  write_promise_resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(
+      GetScriptState(), exception_state.GetContext());
   return write_promise_resolver_->Promise();
 }
 
@@ -200,8 +171,6 @@
 // asynchronously. Fulfill |write_promise_resolver_| once all data has been
 // written.
 void TCPWritableStreamWrapper::WriteCachedData() {
-  DVLOG(1) << "TCPWritableStreamWrapper::WriteCachedData() this=" << this;
-
   auto data = base::make_span(static_cast<uint8_t*>(cached_data_->data()),
                               cached_data_->length())
                   .subspan(offset_);
@@ -231,8 +200,6 @@
 // bytes written. May close |data_pipe_| as a side-effect on error.
 size_t TCPWritableStreamWrapper::WriteDataSynchronously(
     base::span<const uint8_t> data) {
-  DVLOG(1) << "TCPWritableStreamWrapper::WriteDataSynchronously() this=" << this
-           << " data=(" << data.data() << ", " << data.size() << ")";
   DCHECK(data_pipe_);
 
   // This use of saturated cast means that we will fallback to asynchronous
@@ -257,37 +224,64 @@
   }
 }
 
-void TCPWritableStreamWrapper::CloseStream(bool error) {
+void TCPWritableStreamWrapper::CloseStream() {
   if (GetState() != State::kOpen) {
     return;
   }
-  SetState(error ? State::kAborted : State::kClosed);
+  SetState(State::kClosed);
+  DCHECK(!write_promise_resolver_);
 
-  {
-    ScriptState::Scope scope(GetScriptState());
-    ScriptValue exception =
-        error
-            ? CreateException(GetScriptState(), DOMExceptionCode::kNetworkError,
-                              "Connection aborted by remote")
-            : CreateException(GetScriptState(),
-                              DOMExceptionCode::kInvalidStateError,
-                              "Stream closed.");
-    if (write_promise_resolver_) {
-      write_promise_resolver_->Reject(exception);
-      write_promise_resolver_ = nullptr;
-    }
-
-    Controller()->error(GetScriptState(), exception);
+  // If close request came from writer.close() or writer.abort(), the internal
+  // state of the stream is already set to closed.  Therefore we don't have to
+  // do anything with the controller.
+  if (!data_pipe_) {
+    // This is a rare case indicating that writer.close/abort() interrupted
+    // the OnWriteError() call where the pipe already got reset, but the
+    // corresponding IPC hasn't yet arrived. The simplest way is to abort
+    // CloseStream by setting state to Open and allow the IPC to finish the
+    // job.
+    SetState(State::kOpen);
+    return;
   }
 
-  on_close_.Reset();
-
   ResetPipe();
+  std::move(on_close_).Run(/*error=*/false);
+}
+
+void TCPWritableStreamWrapper::ErrorStream(int32_t error_code) {
+  if (GetState() != State::kOpen) {
+    return;
+  }
+  SetState(State::kAborted);
+
+  auto message =
+      String{"Stream aborted by the remote: " + net::ErrorToString(error_code)};
+  auto* exception = MakeGarbageCollected<DOMException>(
+      DOMExceptionCode::kNetworkError, message);
+
+  // Can be already reset due to HandlePipeClosed() called previously.
+  if (data_pipe_) {
+    ResetPipe();
+  }
+
+  auto* script_state = GetScriptState();
+  DCHECK(script_state->ContextIsValid());
+
+  ScriptState::Scope scope{script_state};
+  if (write_promise_resolver_) {
+    write_promise_resolver_->RejectWithDOMException(
+        DOMExceptionCode::kNetworkError, message);
+    write_promise_resolver_ = nullptr;
+  } else {
+    auto* script_state = GetScriptState();
+    Controller()->error(script_state,
+                        ScriptValue::From(script_state, exception));
+  }
+
+  std::move(on_close_).Run(/*error=*/true);
 }
 
 void TCPWritableStreamWrapper::ResetPipe() {
-  DVLOG(1) << "TCPWritableStreamWrapper::ResetPipe() this=" << this;
-
   write_watcher_.Cancel();
   close_watcher_.Cancel();
   data_pipe_.reset();
@@ -297,8 +291,6 @@
 }
 
 void TCPWritableStreamWrapper::Dispose() {
-  DVLOG(1) << "TCPWritableStreamWrapper::Dispose() this=" << this;
-
   ResetPipe();
 }
 
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h b/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h
index 049a1db..6d747b0 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h
@@ -6,11 +6,13 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_DIRECT_SOCKETS_TCP_WRITABLE_STREAM_WRAPPER_H_
 
 #include "base/allocator/partition_allocator/partition_root.h"
+#include "base/notreached.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
@@ -31,31 +33,31 @@
 
  public:
   TCPWritableStreamWrapper(ScriptState*,
-                           base::OnceCallback<void(bool)> on_close,
+                           CloseOnceCallback,
                            mojo::ScopedDataPipeProducerHandle);
 
-  void CloseStream(bool error) override;
-  void CloseSocket(bool error) override;
-
+  // WritableStreamWrapper:
+  void CloseStream() override;
+  void ErrorStream(int32_t error_code) override;
   bool HasPendingWrite() const override;
-
   void Trace(Visitor*) const override;
 
- private:
-  class TCPUnderlyingSink;
+ protected:
+  // WritableStreamWrapper:
+  void OnAbortSignal() override;
+  ScriptPromise Write(ScriptValue chunk, ExceptionState&) override;
 
+ private:
   // Called when |data_pipe_| becomes writable or errored.
   void OnHandleReady(MojoResult, const mojo::HandleSignalsState&);
 
   // Called when |data_pipe_| is closed.
-  void OnPeerClosed(MojoResult, const mojo::HandleSignalsState&);
-
-  // Implements UnderlyingSink::write().
-  ScriptPromise Write(ScriptValue chunk, ExceptionState&) override;
+  void OnHandleReset(MojoResult, const mojo::HandleSignalsState&);
 
   // Writes |data| to |data_pipe_|, possible saving unwritten data to
   // |cached_data_|.
-  ScriptPromise WriteOrCacheData(base::span<const uint8_t> data);
+  ScriptPromise WriteOrCacheData(base::span<const uint8_t> data,
+                                 ExceptionState&);
 
   // Attempts to write some more of |cached_data_| to |data_pipe_|.
   void WriteCachedData();
@@ -73,6 +75,7 @@
   // Prepares the object for destruction.
   void Dispose();
 
+  // TODO(crbug.com/1337286): Remove this class.
   class CachedDataBuffer {
    public:
     CachedDataBuffer(v8::Isolate* isolate, const uint8_t* data, size_t length);
@@ -97,14 +100,14 @@
     std::unique_ptr<uint8_t[], OnFree> buffer_;
   };
 
-  base::OnceCallback<void(bool)> on_close_;
+  CloseOnceCallback on_close_;
 
   mojo::ScopedDataPipeProducerHandle data_pipe_;
 
   // Only armed when we need to write something.
   mojo::SimpleWatcher write_watcher_;
 
-  // Always armed to detect close.
+  // Always armed to detect pipe close.
   mojo::SimpleWatcher close_watcher_;
 
   // Data which has been passed to write() but still needs to be written
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper_unittest.cc b/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper_unittest.cc
index bab27f1..3257900 100644
--- a/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper_unittest.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper_unittest.cc
@@ -4,12 +4,16 @@
 
 #include "third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h"
 
+#include "base/callback_helpers.h"
 #include "base/test/mock_callback.h"
+#include "net/base/net_errors.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/core/streams/writable_stream.h"
 #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
+#include "third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
@@ -34,7 +38,7 @@
 
   // The default value of |capacity| means some sensible value selected by mojo.
   TCPWritableStreamWrapper* Create(const V8TestingScope& scope,
-                                   uint32_t capacity = 0) {
+                                   uint32_t capacity = 1) {
     MojoCreateDataPipeOptions options;
     options.struct_size = sizeof(MojoCreateDataPipeOptions);
     options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
@@ -50,12 +54,11 @@
 
     auto* script_state = scope.GetScriptState();
     stream_wrapper_ = MakeGarbageCollected<TCPWritableStreamWrapper>(
-        script_state, WTF::Bind(&StreamCreator::Close, WrapPersistent(this)),
-        std::move(data_pipe_producer));
+        script_state, base::DoNothing(), std::move(data_pipe_producer));
     return stream_wrapper_;
   }
 
-  void ClosePipe() { data_pipe_consumer_.reset(); }
+  void ResetPipe() { data_pipe_consumer_.reset(); }
 
   // Reads everything from |data_pipe_consumer_| and returns it in a vector.
   Vector<uint8_t> ReadAllPendingData() {
@@ -82,7 +85,7 @@
     return data;
   }
 
-  void Close(bool error) { stream_wrapper_->CloseStream(error); }
+  void Close(bool error) {}
 
   void Trace(Visitor* visitor) const { visitor->Trace(stream_wrapper_); }
 
@@ -228,7 +231,7 @@
   EXPECT_THAT(stream_creator->ReadAllPendingData(), ElementsAre('D'));
 }
 
-TEST(TCPWritableStreamWrapperTest, TriggerHasAborted) {
+TEST(TCPWritableStreamWrapperTest, DISABLED_TriggerHasAborted) {
   V8TestingScope scope;
   auto* stream_creator = MakeGarbageCollected<StreamCreator>();
   auto* tcp_writable_stream_wrapper = stream_creator->Create(scope);
@@ -241,14 +244,94 @@
       writer->write(script_state, ScriptValue::From(script_state, chunk),
                     ASSERT_NO_EXCEPTION);
   ScriptPromiseTester write_tester(script_state, write_promise);
-  // Trigger onAborted() on purpose.
-  stream_creator->ClosePipe();
+
+  tcp_writable_stream_wrapper->ErrorStream(net::ERR_UNEXPECTED);
   write_tester.WaitUntilSettled();
 
+  ASSERT_FALSE(write_tester.IsFulfilled());
+
   EXPECT_EQ(tcp_writable_stream_wrapper->GetState(),
             StreamWrapper::State::kAborted);
 }
 
+class TCPWritableStreamWrapperCloseTestWithMaybePendingWrite
+    : public testing::TestWithParam<bool> {};
+
+INSTANTIATE_TEST_SUITE_P(/**/,
+                         TCPWritableStreamWrapperCloseTestWithMaybePendingWrite,
+                         testing::Bool());
+
+TEST_P(TCPWritableStreamWrapperCloseTestWithMaybePendingWrite, TriggerClose) {
+  V8TestingScope scope;
+  auto* stream_creator = MakeGarbageCollected<StreamCreator>();
+  auto* tcp_writable_stream_wrapper = stream_creator->Create(scope);
+
+  bool pending_write = GetParam();
+  absl::optional<ScriptPromiseTester> tester;
+  if (pending_write) {
+    auto* script_state = scope.GetScriptState();
+    auto* chunk = DOMArrayBuffer::Create("D", 2);
+    ScriptPromise write_promise =
+        tcp_writable_stream_wrapper->Writable()
+            ->getWriter(script_state, ASSERT_NO_EXCEPTION)
+            ->write(script_state, ScriptValue::From(script_state, chunk),
+                    ASSERT_NO_EXCEPTION);
+    tester.emplace(script_state, write_promise);
+    test::RunPendingTasks();
+  }
+
+  // 1. OnWriteError(...) is called.
+  tcp_writable_stream_wrapper->ErrorStream(net::ERR_UNEXPECTED);
+
+  // 2. pipe reset event arrives.
+  stream_creator->ResetPipe();
+  test::RunPendingTasks();
+
+  if (pending_write) {
+    tester->WaitUntilSettled();
+    ASSERT_TRUE(tester->IsRejected());
+  }
+
+  ASSERT_EQ(tcp_writable_stream_wrapper->GetState(),
+            StreamWrapper::State::kAborted);
+}
+
+TEST_P(TCPWritableStreamWrapperCloseTestWithMaybePendingWrite,
+       TriggerCloseInReverseOrder) {
+  V8TestingScope scope;
+  auto* stream_creator = MakeGarbageCollected<StreamCreator>();
+  auto* tcp_writable_stream_wrapper = stream_creator->Create(scope);
+
+  bool pending_write = GetParam();
+  absl::optional<ScriptPromiseTester> tester;
+  if (pending_write) {
+    auto* script_state = scope.GetScriptState();
+    auto* chunk = DOMArrayBuffer::Create("D", 2);
+    ScriptPromise write_promise =
+        tcp_writable_stream_wrapper->Writable()
+            ->getWriter(script_state, ASSERT_NO_EXCEPTION)
+            ->write(script_state, ScriptValue::From(script_state, chunk),
+                    ASSERT_NO_EXCEPTION);
+    tester.emplace(script_state, write_promise);
+    test::RunPendingTasks();
+  }
+
+  // 1. pipe reset event arrives.
+  stream_creator->ResetPipe();
+  test::RunPendingTasks();
+
+  // 2. OnWriteError(...) is called.
+  tcp_writable_stream_wrapper->ErrorStream(net::ERR_UNEXPECTED);
+
+  if (pending_write) {
+    tester->WaitUntilSettled();
+    ASSERT_TRUE(tester->IsRejected());
+  }
+
+  ASSERT_EQ(tcp_writable_stream_wrapper->GetState(),
+            StreamWrapper::State::kAborted);
+}
+
 }  // namespace
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper.cc b/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper.cc
index dec770fa..82fdb3b6 100644
--- a/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper.cc
@@ -7,6 +7,7 @@
 #include "base/callback_forward.h"
 #include "base/notreached.h"
 #include "base/time/time.h"
+#include "net/base/net_errors.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_underlying_source.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_udp_message.h"
@@ -26,37 +27,18 @@
 
 namespace blink {
 
-class UDPReadableStreamWrapper::UDPUnderlyingSource
-    : public ReadableStreamWrapper::UnderlyingSource {
- public:
-  UDPUnderlyingSource(ScriptState* script_state,
-                      UDPReadableStreamWrapper* readable_stream_wrapper)
-      : ReadableStreamWrapper::UnderlyingSource(script_state,
-                                                readable_stream_wrapper) {}
-
-  ScriptPromise Cancel(ScriptState* script_state, ScriptValue reason) override {
-    GetReadableStreamWrapper()->CloseSocket(/*error=*/false);
-    return ScriptPromise::CastUndefined(script_state);
-  }
-
-  void Trace(Visitor* visitor) const override {
-    ReadableStreamWrapper::UnderlyingSource::Trace(visitor);
-  }
-};
-
 // UDPReadableStreamWrapper definition
 
 UDPReadableStreamWrapper::UDPReadableStreamWrapper(
     ScriptState* script_state,
+    CloseOnceCallback on_close,
     const Member<UDPSocketMojoRemote> udp_socket,
-    base::OnceCallback<void(bool)> on_close,
     uint32_t high_water_mark)
     : ReadableStreamWrapper(script_state),
-      udp_socket_(udp_socket),
-      on_close_(std::move(on_close)) {
+      on_close_(std::move(on_close)),
+      udp_socket_(udp_socket) {
   InitSourceAndReadable(
-      /*source=*/MakeGarbageCollected<UDPUnderlyingSource>(GetScriptState(),
-                                                           this),
+      /*source=*/MakeGarbageCollected<UnderlyingSource>(GetScriptState(), this),
       high_water_mark);
 }
 
@@ -97,26 +79,27 @@
   ReadableStreamWrapper::Trace(visitor);
 }
 
-void UDPReadableStreamWrapper::CloseSocket(bool error) {
-  DCHECK_EQ(GetState(), State::kOpen);
-  std::move(on_close_).Run(error);
-  DCHECK_NE(GetState(), State::kOpen);
-}
-
-void UDPReadableStreamWrapper::CloseStream(bool error) {
+void UDPReadableStreamWrapper::CloseStream() {
   if (GetState() != State::kOpen) {
     return;
   }
-  SetState(error ? State::kAborted : State::kClosed);
+  SetState(State::kClosed);
 
-  if (error) {
-    Controller()->Error(
-        MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError));
-  } else {
-    Controller()->Close();
+  std::move(on_close_).Run(/*error=*/false);
+}
+
+void UDPReadableStreamWrapper::ErrorStream(int32_t error_code) {
+  if (GetState() != State::kOpen) {
+    return;
   }
+  SetState(State::kAborted);
 
-  on_close_.Reset();
+  auto* exception = MakeGarbageCollected<DOMException>(
+      DOMExceptionCode::kNetworkError, String{"Stream aborted by the remote: " +
+                                              net::ErrorToString(error_code)});
+  Controller()->Error(exception);
+
+  std::move(on_close_).Run(/*error=*/true);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper.h b/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper.h
index 32fd921d..b71dfb8 100644
--- a/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper.h
+++ b/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper.h
@@ -23,27 +23,24 @@
     : public GarbageCollected<UDPReadableStreamWrapper>,
       public ReadableStreamWrapper {
  public:
-  UDPReadableStreamWrapper(ScriptState* script_state,
-                           const Member<UDPSocketMojoRemote> udp_socket,
-                           base::OnceCallback<void(bool)> on_close,
+  UDPReadableStreamWrapper(ScriptState*,
+                           CloseOnceCallback,
+                           const Member<UDPSocketMojoRemote>,
                            uint32_t high_water_mark);
 
+  // ReadableStreamWrapper:
   void Pull() override;
-
   bool Push(base::span<const uint8_t> data,
             const absl::optional<net::IPEndPoint>& src_addr) override;
-
-  void CloseStream(bool error) override;
-  void CloseSocket(bool error) override;
-
-  void Trace(Visitor* visitor) const override;
+  void CloseStream() override;
+  void ErrorStream(int32_t error_code) override;
+  void Trace(Visitor*) const override;
 
  private:
   class UDPUnderlyingSource;
 
+  CloseOnceCallback on_close_;
   const Member<UDPSocketMojoRemote> udp_socket_;
-  base::OnceCallback<void(bool)> on_close_;
-
   int32_t pending_receive_requests_ = 0;
 };
 
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper_unittest.cc b/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper_unittest.cc
index 40d9f1a..bd8bad68 100644
--- a/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper_unittest.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper_unittest.cc
@@ -19,6 +19,7 @@
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
+#include "third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h"
 #include "third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -73,14 +74,11 @@
 
     auto* script_state = scope.GetScriptState();
     stream_wrapper_ = MakeGarbageCollected<UDPReadableStreamWrapper>(
-        script_state, udp_socket,
-        WTF::Bind(&StreamCreator::Close, WrapPersistent(this)),
+        script_state, base::DoNothing(), udp_socket,
         /*high_water_mark=*/1);
     return stream_wrapper_;
   }
 
-  void Close(bool error) { stream_wrapper_->CloseStream(error); }
-
   void Trace(Visitor* visitor) const { visitor->Trace(stream_wrapper_); }
 
   FakeDirectUDPSocket& fake_udp_socket() { return fake_udp_socket_; }
@@ -257,7 +255,7 @@
   EXPECT_FALSE(message);
 }
 
-TEST(UDPReadableStreamWrapperTest, CancelStreamFromWrapper) {
+TEST(UDPReadableStreamWrapperTest, ReadRejectsOnError) {
   V8TestingScope scope;
 
   auto* stream_creator = MakeGarbageCollected<StreamCreator>();
@@ -273,18 +271,12 @@
       udp_readable_stream_wrapper->Readable()->GetDefaultReaderForTesting(
           script_state, ASSERT_NO_EXCEPTION);
 
-  udp_readable_stream_wrapper->CloseStream(/*error=*/false);
+  udp_readable_stream_wrapper->ErrorStream(net::ERR_UNEXPECTED);
 
   ScriptPromiseTester read_tester(
       script_state, reader->read(script_state, ASSERT_NO_EXCEPTION));
   read_tester.WaitUntilSettled();
-  EXPECT_TRUE(read_tester.IsFulfilled());
-
-  auto [message, done] =
-      UnpackPromiseResult(scope, read_tester.Value().V8Value());
-
-  EXPECT_TRUE(done);
-  EXPECT_FALSE(message);
+  EXPECT_TRUE(read_tester.IsRejected());
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_socket.cc b/third_party/blink/renderer/modules/direct_sockets/udp_socket.cc
index 5ccbfcf..91eca46 100644
--- a/third_party/blink/renderer/modules/direct_sockets/udp_socket.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/udp_socket.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/direct_sockets/udp_socket.h"
 
+#include "base/barrier_callback.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/notreached.h"
 #include "net/base/net_errors.h"
@@ -11,7 +12,6 @@
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_socket_close_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_udp_socket_connection.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_udp_socket_options.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -19,6 +19,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/fileapi/blob.h"
 #include "third_party/blink/renderer/core/streams/writable_stream.h"
+#include "third_party/blink/renderer/modules/direct_sockets/stream_wrapper.h"
 #include "third_party/blink/renderer/modules/direct_sockets/udp_readable_stream_wrapper.h"
 #include "third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.h"
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
@@ -121,12 +122,15 @@
                      const absl::optional<net::IPEndPoint>& local_addr,
                      const absl::optional<net::IPEndPoint>& peer_addr) {
   if (result == net::OK && peer_addr) {
+    auto close_callback = base::BarrierCallback<bool>(
+        /*num_callbacks=*/2,
+        WTF::Bind(&UDPSocket::OnBothStreamsClosed, WrapWeakPersistent(this)));
+
     readable_stream_wrapper_ = MakeGarbageCollected<UDPReadableStreamWrapper>(
-        script_state_, udp_socket_,
-        WTF::Bind(&UDPSocket::CloseInternal, WrapWeakPersistent(this)),
+        script_state_, close_callback, udp_socket_,
         readable_stream_buffer_size_.value_or(readableStreamDefaultBufferSize));
     writable_stream_wrapper_ = MakeGarbageCollected<UDPWritableStreamWrapper>(
-        script_state_, udp_socket_);
+        script_state_, close_callback, udp_socket_);
 
     auto* connection = UDPSocketConnection::Create();
 
@@ -223,49 +227,24 @@
 }
 
 void UDPSocket::CloseOnError() {
-  if (Initialized()) {
-    CloseInternal(/*error=*/true);
-    DCHECK(Closed());
-  }
-}
-
-void UDPSocket::Close(const SocketCloseOptions* options,
-                      ExceptionState& exception_state) {
   if (!Initialized()) {
-    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
-                                      "Socket is not properly initialized.");
     return;
   }
 
-  if (Closed()) {
-    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
-                                      "Socket is already closed or errored.");
-    return;
-  }
-
-  if (!options->hasForce() || !options->force()) {
-    if (readable_stream_wrapper_->Locked() ||
-        writable_stream_wrapper_->Locked()) {
-      exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
-                                        "Close called on locked streams.");
-      return;
-    }
-  }
-
-  CloseInternal(/*error=*/false);
-  DCHECK(Closed());
+  readable_stream_wrapper_->ErrorStream(net::ERR_CONNECTION_ABORTED);
+  writable_stream_wrapper_->ErrorStream(net::ERR_CONNECTION_ABORTED);
 }
 
-void UDPSocket::CloseInternal(bool error) {
+void UDPSocket::OnBothStreamsClosed(std::vector<bool> args) {
+  DCHECK_EQ(args.size(), 2U);
+  // At least one callback was invoked with error = true.
+  bool error = base::ranges::any_of(args, base::identity());
+
   CloseServiceAndResetFeatureHandle();
   ResolveOrRejectClosed(error);
 
   socket_listener_.reset();
 
-  // Reject pending read/write promises.
-  readable_stream_wrapper_->CloseStream(error);
-  writable_stream_wrapper_->CloseStream(error);
-
   // Close the socket.
   udp_socket_->Close();
 }
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_socket.h b/third_party/blink/renderer/modules/direct_sockets/udp_socket.h
index 11655fe..00e2116 100644
--- a/third_party/blink/renderer/modules/direct_sockets/udp_socket.h
+++ b/third_party/blink/renderer/modules/direct_sockets/udp_socket.h
@@ -55,26 +55,10 @@
                            const UDPSocketOptions*,
                            ExceptionState&);
 
-  // Socket:
-  ScriptPromise connection(ScriptState* script_state) const override {
-    return Socket::connection(script_state);
-  }
-  ScriptPromise closed(ScriptState* script_state) const override {
-    return Socket::closed(script_state);
-  }
-  ScriptPromise close(ScriptState* script_state,
-                      const SocketCloseOptions* options,
-                      ExceptionState& exception_state) override {
-    return Socket::close(script_state, options, exception_state);
-  }
-
  public:
   explicit UDPSocket(ScriptState*);
   ~UDPSocket() override;
 
-  UDPSocket(const UDPSocket&) = delete;
-  UDPSocket& operator=(const UDPSocket&) = delete;
-
   // Validates options and calls
   // DirectSocketsServiceMojoRemote::OpenUdpSocket(...) with Init(...) passed as
   // callback.
@@ -98,21 +82,20 @@
  private:
   mojo::PendingReceiver<blink::mojom::blink::DirectUDPSocket>
   GetUDPSocketReceiver();
-
   mojo::PendingRemote<network::mojom::blink::UDPSocketListener>
   GetUDPSocketListener();
 
   // network::mojom::blink::UDPSocketListener:
   void OnReceived(int32_t result,
-                  const absl::optional<::net::IPEndPoint>& src_addr,
-                  absl::optional<::base::span<const ::uint8_t>> data) override;
+                  const absl::optional<net::IPEndPoint>& src_addr,
+                  absl::optional<base::span<const uint8_t>> data) override;
 
   void OnServiceConnectionError() override;
   void OnSocketConnectionError();
 
   void CloseOnError();
-  void Close(const SocketCloseOptions*, ExceptionState&) override;
-  void CloseInternal(bool error);
+
+  void OnBothStreamsClosed(std::vector<bool> args);
 
   const Member<UDPSocketMojoRemote> udp_socket_;
   HeapMojoReceiver<network::mojom::blink::UDPSocketListener, UDPSocket>
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_socket.idl b/third_party/blink/renderer/modules/direct_sockets/udp_socket.idl
index 46e1051..7d86091 100644
--- a/third_party/blink/renderer/modules/direct_sockets/udp_socket.idl
+++ b/third_party/blink/renderer/modules/direct_sockets/udp_socket.idl
@@ -17,5 +17,5 @@
   [CallWith=ScriptState] readonly attribute Promise<void> closed;
 
   [CallWith=ScriptState, RaisesException, Measure]
-  Promise<void> close(optional SocketCloseOptions options = {});
+  Promise<void> close();
 };
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.cc b/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.cc
index 56fffda..57ccf43 100644
--- a/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.cc
@@ -8,10 +8,12 @@
 #include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_udp_message.h"
+#include "third_party/blink/renderer/core/dom/abort_signal.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
@@ -29,31 +31,16 @@
 
 namespace blink {
 
-// UDPWritableStreamWrapper::UnderlyingSink declaration
-
-class UDPWritableStreamWrapper::UDPUnderlyingSink final
-    : public WritableStreamWrapper::UnderlyingSink {
- public:
-  explicit UDPUnderlyingSink(UDPWritableStreamWrapper* writable_stream_wrapper)
-      : WritableStreamWrapper::UnderlyingSink(writable_stream_wrapper) {}
-
-  ScriptPromise close(ScriptState* script_state, ExceptionState&) override {
-    GetWritableStreamWrapper()->CloseStream(/*error=*/false);
-    return ScriptPromise::CastUndefined(script_state);
-  }
-
-  void Trace(Visitor* visitor) const override {
-    WritableStreamWrapper::UnderlyingSink::Trace(visitor);
-  }
-};
-
 // UDPWritableStreamWrapper definition
 
 UDPWritableStreamWrapper::UDPWritableStreamWrapper(
     ScriptState* script_state,
+    CloseOnceCallback on_close,
     const Member<UDPSocketMojoRemote> udp_socket)
-    : WritableStreamWrapper(script_state), udp_socket_(udp_socket) {
-  InitSinkAndWritable(/*sink=*/MakeGarbageCollected<UDPUnderlyingSink>(this),
+    : WritableStreamWrapper(script_state),
+      on_close_(std::move(on_close)),
+      udp_socket_(udp_socket) {
+  InitSinkAndWritable(/*sink=*/MakeGarbageCollected<UnderlyingSink>(this),
                       /*high_water_mark=*/1);
 }
 
@@ -67,6 +54,13 @@
   WritableStreamWrapper::Trace(visitor);
 }
 
+void UDPWritableStreamWrapper::OnAbortSignal() {
+  if (send_resolver_) {
+    send_resolver_->Reject(Controller()->signal()->reason(GetScriptState()));
+    send_resolver_ = nullptr;
+  }
+}
+
 ScriptPromise UDPWritableStreamWrapper::Write(ScriptValue chunk,
                                               ExceptionState& exception_state) {
   DCHECK(udp_socket_->get().is_bound());
@@ -87,8 +81,8 @@
   base::span<const uint8_t> data{array_piece.Bytes(), array_piece.ByteLength()};
 
   DCHECK(!send_resolver_);
-  send_resolver_ =
-      MakeGarbageCollected<ScriptPromiseResolver>(GetScriptState());
+  send_resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(
+      GetScriptState(), exception_state.GetContext());
 
   // Why not just return send_resolver_->Promise()?
   // In view of the async nature of the write handler, the callback might get
@@ -108,35 +102,52 @@
   if (send_resolver_) {
     if (result == net::Error::OK) {
       send_resolver_->Resolve();
+      send_resolver_ = nullptr;
     } else {
-      send_resolver_->Reject(MakeGarbageCollected<DOMException>(
-          DOMExceptionCode::kNetworkError, "Failed to send."));
+      ErrorStream(result);
     }
-    send_resolver_ = nullptr;
+    DCHECK(!send_resolver_);
   }
 }
 
-void UDPWritableStreamWrapper::CloseStream(bool error) {
+void UDPWritableStreamWrapper::CloseStream() {
   if (GetState() != State::kOpen) {
     return;
   }
-  SetState(error ? State::kAborted : State::kClosed);
+  SetState(State::kClosed);
+  DCHECK(!send_resolver_);
 
-  ScriptState::Scope scope(GetScriptState());
+  std::move(on_close_).Run(/*error=*/false);
+}
 
-  ScriptValue exception =
-      error ? CreateException(GetScriptState(), DOMExceptionCode::kNetworkError,
-                              "Connection aborted by remote")
-            : CreateException(GetScriptState(),
-                              DOMExceptionCode::kInvalidStateError,
-                              "Stream closed.");
+void UDPWritableStreamWrapper::ErrorStream(int32_t error_code) {
+  if (GetState() != State::kOpen) {
+    return;
+  }
+  SetState(State::kAborted);
 
+  auto* script_state = GetScriptState();
+  DCHECK(script_state->ContextIsValid());
+
+  auto message =
+      String{"Stream aborted by the remote: " + net::ErrorToString(error_code)};
+
+  ScriptState::Scope scope{script_state};
+  // Scope is needed because there's no ScriptState* on the call stack for
+  // either RejectWithDOMException or ScriptValue::From.
   if (send_resolver_) {
-    send_resolver_->Reject(exception);
+    send_resolver_->RejectWithDOMException(DOMExceptionCode::kNetworkError,
+                                           message);
     send_resolver_ = nullptr;
+  } else {
+    Controller()->error(
+        script_state,
+        ScriptValue::From(script_state,
+                          MakeGarbageCollected<DOMException>(
+                              DOMExceptionCode::kNetworkError, message)));
   }
 
-  Controller()->error(GetScriptState(), exception);
+  std::move(on_close_).Run(/*error=*/true);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.h b/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.h
index 929f2d1..30dd459 100644
--- a/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.h
+++ b/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.h
@@ -26,23 +26,27 @@
     : public GarbageCollected<UDPWritableStreamWrapper>,
       public WritableStreamWrapper {
  public:
-  UDPWritableStreamWrapper(ScriptState* script_state,
-                           const Member<UDPSocketMojoRemote> udp_socket_);
+  UDPWritableStreamWrapper(ScriptState*,
+                           CloseOnceCallback,
+                           const Member<UDPSocketMojoRemote>);
 
-  void CloseStream(bool error) override;
+  // WritableStreamWrapper:
+  void CloseStream() override;
+  void ErrorStream(int32_t error_code) override;
   bool HasPendingWrite() const override;
-
   void Trace(Visitor*) const override;
 
+ protected:
+  // WritableStreamWrapper:
+  void OnAbortSignal() override;
+  ScriptPromise Write(ScriptValue chunk, ExceptionState&) override;
+
  private:
-  class UDPUnderlyingSink;
-
-  ScriptPromise Write(ScriptValue chunk,
-                      ExceptionState& exception_state) override;
-
   // Callback for DirectUDPSocket::Send().
   void OnSend(int32_t result);
 
+  CloseOnceCallback on_close_;
+
   const Member<UDPSocketMojoRemote> udp_socket_;
   Member<ScriptPromiseResolver> send_resolver_;
 };
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper_unittest.cc b/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper_unittest.cc
index 60be7a39..83616cb 100644
--- a/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper_unittest.cc
+++ b/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper_unittest.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/googletest/src/googlemock/include/gmock/gmock-matchers.h"
@@ -53,7 +54,14 @@
 
 class StreamCreator : public GarbageCollected<StreamCreator> {
  public:
-  StreamCreator() : receiver_{&fake_udp_socket_} {}
+  StreamCreator()
+      : fake_udp_socket_{std::make_unique<FakeDirectUDPSocket>()},
+        receiver_{fake_udp_socket_.get()} {}
+
+  explicit StreamCreator(std::unique_ptr<FakeDirectUDPSocket> socket)
+      : fake_udp_socket_(std::move(socket)),
+        receiver_{fake_udp_socket_.get()} {}
+
   ~StreamCreator() { test::RunPendingTasks(); }
 
   UDPWritableStreamWrapper* Create(const V8TestingScope& scope) {
@@ -65,16 +73,22 @@
 
     auto* script_state = scope.GetScriptState();
     stream_wrapper_ = MakeGarbageCollected<UDPWritableStreamWrapper>(
-        script_state, udp_socket);
+        script_state,
+        WTF::Bind(&StreamCreator::Close, WrapWeakPersistent(this)), udp_socket);
     return stream_wrapper_;
   }
 
   void Trace(Visitor* visitor) const { visitor->Trace(stream_wrapper_); }
 
-  FakeDirectUDPSocket& fake_udp_socket() { return fake_udp_socket_; }
+  FakeDirectUDPSocket* fake_udp_socket() { return fake_udp_socket_.get(); }
+
+  bool CloseCalledWith(bool error) { return close_called_with_ == error; }
 
  private:
-  FakeDirectUDPSocket fake_udp_socket_;
+  void Close(bool error) { close_called_with_ = error; }
+
+  absl::optional<bool> close_called_with_;
+  std::unique_ptr<FakeDirectUDPSocket> fake_udp_socket_;
   mojo::Receiver<blink::mojom::blink::DirectUDPSocket> receiver_;
   Member<UDPWritableStreamWrapper> stream_wrapper_;
 };
@@ -113,8 +127,8 @@
 
   ASSERT_TRUE(tester.IsFulfilled());
 
-  auto& fake_udp_socket = stream_creator->fake_udp_socket();
-  EXPECT_THAT(fake_udp_socket.GetReceivedData(), ::testing::ElementsAre('A'));
+  auto* fake_udp_socket = stream_creator->fake_udp_socket();
+  EXPECT_THAT(fake_udp_socket->GetReceivedData(), ::testing::ElementsAre('A'));
 }
 
 TEST(UDPWritableStreamWrapperTest, WriteUdpMessageFromTypedArray) {
@@ -144,8 +158,8 @@
 
   ASSERT_TRUE(tester.IsFulfilled());
 
-  auto& fake_udp_socket = stream_creator->fake_udp_socket();
-  EXPECT_THAT(fake_udp_socket.GetReceivedData(),
+  auto* fake_udp_socket = stream_creator->fake_udp_socket();
+  EXPECT_THAT(fake_udp_socket->GetReceivedData(),
               ::testing::ElementsAre('A', 'B', 'C'));
 }
 
@@ -177,8 +191,8 @@
   ASSERT_TRUE(tester.IsFulfilled());
 
   // Nothing should have been written from the empty DOMArrayBuffer.
-  auto& fake_udp_socket = stream_creator->fake_udp_socket();
-  EXPECT_THAT(fake_udp_socket.GetReceivedData(), ::testing::ElementsAre());
+  auto* fake_udp_socket = stream_creator->fake_udp_socket();
+  EXPECT_THAT(fake_udp_socket->GetReceivedData(), ::testing::ElementsAre());
 }
 
 TEST(UDPWritableStreamWrapperTest, WriteUdpMessageWithoutDataField) {
@@ -240,8 +254,8 @@
     ASSERT_TRUE(tester.IsFulfilled());
   }
 
-  auto& fake_udp_socket = stream_creator->fake_udp_socket();
-  EXPECT_THAT(fake_udp_socket.GetReceivedData(),
+  auto* fake_udp_socket = stream_creator->fake_udp_socket();
+  EXPECT_THAT(fake_udp_socket->GetReceivedData(),
               ::testing::ElementsAre('A', 'B'));
 }
 
@@ -288,6 +302,42 @@
   ASSERT_TRUE(write_after_close_tester.IsRejected());
 }
 
+TEST(UDPWritableStreamWrapperTest, WriteFailed) {
+  class FailingFakeDirectUDPSocket : public FakeDirectUDPSocket {
+   public:
+    void Send(base::span<const uint8_t> data, SendCallback callback) override {
+      std::move(callback).Run(net::ERR_UNEXPECTED);
+    }
+  };
+
+  V8TestingScope scope;
+
+  auto* stream_creator = MakeGarbageCollected<StreamCreator>(
+      std::make_unique<FailingFakeDirectUDPSocket>());
+  auto* udp_writable_stream_wrapper = stream_creator->Create(scope);
+
+  auto* script_state = scope.GetScriptState();
+  auto* writer = udp_writable_stream_wrapper->Writable()->getWriter(
+      script_state, ASSERT_NO_EXCEPTION);
+
+  auto* chunk = DOMArrayBuffer::Create("A", 1);
+  auto* message = UDPMessage::Create();
+  message->setData(
+      MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(chunk));
+
+  ScriptPromise write_result =
+      writer->write(script_state, ScriptValue::From(script_state, message),
+                    ASSERT_NO_EXCEPTION);
+  ScriptPromiseTester write_tester(script_state, write_result);
+  write_tester.WaitUntilSettled();
+
+  ASSERT_TRUE(write_tester.IsRejected());
+  ASSERT_EQ(udp_writable_stream_wrapper->GetState(),
+            StreamWrapper::State::kAborted);
+
+  ASSERT_TRUE(stream_creator->CloseCalledWith(/*error=*/true));
+}
+
 }  // namespace
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
index 4f00f3ee..9f020038 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
@@ -64,6 +64,7 @@
     MediaStreamVideoTrack* track,
     const VideoTrackAdapterSettings& track_adapter_settings,
     const VideoCaptureDeliverFrameCB& frame_callback,
+    const VideoCaptureNotifyFrameDroppedCB& notify_frame_dropped_callback,
     const EncodedVideoFrameCB& encoded_frame_callback,
     const VideoTrackSettingsCallback& settings_callback,
     const VideoTrackFormatCallback& format_callback,
@@ -73,11 +74,11 @@
   tracks_.push_back(track);
   secure_tracker_.Add(track, true);
 
-  pending_tracks_.push_back(PendingTrackInfo(
-      track, frame_callback, encoded_frame_callback, settings_callback,
-      format_callback,
+  pending_tracks_.push_back(PendingTrackInfo{
+      track, frame_callback, notify_frame_dropped_callback,
+      encoded_frame_callback, settings_callback, format_callback,
       std::make_unique<VideoTrackAdapterSettings>(track_adapter_settings),
-      std::move(callback)));
+      std::move(callback)});
 
   switch (state_) {
     case NEW: {
@@ -457,6 +458,7 @@
     if (result == mojom::blink::MediaStreamRequestResult::OK) {
       GetTrackAdapter()->AddTrack(
           track_info.track, track_info.frame_callback,
+          track_info.notify_frame_dropped_callback,
           track_info.encoded_frame_callback, track_info.settings_callback,
           track_info.format_callback, *track_info.adapter_settings);
       UpdateTrackSettings(track_info.track, *track_info.adapter_settings);
@@ -558,28 +560,4 @@
   return track_adapter_;
 }
 
-MediaStreamVideoSource::PendingTrackInfo::PendingTrackInfo(
-    MediaStreamVideoTrack* track,
-    const VideoCaptureDeliverFrameCB& frame_callback,
-    const EncodedVideoFrameCB& encoded_frame_callback,
-    const VideoTrackSettingsCallback& settings_callback,
-    const VideoTrackFormatCallback& format_callback,
-    std::unique_ptr<VideoTrackAdapterSettings> adapter_settings,
-    ConstraintsOnceCallback callback)
-    : track(track),
-      frame_callback(frame_callback),
-      encoded_frame_callback(encoded_frame_callback),
-      settings_callback(settings_callback),
-      format_callback(format_callback),
-      adapter_settings(std::move(adapter_settings)),
-      callback(std::move(callback)) {}
-
-MediaStreamVideoSource::PendingTrackInfo::PendingTrackInfo(
-    PendingTrackInfo&& other) = default;
-MediaStreamVideoSource::PendingTrackInfo&
-MediaStreamVideoSource::PendingTrackInfo::operator=(
-    MediaStreamVideoSource::PendingTrackInfo&& other) = default;
-
-MediaStreamVideoSource::PendingTrackInfo::~PendingTrackInfo() {}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc
index 610e38c..cc59e081 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc
@@ -8,6 +8,7 @@
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "media/base/limits.h"
 #include "media/base/video_frame.h"
@@ -442,6 +443,34 @@
   sink.DisconnectFromTrack();
 }
 
+TEST_F(MediaStreamVideoSourceTest, NotifyFrameDropped) {
+  constexpr int kMaxFps = 10;
+  WebMediaStreamTrack track = CreateTrackAndStartSource(640, 480, kMaxFps);
+  MockMediaStreamVideoSink sink;
+  sink.ConnectToTrack(track);
+  MediaStreamVideoTrack* native_track = MediaStreamVideoTrack::From(track);
+  native_track->SetSinkNotifyFrameDroppedCallback(
+      &sink, sink.GetNotifyFrameDroppedCB());
+
+  // Drive two frames through whose timestamps are spaced too close for the max
+  // frame rate. The last one should be dropped and cause a notification.
+  base::RunLoop run_loop;
+  base::OnceClosure quit_closure = run_loop.QuitClosure();
+  EXPECT_CALL(sink, OnNotifyFrameDropped).WillOnce([&] {
+    std::move(quit_closure).Run();
+  });
+  scoped_refptr<media::VideoFrame> frame1 =
+      media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
+  frame1->set_timestamp(base::Milliseconds(10));
+  mock_source()->DeliverVideoFrame(frame1);
+  scoped_refptr<media::VideoFrame> frame2 =
+      media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
+  frame2->set_timestamp(base::Milliseconds(20));
+  mock_source()->DeliverVideoFrame(frame2);
+  run_loop.Run();
+  sink.DisconnectFromTrack();
+}
+
 TEST_F(MediaStreamVideoSourceTest, ReconfigureTrack) {
   WebMediaStreamTrack track = CreateTrackAndStartSource(
       640, 480, media::limits::kMaxFramesPerSecond - 2);
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
index 50af5d9..b495b870 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
@@ -39,6 +39,10 @@
     std::vector<scoped_refptr<media::VideoFrame>> scaled_video_frames,
     base::TimeTicks estimated_capture_time)>;
 
+// This alias mimics the definition of VideoCaptureNotifyFrameDroppedCB.
+using VideoCaptureNotifyFrameDroppedInternalCallback =
+    WTF::CrossThreadFunction<void()>;
+
 // Mimics blink::EncodedVideoFrameCB
 using EncodedVideoFrameInternalCallback =
     WTF::CrossThreadFunction<void(scoped_refptr<EncodedVideoFrame> frame,
@@ -94,6 +98,10 @@
   // Must be called on the main render thread.
   void AddCallback(VideoSinkId id, VideoCaptureDeliverFrameCB callback);
 
+  // Sets the frame dropped callback of the sink of frame |id].
+  void SetNotifyFrameDroppedCallback(VideoSinkId id,
+                                     VideoCaptureNotifyFrameDroppedCB callback);
+
   // Add |callback| to receive encoded video frames on the IO-thread.
   // Must be called on the main render thread.
   void AddEncodedCallback(VideoSinkId id, EncodedVideoFrameCB callback);
@@ -117,6 +125,10 @@
       std::vector<scoped_refptr<media::VideoFrame>> scaled_video_frames,
       base::TimeTicks estimated_capture_time);
 
+  // Triggers all registered dropped frame callbacks. Must be called on the
+  // IO-thread.
+  void NotifyFrameDroppedOnIO();
+
   // Triggers all encoded callbacks with |frame| and |estimated_capture_time|.
   // Must be called on the IO-thread.
   void DeliverEncodedVideoFrameOnIO(scoped_refptr<EncodedVideoFrame> frame,
@@ -130,9 +142,21 @@
 
  private:
   friend class WTF::ThreadSafeRefCounted<FrameDeliverer>;
+
+  // Struct containing sink id, frame delivery and frame dropped callbacks.
+  struct VideoIdCallbacks {
+    VideoSinkId id;
+    VideoCaptureDeliverFrameInternalCallback deliver_frame;
+    VideoCaptureNotifyFrameDroppedInternalCallback notify_frame_dropped;
+  };
+
   virtual ~FrameDeliverer();
   void AddCallbackOnIO(VideoSinkId id,
                        VideoCaptureDeliverFrameInternalCallback callback);
+  void SetNotifyFrameDroppedCallbackOnIO(
+      VideoSinkId id,
+      VideoCaptureNotifyFrameDroppedInternalCallback callback,
+      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
   void RemoveCallbackOnIO(
       VideoSinkId id,
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
@@ -171,9 +195,7 @@
   scoped_refptr<media::VideoFrame> black_frame_;
   bool emit_frame_drop_events_;
 
-  using VideoIdCallbackPair =
-      std::pair<VideoSinkId, VideoCaptureDeliverFrameInternalCallback>;
-  Vector<VideoIdCallbackPair> callbacks_;
+  Vector<VideoIdCallbacks> callbacks_;
   HashMap<VideoSinkId, EncodedVideoFrameInternalCallback> encoded_callbacks_;
 
   // Callbacks that will be invoked a single time when a crop-version
@@ -221,7 +243,40 @@
     VideoSinkId id,
     VideoCaptureDeliverFrameInternalCallback callback) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-  callbacks_.push_back(std::make_pair(id, std::move(callback)));
+  callbacks_.push_back(VideoIdCallbacks{id, std::move(callback),
+                                        CrossThreadBindRepeating([] {})});
+}
+
+void MediaStreamVideoTrack::FrameDeliverer::SetNotifyFrameDroppedCallback(
+    VideoSinkId id,
+    VideoCaptureNotifyFrameDroppedCB callback) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
+  PostCrossThreadTask(
+      *io_task_runner_, FROM_HERE,
+      CrossThreadBindOnce(&FrameDeliverer::SetNotifyFrameDroppedCallbackOnIO,
+                          WrapRefCounted(this), WTF::CrossThreadUnretained(id),
+                          CrossThreadBindRepeating(std::move(callback)),
+                          Thread::Current()->GetTaskRunner()));
+}
+
+void MediaStreamVideoTrack::FrameDeliverer::SetNotifyFrameDroppedCallbackOnIO(
+    VideoSinkId id,
+    VideoCaptureNotifyFrameDroppedInternalCallback callback,
+    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  DVLOG(1) << __func__;
+  for (auto& entry : callbacks_) {
+    if (entry.id == id) {
+      // Old callback destruction needs to happen on the specified task
+      // runner.
+      PostCrossThreadTask(
+          *task_runner, FROM_HERE,
+          CrossThreadBindOnce(
+              [](VideoCaptureNotifyFrameDroppedInternalCallback) {},
+              std::move(entry.notify_frame_dropped)));
+      entry.notify_frame_dropped = std::move(callback);
+    }
+  }
 }
 
 void MediaStreamVideoTrack::FrameDeliverer::AddEncodedCallback(
@@ -257,13 +312,15 @@
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   auto* it = callbacks_.begin();
   for (; it != callbacks_.end(); ++it) {
-    if (it->first == id) {
+    if (it->id == id) {
       // Callback destruction needs to happen on the specified task runner.
       PostCrossThreadTask(
           *task_runner, FROM_HERE,
           CrossThreadBindOnce(
-              [](VideoCaptureDeliverFrameInternalCallback callback) {},
-              std::move(it->second)));
+              [](VideoCaptureDeliverFrameInternalCallback frame,
+                 VideoCaptureNotifyFrameDroppedInternalCallback dropped) {},
+              std::move(it->deliver_frame),
+              std::move(it->notify_frame_dropped)));
       callbacks_.erase(it);
       return;
     }
@@ -420,9 +477,10 @@
     video_frame = GetBlackFrame(*frame);
     scaled_video_frames.clear();
   }
-  for (const auto& entry : callbacks_)
-    entry.second.Run(video_frame, scaled_video_frames, estimated_capture_time);
-
+  for (const auto& entry : callbacks_) {
+    entry.deliver_frame.Run(video_frame, scaled_video_frames,
+                            estimated_capture_time);
+  }
   // The delay on refresh timer is reset each time a frame is received so that
   // it will not fire for at least an additional period. This means refresh
   // frames will only be requested when the source has halted delivery (e.g., a
@@ -438,6 +496,13 @@
   MaybeInvokeNewCropVersionCallbacksOnIO(crop_version);
 }
 
+void MediaStreamVideoTrack::FrameDeliverer::NotifyFrameDroppedOnIO() {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  DVLOG(1) << __func__;
+  for (const auto& entry : callbacks_)
+    entry.notify_frame_dropped.Run();
+}
+
 void MediaStreamVideoTrack::FrameDeliverer::DeliverEncodedVideoFrameOnIO(
     scoped_refptr<EncodedVideoFrame> frame,
     base::TimeTicks estimated_capture_time) {
@@ -541,6 +606,9 @@
           &MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO,
           frame_deliverer_)),
       ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+          &MediaStreamVideoTrack::FrameDeliverer::NotifyFrameDroppedOnIO,
+          frame_deliverer_)),
+      ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
           &MediaStreamVideoTrack::FrameDeliverer::DeliverEncodedVideoFrameOnIO,
           frame_deliverer_)),
       media::BindToCurrentLoop(WTF::BindRepeating(
@@ -583,6 +651,9 @@
           &MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO,
           frame_deliverer_)),
       ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+          &MediaStreamVideoTrack::FrameDeliverer::NotifyFrameDroppedOnIO,
+          frame_deliverer_)),
+      ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
           &MediaStreamVideoTrack::FrameDeliverer::DeliverEncodedVideoFrameOnIO,
           frame_deliverer_)),
       media::BindToCurrentLoop(WTF::BindRepeating(
@@ -650,6 +721,14 @@
     StartTimerForRequestingFrames();
 }
 
+void MediaStreamVideoTrack::SetSinkNotifyFrameDroppedCallback(
+    WebMediaStreamSink* sink,
+    const VideoCaptureNotifyFrameDroppedCB& callback) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
+  DVLOG(1) << __func__;
+  frame_deliverer_->SetNotifyFrameDroppedCallback(sink, callback);
+}
+
 void MediaStreamVideoTrack::AddEncodedSink(WebMediaStreamSink* sink,
                                            EncodedVideoFrameCB callback) {
   DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h
index 414b90f..8308ea31 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h
@@ -99,6 +99,12 @@
                const VideoCaptureDeliverFrameCB& callback,
                MediaStreamVideoSink::IsSecure is_secure,
                MediaStreamVideoSink::UsesAlpha uses_alpha);
+  // Sets |sink|'s dropped frame notification callback which will receive calls
+  // on the IO thread. |callback| will be reset on the render thread.
+  // Note: the method needs to be called after a sink has been added.
+  void SetSinkNotifyFrameDroppedCallback(
+      WebMediaStreamSink* sink,
+      const VideoCaptureNotifyFrameDroppedCB& callback);
   void RemoveSink(WebMediaStreamSink* sink);
 
   // Returns the number of currently connected sinks.
diff --git a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.cc b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.cc
index 1094c470..2f82600c 100644
--- a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.cc
+++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.cc
@@ -30,6 +30,13 @@
                          weak_factory_.GetWeakPtr()));
 }
 
+VideoCaptureNotifyFrameDroppedCB
+MockMediaStreamVideoSink::GetNotifyFrameDroppedCB() {
+  return media::BindToCurrentLoop(
+      WTF::BindRepeating(&MockMediaStreamVideoSink::NotifyFrameDropped,
+                         weak_factory_.GetWeakPtr()));
+}
+
 void MockMediaStreamVideoSink::DeliverVideoFrame(
     scoped_refptr<media::VideoFrame> frame,
     std::vector<scoped_refptr<media::VideoFrame>> scaled_frames,
@@ -47,6 +54,10 @@
   OnEncodedVideoFrame(estimated_capture_time);
 }
 
+void MockMediaStreamVideoSink::NotifyFrameDropped() {
+  OnNotifyFrameDropped();
+}
+
 void MockMediaStreamVideoSink::OnReadyStateChanged(
     blink::WebMediaStreamSource::ReadyState state) {
   state_ = state;
diff --git a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.h b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.h
index 48e5b27..8fc3b31 100644
--- a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.h
+++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_sink.h
@@ -53,8 +53,12 @@
   MOCK_METHOD(void, OnVideoFrame, (base::TimeTicks));
   MOCK_METHOD(void, OnEncodedVideoFrame, (base::TimeTicks));
 
+  // Triggered when a frame is dropped.
+  MOCK_METHOD(void, OnNotifyFrameDropped, ());
+
   VideoCaptureDeliverFrameCB GetDeliverFrameCB();
   EncodedVideoFrameCB GetDeliverEncodedVideoFrameCB();
+  VideoCaptureNotifyFrameDroppedCB GetNotifyFrameDroppedCB();
 
   int number_of_frames() const { return number_of_frames_; }
   media::VideoPixelFormat format() const { return format_; }
@@ -78,6 +82,7 @@
       base::TimeTicks estimated_capture_time);
   void DeliverEncodedVideoFrame(scoped_refptr<EncodedVideoFrame> frame,
                                 base::TimeTicks estimated_capture_time);
+  void NotifyFrameDropped();
 
   MediaStreamVideoSink::UsesAlpha uses_alpha_ =
       MediaStreamVideoSink::UsesAlpha::kDefault;
diff --git a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
index bfc1c0ac..492358a 100644
--- a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
@@ -72,11 +72,6 @@
   is_suspended_ = !has_consumers;
 }
 
-VideoCaptureFeedbackCB MockMediaStreamVideoSource::GetFeedbackCallback() const {
-  return WTF::BindRepeating(&MockMediaStreamVideoSource::OnFrameFeedback,
-                            WTF::Unretained(this));
-}
-
 base::WeakPtr<MediaStreamVideoSource> MockMediaStreamVideoSource::GetWeakPtr()
     const {
   return weak_factory_.GetWeakPtr();
diff --git a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
index f2764b6fb..17f9431 100644
--- a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
+++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
@@ -32,7 +32,6 @@
   MOCK_METHOD1(SetCanDiscardAlpha, void(bool can_discard_alpha));
   MOCK_CONST_METHOD0(SupportsEncodedOutput, bool());
   MOCK_METHOD1(OnFrameDropped, void(media::VideoCaptureFrameDropReason));
-  MOCK_CONST_METHOD1(OnFrameFeedback, void(const media::VideoCaptureFeedback&));
   MOCK_METHOD3(Crop,
                void(const base::Token&,
                     uint32_t,
@@ -82,7 +81,6 @@
   absl::optional<media::VideoCaptureParams> GetCurrentCaptureParams()
       const override;
   void OnHasConsumers(bool has_consumers) override;
-  VideoCaptureFeedbackCB GetFeedbackCallback() const override;
   base::WeakPtr<MediaStreamVideoSource> GetWeakPtr() const override;
 
  protected:
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
index 29511db0..2601a92 100644
--- a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
+++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
@@ -137,6 +137,8 @@
  public:
   struct VideoTrackCallbacks {
     VideoCaptureDeliverFrameInternalCallback frame_callback;
+    VideoCaptureNotifyFrameDroppedInternalCallback
+        notify_frame_dropped_callback;
     DeliverEncodedVideoFrameInternalCallback encoded_frame_callback;
     VideoTrackSettingsInternalCallback settings_callback;
     VideoTrackFormatInternalCallback format_callback;
@@ -159,6 +161,8 @@
   void AddCallbacks(
       const MediaStreamVideoTrack* track,
       VideoCaptureDeliverFrameInternalCallback frame_callback,
+      VideoCaptureNotifyFrameDroppedInternalCallback
+          notify_frame_dropped_callback,
       DeliverEncodedVideoFrameInternalCallback encoded_frame_callback,
       VideoTrackSettingsInternalCallback settings_callback,
       VideoTrackFormatInternalCallback format_callback);
@@ -179,6 +183,9 @@
       const base::TimeTicks& estimated_capture_time,
       bool is_device_rotated);
 
+  // Deliver an indication that a frame was dropped.
+  void DoNotifyFrameDropped(media::VideoCaptureFrameDropReason reason);
+
   void DeliverEncodedVideoFrame(scoped_refptr<EncodedVideoFrame> frame,
                                 base::TimeTicks estimated_capture_time);
 
@@ -270,6 +277,8 @@
 void VideoTrackAdapter::VideoFrameResolutionAdapter::AddCallbacks(
     const MediaStreamVideoTrack* track,
     VideoCaptureDeliverFrameInternalCallback frame_callback,
+    VideoCaptureNotifyFrameDroppedInternalCallback
+        notify_frame_dropped_callback,
     DeliverEncodedVideoFrameInternalCallback encoded_frame_callback,
     VideoTrackSettingsInternalCallback settings_callback,
     VideoTrackFormatInternalCallback format_callback) {
@@ -285,8 +294,9 @@
   }
 
   VideoTrackCallbacks track_callbacks = {
-      std::move(frame_callback), std::move(encoded_frame_callback),
-      std::move(settings_callback), std::move(format_callback)};
+      std::move(frame_callback), std::move(notify_frame_dropped_callback),
+      std::move(encoded_frame_callback), std::move(settings_callback),
+      std::move(format_callback)};
   callbacks_.emplace(track, std::move(track_callbacks));
 }
 
@@ -334,7 +344,7 @@
 
   auto frame_drop_reason = media::VideoCaptureFrameDropReason::kNone;
   if (MaybeDropFrame(*video_frame, frame_rate, &frame_drop_reason)) {
-    PostFrameDroppedToMainTaskRunner(frame_drop_reason);
+    DoNotifyFrameDropped(frame_drop_reason);
     return;
   }
 
@@ -436,10 +446,19 @@
   }
 }
 
+void VideoTrackAdapter::VideoFrameResolutionAdapter::DoNotifyFrameDropped(
+    media::VideoCaptureFrameDropReason reason) {
+  DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+  PostFrameDroppedToMainTaskRunner(reason);
+  for (const auto& callback : callbacks_)
+    callback.second.notify_frame_dropped_callback.Run();
+}
+
 bool VideoTrackAdapter::VideoFrameResolutionAdapter::MaybeDropFrame(
     const media::VideoFrame& frame,
     float source_frame_rate,
     media::VideoCaptureFrameDropReason* reason) {
+  DVLOG(3) << __func__;
   DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
 
   // Do not drop frames if max frame rate hasn't been specified.
@@ -456,6 +475,7 @@
 
   // Check if the time since the last frame is completely off.
   if (delta_ms.is_negative() || delta_ms > kMaxTimeInMsBetweenFrames) {
+    DVLOG(3) << " reset timestamps";
     // Reset |last_time_stamp_| and fps calculation.
     last_time_stamp_ = frame.timestamp();
     frame_rate_ = MediaStreamVideoSource::kDefaultFrameRate;
@@ -482,6 +502,7 @@
   // Calculate the frame rate using a simple AR filter.
   // Use a simple filter with 0.1 weight of the current sample.
   frame_rate_ = 100 / delta_ms.InMillisecondsF() + 0.9 * frame_rate_;
+  DVLOG(3) << " delta_ms " << delta_ms << " frame_rate_ " << frame_rate_;
 
   // Prefer to not drop frames.
   if (settings_.max_frame_rate() + 0.5f > frame_rate_)
@@ -562,12 +583,14 @@
   DCHECK(!monitoring_frame_rate_timer_);
 }
 
-void VideoTrackAdapter::AddTrack(const MediaStreamVideoTrack* track,
-                                 VideoCaptureDeliverFrameCB frame_callback,
-                                 EncodedVideoFrameCB encoded_frame_callback,
-                                 VideoTrackSettingsCallback settings_callback,
-                                 VideoTrackFormatCallback format_callback,
-                                 const VideoTrackAdapterSettings& settings) {
+void VideoTrackAdapter::AddTrack(
+    const MediaStreamVideoTrack* track,
+    VideoCaptureDeliverFrameCB frame_callback,
+    VideoCaptureNotifyFrameDroppedCB notify_frame_dropped_callback,
+    EncodedVideoFrameCB encoded_frame_callback,
+    VideoTrackSettingsCallback settings_callback,
+    VideoTrackFormatCallback format_callback,
+    const VideoTrackAdapterSettings& settings) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   PostCrossThreadTask(
@@ -576,6 +599,7 @@
           &VideoTrackAdapter::AddTrackOnIO, WTF::CrossThreadUnretained(this),
           WTF::CrossThreadUnretained(track),
           CrossThreadBindRepeating(std::move(frame_callback)),
+          CrossThreadBindRepeating(std::move(notify_frame_dropped_callback)),
           CrossThreadBindRepeating(std::move(encoded_frame_callback)),
           CrossThreadBindRepeating(std::move(settings_callback)),
           CrossThreadBindRepeating(std::move(format_callback)), settings));
@@ -584,6 +608,8 @@
 void VideoTrackAdapter::AddTrackOnIO(
     const MediaStreamVideoTrack* track,
     VideoCaptureDeliverFrameInternalCallback frame_callback,
+    VideoCaptureNotifyFrameDroppedInternalCallback
+        notify_frame_dropped_callback,
     DeliverEncodedVideoFrameInternalCallback encoded_frame_callback,
     VideoTrackSettingsInternalCallback settings_callback,
     VideoTrackFormatInternalCallback format_callback,
@@ -602,9 +628,11 @@
     adapters_.push_back(adapter);
   }
 
-  adapter->AddCallbacks(
-      track, std::move(frame_callback), std::move(encoded_frame_callback),
-      std::move(settings_callback), std::move(format_callback));
+  adapter->AddCallbacks(track, std::move(frame_callback),
+                        std::move(notify_frame_dropped_callback),
+                        std::move(encoded_frame_callback),
+                        std::move(settings_callback),
+                        std::move(format_callback));
 }
 
 void VideoTrackAdapter::RemoveTrack(const MediaStreamVideoTrack* track) {
@@ -792,6 +820,7 @@
   // If the track was found, re-add it with new settings.
   if (track_callbacks.frame_callback) {
     AddTrackOnIO(track, std::move(track_callbacks.frame_callback),
+                 std::move(track_callbacks.notify_frame_dropped_callback),
                  std::move(track_callbacks.encoded_frame_callback),
                  std::move(track_callbacks.settings_callback),
                  std::move(track_callbacks.format_callback), settings);
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter.h b/third_party/blink/renderer/modules/mediastream/video_track_adapter.h
index 3f99d04..b1d085f 100644
--- a/third_party/blink/renderer/modules/mediastream/video_track_adapter.h
+++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.h
@@ -56,6 +56,7 @@
   // |on_muted_state_callback|.
   void AddTrack(const MediaStreamVideoTrack* track,
                 VideoCaptureDeliverFrameCB frame_callback,
+                VideoCaptureNotifyFrameDroppedCB notify_frame_dropped_callback,
                 EncodedVideoFrameCB encoded_frame_callback,
                 VideoTrackSettingsCallback settings_callback,
                 VideoTrackFormatCallback track_callback,
@@ -116,6 +117,8 @@
           scoped_refptr<media::VideoFrame> video_frame,
           std::vector<scoped_refptr<media::VideoFrame>> scaled_video_frames,
           base::TimeTicks estimated_capture_time)>;
+  using VideoCaptureNotifyFrameDroppedInternalCallback =
+      WTF::CrossThreadFunction<void()>;
   using DeliverEncodedVideoFrameInternalCallback =
       WTF::CrossThreadFunction<void(
           scoped_refptr<EncodedVideoFrame> video_frame,
@@ -127,6 +130,8 @@
   void AddTrackOnIO(
       const MediaStreamVideoTrack* track,
       VideoCaptureDeliverFrameInternalCallback frame_callback,
+      VideoCaptureNotifyFrameDroppedInternalCallback
+          notify_frame_dropped_callback,
       DeliverEncodedVideoFrameInternalCallback encoded_frame_callback,
       VideoTrackSettingsInternalCallback settings_callback,
       VideoTrackFormatInternalCallback track_callback,
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc
index abafe955..e02ac9e 100644
--- a/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc
+++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc
@@ -262,6 +262,9 @@
             base::BindRepeating(&VideoTrackAdapterFixtureTest::OnFrameDelivered,
                                 base::Unretained(this)),
             base::BindRepeating(
+                &VideoTrackAdapterFixtureTest::OnNotifyFrameDropped,
+                base::Unretained(this)),
+            base::BindRepeating(
                 &VideoTrackAdapterFixtureTest::OnEncodedVideoFrameDelivered,
                 base::Unretained(this)),
             base::DoNothing(), base::DoNothing(), adapter_settings));
@@ -305,6 +308,7 @@
   MOCK_METHOD2(OnEncodedVideoFrameDelivered,
                void(scoped_refptr<EncodedVideoFrame>,
                     base::TimeTicks estimated_capture_time));
+  MOCK_METHOD0(OnNotifyFrameDropped, void());
 
   ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport>
       platform_support_;
@@ -437,6 +441,7 @@
       base::BindOnce(
           &VideoTrackAdapter::AddTrack, adapter_, second_track.get(),
           /*frame_callback=*/base::DoNothing(),
+          /*notify_dropped_frame_callback=*/base::DoNothing(),
           /*encoded_frame_callback=*/base::DoNothing(),
           /*settings_callback=*/base::BindLambdaForTesting(check_dimensions),
           /*track_callback=*/base::DoNothing(), adapter_settings));
@@ -476,6 +481,7 @@
           track.get(),
           base::BindRepeating(&VideoTrackAdapterEncodedTest::OnFrameDelivered,
                               base::Unretained(this)),
+          base::DoNothing(),
           base::BindRepeating(
               &VideoTrackAdapterEncodedTest::OnEncodedVideoFrameDelivered,
               base::Unretained(this)),
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
index fc79f37..f76e82c9d 100644
--- a/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
+++ b/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
@@ -99,6 +99,8 @@
       std::vector<scoped_refptr<media::VideoFrame>> scaled_frames,
       base::TimeTicks estimated_capture_time);
 
+  void OnNotifyVideoFrameDroppedOnIO();
+
  private:
   friend class WTF::ThreadSafeRefCounted<WebRtcVideoSourceAdapter>;
 
@@ -106,6 +108,8 @@
       scoped_refptr<media::VideoFrame> frame,
       std::vector<scoped_refptr<media::VideoFrame>> scaled_frames);
 
+  void OnNotifyVideoFrameDroppedOnNetworkThread();
+
   virtual ~WebRtcVideoSourceAdapter();
 
   scoped_refptr<base::SingleThreadTaskRunner> render_task_runner_;
@@ -175,6 +179,17 @@
 }
 
 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
+    OnNotifyVideoFrameDroppedOnIO() {
+  DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+  DVLOG(1) << __func__;
+  PostCrossThreadTask(
+      *libjingle_network_task_runner_.get(), FROM_HERE,
+      CrossThreadBindOnce(
+          &WebRtcVideoSourceAdapter::OnNotifyVideoFrameDroppedOnNetworkThread,
+          WrapRefCounted(this)));
+}
+
+void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
     OnVideoFrameOnNetworkThread(
         scoped_refptr<media::VideoFrame> frame,
         std::vector<scoped_refptr<media::VideoFrame>> scaled_frames) {
@@ -184,6 +199,14 @@
     video_source_->OnFrameCaptured(std::move(frame), std::move(scaled_frames));
 }
 
+void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
+    OnNotifyVideoFrameDroppedOnNetworkThread() {
+  DCHECK(libjingle_network_task_runner_->BelongsToCurrentThread());
+  base::AutoLock auto_lock(video_source_stop_lock_);
+  if (video_source_)
+    video_source_->OnNotifyFrameDropped();
+}
+
 MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink(
     MediaStreamComponent* component,
     PeerConnectionDependencyFactory* factory,
@@ -235,6 +258,10 @@
           &WebRtcVideoSourceAdapter::OnVideoFrameOnIO, source_adapter_)),
       MediaStreamVideoSink::IsSecure::kNo,
       MediaStreamVideoSink::UsesAlpha::kNo);
+  video_track->SetSinkNotifyFrameDroppedCallback(
+      this, ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+                &WebRtcVideoSourceAdapter::OnNotifyVideoFrameDroppedOnIO,
+                source_adapter_)));
 
   DVLOG(3) << "MediaStreamVideoWebRtcSink ctor() : is_screencast "
            << is_screencast;
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc
index d5c619fb..c30e660 100644
--- a/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
 #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace blink {
 
@@ -21,6 +22,12 @@
 using ::testing::Mock;
 using ::testing::Optional;
 
+class MockWebRtcVideoSink : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
+ public:
+  MOCK_METHOD(void, OnFrame, (const webrtc::VideoFrame&), (override));
+  MOCK_METHOD(void, OnDiscardedFrame, (), (override));
+};
+
 class MockPeerConnectionDependencyFactory2
     : public MockPeerConnectionDependencyFactory {
  public:
@@ -42,14 +49,18 @@
 
 class MediaStreamVideoWebRtcSinkTest : public ::testing::Test {
  public:
+  ~MediaStreamVideoWebRtcSinkTest() override {
+    registry_.reset();
+    component_ = nullptr;
+    dependency_factory_ = nullptr;
+    ThreadState::Current()->CollectAllGarbageForTesting();
+  }
+
   MockMediaStreamVideoSource* SetVideoTrack() {
     registry_.Init();
     MockMediaStreamVideoSource* source =
         registry_.AddVideoTrack("test video track");
-    auto video_components = registry_.test_stream()->VideoComponents();
-    component_ = video_components[0];
-    // TODO(hta): Verify that component_ is valid. When constraints produce
-    // no valid format, using the track will cause a crash.
+    CompleteSetVideoTrack();
     return source;
   }
 
@@ -58,10 +69,18 @@
     registry_.AddVideoTrack("test video track",
                             blink::VideoTrackAdapterSettings(), noise_reduction,
                             false, 0.0);
-    auto video_components = registry_.test_stream()->VideoComponents();
-    component_ = video_components[0];
-    // TODO(hta): Verify that component_ is valid. When constraints produce
-    // no valid format, using the track will cause a crash.
+    CompleteSetVideoTrack();
+  }
+
+  MockMediaStreamVideoSource* SetVideoTrackWithMaxFramerate(
+      int max_frame_rate) {
+    registry_.Init();
+    MockMediaStreamVideoSource* source = registry_.AddVideoTrack(
+        "test video track",
+        blink::VideoTrackAdapterSettings(gfx::Size(100, 100), max_frame_rate),
+        absl::nullopt, false, 0.0);
+    CompleteSetVideoTrack();
+    return source;
   }
 
  protected:
@@ -71,6 +90,13 @@
   ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
 
  private:
+  void CompleteSetVideoTrack() {
+    auto video_components = registry_.test_stream()->VideoComponents();
+    component_ = video_components[0];
+    // TODO(hta): Verify that component_ is valid. When constraints produce
+    // no valid format, using the track will cause a crash.
+  }
+
   blink::MockMediaStreamRegistry registry_;
 };
 
@@ -83,6 +109,34 @@
   EXPECT_FALSE(my_sink.SourceNeedsDenoisingForTesting());
 }
 
+TEST_F(MediaStreamVideoWebRtcSinkTest, NotifiesFrameDropped) {
+  MockMediaStreamVideoSource* mock_source = SetVideoTrackWithMaxFramerate(10);
+  mock_source->StartMockedSource();
+  blink::MediaStreamVideoWebRtcSink my_sink(
+      component_, dependency_factory_.Get(),
+      blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+  webrtc::VideoTrackInterface* webrtc_track = my_sink.webrtc_video_track();
+  MockWebRtcVideoSink mock_sink;
+  webrtc_track->GetSource()->AddOrUpdateSink(&mock_sink, rtc::VideoSinkWants());
+
+  // Drive two frames too closely spaced through. Expect one frame drop.
+  base::RunLoop run_loop;
+  base::OnceClosure quit_closure = run_loop.QuitClosure();
+  EXPECT_CALL(mock_sink, OnDiscardedFrame).WillOnce([&] {
+    std::move(quit_closure).Run();
+  });
+  scoped_refptr<media::VideoFrame> frame1 =
+      media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
+  frame1->set_timestamp(base::Milliseconds(1));
+  mock_source->DeliverVideoFrame(frame1);
+  scoped_refptr<media::VideoFrame> frame2 =
+      media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
+  frame2->set_timestamp(base::Milliseconds(2));
+  mock_source->DeliverVideoFrame(frame2);
+  platform_->RunUntilIdle();
+  run_loop.Run();
+}
+
 TEST_F(MediaStreamVideoWebRtcSinkTest,
        ForwardsConstraintsChangeToWebRtcVideoTrackSourceProxy) {
   Persistent<MockPeerConnectionDependencyFactory2> dependency_factory2 =
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc
index ebba190c..a62a18c 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc
+++ b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc
@@ -335,9 +335,9 @@
 };
 
 MockPeerConnectionDependencyFactory::MockPeerConnectionDependencyFactory()
-    : signaling_thread_("MockPCFactory WebRtc Signaling Thread") {
+    : thread_("MockPCFactory WebRtc Signaling/Networking Thread") {
   EnsureWebRtcAudioDeviceImpl();
-  CHECK(signaling_thread_.Start());
+  CHECK(thread_.Start());
 }
 
 MockPeerConnectionDependencyFactory::~MockPeerConnectionDependencyFactory() {}
@@ -381,7 +381,12 @@
 
 scoped_refptr<base::SingleThreadTaskRunner>
 MockPeerConnectionDependencyFactory::GetWebRtcSignalingTaskRunner() {
-  return signaling_thread_.task_runner();
+  return thread_.task_runner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+MockPeerConnectionDependencyFactory::GetWebRtcNetworkTaskRunner() {
+  return thread_.task_runner();
 }
 
 void MockPeerConnectionDependencyFactory::SetFailToCreateSessionDescription(
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h
index 56f1408..51aa430c 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h
+++ b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h
@@ -189,6 +189,8 @@
                                                     int sdp_mline_index,
                                                     const String& sdp) override;
 
+  scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcNetworkTaskRunner()
+      override;
   scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcSignalingTaskRunner()
       override;
 
@@ -199,7 +201,7 @@
 
  private:
   // TODO(crbug.com/787254): Replace with the appropriate Blink class.
-  base::Thread signaling_thread_;
+  base::Thread thread_;
   bool fail_to_create_session_description_ = false;
 };
 
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h
index b8ad4b93a..bcacc27 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h
@@ -137,7 +137,8 @@
   // network threads (rtc::Thread), if they exist. These threads are ensured to
   // exist after an RTCPeerConnectionHandler has been Initialized().
   scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcWorkerTaskRunner();
-  scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcNetworkTaskRunner();
+  virtual scoped_refptr<base::SingleThreadTaskRunner>
+  GetWebRtcNetworkTaskRunner();
 
   virtual scoped_refptr<base::SingleThreadTaskRunner>
   GetWebRtcSignalingTaskRunner();
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
index 6c28f056..cfc41475 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
@@ -95,11 +95,22 @@
   }
 
   if (current_swap_buffer_) {
-    // Ensure we wait for previous WebGPU commands before destroying the shared
-    // image.
     if (auto context_provider = GetContextProviderWeakPtr()) {
       gpu::webgpu::WebGPUInterface* webgpu =
           context_provider->ContextProvider()->WebGPUInterface();
+
+      // Dissociate mailbox to avoid memory leaks.
+      if (wire_device_id_ && wire_texture_id_) {
+        webgpu->DissociateMailbox(wire_texture_id_, wire_texture_generation_);
+
+        wire_device_id_ = 0;
+        wire_device_generation_ = 0;
+        wire_texture_id_ = 0;
+        wire_texture_generation_ = 0;
+      }
+
+      // Ensure we wait for previous WebGPU commands before destroying the
+      // shared image.
       webgpu->GenUnverifiedSyncTokenCHROMIUM(
           current_swap_buffer_->access_finished_token.GetData());
     }
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
index 28e0297b..1375a9c 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
@@ -29,6 +29,24 @@
 
   MOCK_METHOD1(ReserveTexture, gpu::webgpu::ReservedTexture(WGPUDevice device));
 
+  // Could have used mock, but we only care about number of associated
+  // mailboxes, so use override for now
+  void AssociateMailbox(GLuint,
+                        GLuint,
+                        GLuint,
+                        GLuint,
+                        GLuint,
+                        gpu::webgpu::MailboxFlags,
+                        const GLbyte*) override {
+    num_associated_mailboxes++;
+  }
+  void DissociateMailbox(GLuint, GLuint) override {
+    num_associated_mailboxes--;
+  }
+  void DissociateMailboxForPresent(GLuint, GLuint, GLuint, GLuint) override {
+    num_associated_mailboxes--;
+  }
+
   // It is hard to use GMock with SyncTokens represented as GLByte*, instead we
   // remember which were the last sync tokens generated or waited upon.
   void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) override {
@@ -52,6 +70,8 @@
   gpu::SyncToken most_recent_generated_token;
   gpu::SyncToken most_recent_waited_token;
 
+  int num_associated_mailboxes = 0;
+
  private:
   uint64_t token_id_ = 42;
 };
@@ -412,4 +432,64 @@
                                                       &release_callback_2));
 }
 
+// Test that checks mailbox is dissociated when Neuter() is called.
+TEST_F(WebGPUSwapBufferProviderTest, VerifyMailboxDissociationOnNeuter) {
+  const gfx::Size kSize(10, 10);
+
+  viz::TransferableResource resource1;
+  gpu::webgpu::ReservedTexture reservation1 = {
+      reinterpret_cast<WGPUTexture>(&resource1), 1, 1, 1, 1};
+  viz::ReleaseCallback release_callback1;
+
+  viz::TransferableResource resource2;
+  gpu::webgpu::ReservedTexture reservation2 = {
+      reinterpret_cast<WGPUTexture>(&resource2), 2, 2, 1, 1};
+  viz::ReleaseCallback release_callback2;
+
+  // Produce and prepare transferable resource
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation1));
+  provider_->GetNewTexture(kSize);
+  EXPECT_EQ(webgpu_->num_associated_mailboxes, 1);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource1,
+                                                     &release_callback1));
+  EXPECT_EQ(webgpu_->num_associated_mailboxes, 0);
+
+  // Produce 2nd resource but this time neuters the provider. Mailbox must also
+  // be dissociated.
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation2));
+  provider_->GetNewTexture(kSize);
+  EXPECT_EQ(webgpu_->num_associated_mailboxes, 1);
+
+  provider_->Neuter();
+  EXPECT_EQ(webgpu_->num_associated_mailboxes, 0);
+}
+
+// Test that checks mailbox is not dissociated twice when both
+// PrepareTransferableResource() and Neuter() are called.
+TEST_F(WebGPUSwapBufferProviderTest, VerifyNoDoubleMailboxDissociation) {
+  const gfx::Size kSize(10, 10);
+
+  viz::TransferableResource resource1;
+  gpu::webgpu::ReservedTexture reservation1 = {
+      reinterpret_cast<WGPUTexture>(&resource1), 1, 1, 1, 1};
+  viz::ReleaseCallback release_callback1;
+
+  // Produce and prepare transferable resource
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation1));
+  provider_->GetNewTexture(kSize);
+  EXPECT_EQ(webgpu_->num_associated_mailboxes, 1);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource1,
+                                                     &release_callback1));
+  EXPECT_EQ(webgpu_->num_associated_mailboxes, 0);
+
+  // Calling Neuter() won't dissociate mailbox again.
+  provider_->Neuter();
+  EXPECT_EQ(webgpu_->num_associated_mailboxes, 0);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc b/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
index e27c9ff3..f64f43c 100644
--- a/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
+++ b/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
@@ -272,6 +272,11 @@
                translated_camera_time_us);
 }
 
+void WebRtcVideoTrackSource::OnNotifyFrameDropped() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  OnFrameDropped();
+}
+
 WebRtcVideoTrackSource::FrameAdaptationParams
 WebRtcVideoTrackSource::ComputeAdaptationParams(int width,
                                                 int height,
diff --git a/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h b/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h
index 7b0c39f..64582b7 100644
--- a/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h
+++ b/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.h
@@ -61,6 +61,7 @@
   void OnFrameCaptured(
       scoped_refptr<media::VideoFrame> frame,
       std::vector<scoped_refptr<media::VideoFrame>> scaled_frames);
+  void OnNotifyFrameDropped();
 
   using webrtc::VideoTrackSourceInterface::AddOrUpdateSink;
   using webrtc::VideoTrackSourceInterface::RemoveSink;
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index 0cfc0eb..61ec6f623 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: 73380548ab5f7f6fe47ece278005b500e45f8c4d
+Version: bd23d172241f5bdd356368a1ef05a649d8a79bad
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 2afe2f5..7d824fd 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
@@ -15299,6 +15299,15 @@
      ]
     ]
    },
+   "window-placement": {
+    "fullscreen-companion-window-manual.tentative.https.html": [
+     "fe82916aa26cc488e23567d4a2ccfeff33884ed4",
+     [
+      null,
+      {}
+     ]
+    ]
+   },
    "xhr": {
     "send-authentication-existing-session-manual.htm": [
      "a80efd6e8436408db15d8019beef3abc0dfd0ab9",
@@ -336357,7 +336366,13 @@
     "README.md": [
      "2a7df11c32c2748bd63b7e427bea18079cb432ff",
      []
-    ]
+    ],
+    "resources": {
+     "helpers.js": [
+      "886098923d80e801dce753eecc91f723291bc87c",
+      []
+     ]
+    }
    },
    "workers": {
     "DIR_METADATA": [
@@ -380829,7 +380844,7 @@
        ]
       ],
       "grid-shorthand-invalid.html": [
-       "cdcbb4c5443d1e9e46e85985a25e702c94b88f4d",
+       "e5dbe7821c11f45d5663c6ebdf1d5261dbd493c6",
        [
         null,
         {}
@@ -567704,7 +567719,7 @@
    },
    "window-placement": {
     "multi-screen-window-open.tentative.https.html": [
-     "00c00d904507a1fae26b3df3ff25eb15c20f294d",
+     "c9973fc490e03633253f930c750883bc8e594f94",
      [
       null,
       {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-invalid.html
index cdcbb4c5..e5dbe78 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-invalid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-invalid.html
@@ -46,6 +46,7 @@
 test_invalid_value("grid", 'auto-flow / auto-flow');
 test_invalid_value("grid", 'auto-flow 1fr / auto-flow 1fr');
 test_invalid_value("grid", 'dense auto-flow / dense auto-flow');
+test_invalid_value("grid", 'auto / auto-flow foo()');
 // FIXME: add more values to test full syntax
 
 </script>
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 8a13fc98..dafe54d 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-12-1-25-gd9b8a69e9
-Revision: d9b8a69e9a8ba5ac999e721d50c231fe2e01d0bd
+Version: VER-2-12-1-26-gf7daf9d29
+Revision: f7daf9d293c00cbb80c9f7bf4dc93717464a80e8
 CPEPrefix: cpe:/a:freetype:freetype:2.11.1
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/webrtc_overrides/BUILD.gn b/third_party/webrtc_overrides/BUILD.gn
index 5862bfd..438e948 100644
--- a/third_party/webrtc_overrides/BUILD.gn
+++ b/third_party/webrtc_overrides/BUILD.gn
@@ -19,8 +19,11 @@
   ":task_queue_factory",
   "//third_party/webrtc/api:array_view",
   "//third_party/webrtc/api:callfactory_api",
+  "//third_party/webrtc/api:candidate",
+  "//third_party/webrtc/api:dtls_transport_interface",
   "//third_party/webrtc/api:frame_transformer_interface",
   "//third_party/webrtc/api:ice_transport_factory",
+  "//third_party/webrtc/api:ice_transport_interface",
   "//third_party/webrtc/api:libjingle_logging_api",
   "//third_party/webrtc/api:libjingle_peerconnection_api",
   "//third_party/webrtc/api:make_ref_counted",
@@ -32,6 +35,7 @@
   "//third_party/webrtc/api:rtp_packet_info",
   "//third_party/webrtc/api:rtp_parameters",
   "//third_party/webrtc/api:scoped_refptr",
+  "//third_party/webrtc/api:turn_customizer",
   "//third_party/webrtc/api/adaptation:resource_adaptation_api",
   "//third_party/webrtc/api/audio:aec3_config",
   "//third_party/webrtc/api/audio:aec3_config_json",
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py
index 006c1ba8..28f44aae 100755
--- a/tools/binary_size/diagnose_bloat.py
+++ b/tools/binary_size/diagnose_bloat.py
@@ -417,7 +417,9 @@
       for path in self.build.abs_apk_paths:
         self._ArchiveFile(path)
       for path in self.build.abs_mapping_paths:
-        self._ArchiveFile(path)
+        # TrichromeLibrary has no .mapping file.
+        if 'TrichromeLibrary' not in path:
+          self._ArchiveFile(path)
       self._ArchiveResourceSizes()
     self._ArchiveSizeFile()
     if self._save_unstripped:
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 5713bbd..8a4f0141 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -61,6 +61,14 @@
 crbug.com/1236631 [ win ] desktop_ui/side_search:* [ Skip ]
 crbug.com/1236631 [ mac ] desktop_ui/side_search:* [ Skip ]
 crbug.com/1236631 [ linux ] desktop_ui/side_search:* [ Skip ]
+crbug.com/1337486 [ mac ] desktop_ui/tab_search:100_recently_closed [ Skip ]
+crbug.com/1337486 [ mac ] desktop_ui/tab_search:10_recently_closed [ Skip ]
+crbug.com/1337486 [ mac ] desktop_ui/tab_search:50_recently_closed [ Skip ]
+crbug.com/1337486 [ mac ] desktop_ui/tab_search:scroll_up_and_down:2020 [ Skip ]
+crbug.com/1337486 [ mac ] desktop_ui/tab_search:top10:2020 [ Skip ]
+crbug.com/1337486 [ mac ] desktop_ui/tab_search:top10:loading:2020 [ Skip ]
+crbug.com/1337486 [ mac ] desktop_ui/tab_search:top50:2020 [ Skip ]
+crbug.com/1337486 [ mac ] desktop_ui/tab_search:top50:loading:2020 [ Skip ]
 
 # Benchmark: blink_perf.webcodecs
 crbug.com/1300680 [ android ] blink_perf.webcodecs/software-video-encoding.html [ Skip ]
diff --git a/ui/chromeos/translations/ui_chromeos_strings_am.xtb b/ui/chromeos/translations/ui_chromeos_strings_am.xtb
index da507a5..9a5652e 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_am.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_am.xtb
@@ -618,6 +618,7 @@
 <translation id="6296410173147755564">ልክ ያልኾነ PUK</translation>
 <translation id="6312403991423642364">ያልታወቀ የአውታረ መረብ ስህተት</translation>
 <translation id="6317608858038767920">ብጁ የስም አገልጋይ <ph name="INPUT_INDEX" /></translation>
+<translation id="6320212353742551423">የ<ph name="ARCHIVE_TYPE" /> ማህደር</translation>
 <translation id="6321303798550928047">ማውለብለብ</translation>
 <translation id="6327785803543103246">የድር ተኪ ራስ-ግኝት</translation>
 <translation id="6339145975392024142">የአሜሪካ ዓለምአቀፍ (ተኮ)</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_de.xtb b/ui/chromeos/translations/ui_chromeos_strings_de.xtb
index 09f39fe..10ee02ff 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_de.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_de.xtb
@@ -618,6 +618,7 @@
 <translation id="6296410173147755564">Ungültiger PUK</translation>
 <translation id="6312403991423642364">Unbekannter Netzwerkfehler</translation>
 <translation id="6317608858038767920">Benutzerdefinierter Nameserver <ph name="INPUT_INDEX" /></translation>
+<translation id="6320212353742551423"><ph name="ARCHIVE_TYPE" />-Archiv</translation>
 <translation id="6321303798550928047">Winken</translation>
 <translation id="6327785803543103246">Web-Proxy Autodiscovery</translation>
 <translation id="6339145975392024142">US-amerikanisch (PC)</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_es.xtb b/ui/chromeos/translations/ui_chromeos_strings_es.xtb
index 9f674d8..0d9cf4a 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_es.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_es.xtb
@@ -618,6 +618,7 @@
 <translation id="6296410173147755564">PUK no válido</translation>
 <translation id="6312403991423642364">Error desconocido de red</translation>
 <translation id="6317608858038767920">Servidor de nombres personalizado: <ph name="INPUT_INDEX" /></translation>
+<translation id="6320212353742551423">Archivo <ph name="ARCHIVE_TYPE" /></translation>
 <translation id="6321303798550928047">Mano saludando</translation>
 <translation id="6327785803543103246">Detección automática de proxy web</translation>
 <translation id="6339145975392024142">EE. UU. (PC)</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_lt.xtb b/ui/chromeos/translations/ui_chromeos_strings_lt.xtb
index d3a5ba0..5d8f60e8 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_lt.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_lt.xtb
@@ -618,6 +618,7 @@
 <translation id="6296410173147755564">Netinkamas PUK kodas</translation>
 <translation id="6312403991423642364">Nežinoma tinklo klaida</translation>
 <translation id="6317608858038767920">Tinkintas vardų serveris <ph name="INPUT_INDEX" /></translation>
+<translation id="6320212353742551423"><ph name="ARCHIVE_TYPE" /> archyvas</translation>
 <translation id="6321303798550928047">Mojuojanti ranka</translation>
 <translation id="6327785803543103246">Automatinis žiniatinklio tarpinio serverio aptikimas</translation>
 <translation id="6339145975392024142">JAV tarptautinė (AK) klaviatūra</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ms.xtb b/ui/chromeos/translations/ui_chromeos_strings_ms.xtb
index ef303e58..2ddae63 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ms.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ms.xtb
@@ -618,6 +618,7 @@
 <translation id="6296410173147755564">PUK tidak sah</translation>
 <translation id="6312403991423642364">Ralat rangkaian tidak diketahui</translation>
 <translation id="6317608858038767920">Pelayan nama tersuai <ph name="INPUT_INDEX" /></translation>
+<translation id="6320212353742551423">Arkib <ph name="ARCHIVE_TYPE" /></translation>
 <translation id="6321303798550928047">Melambai</translation>
 <translation id="6327785803543103246">Autopenemuan proksi web</translation>
 <translation id="6339145975392024142">Antarabangsa AS (PC)</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_my.xtb b/ui/chromeos/translations/ui_chromeos_strings_my.xtb
index 497700f..b157c6a4 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_my.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_my.xtb
@@ -617,6 +617,7 @@
 <translation id="6296410173147755564">PUK မမှန်ပါ</translation>
 <translation id="6312403991423642364">ကွန်ရက်အမှားအကြောင်း မသိပါ</translation>
 <translation id="6317608858038767920">စိတ်ကြိုက် အမည်ဆာဗာ <ph name="INPUT_INDEX" /></translation>
+<translation id="6320212353742551423"><ph name="ARCHIVE_TYPE" /> မှတ်တမ်း</translation>
 <translation id="6321303798550928047">လက်ဝှေ့ယမ်းနေသည်</translation>
 <translation id="6327785803543103246">ဝဘ်ပရောက်စီ အလိုအလျောက် ရှာဖွေမှု</translation>
 <translation id="6339145975392024142">ယူအက်စ် နိုင်ငံတကာ (PC)</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ne.xtb b/ui/chromeos/translations/ui_chromeos_strings_ne.xtb
index c08efd3..000ac7b 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ne.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ne.xtb
@@ -617,6 +617,7 @@
 <translation id="6296410173147755564">तपाईंले हाल्नुभएको PUK अवैध छ</translation>
 <translation id="6312403991423642364">अज्ञात सञ्जाल त्रुटि</translation>
 <translation id="6317608858038767920">इच्छ्याइएको nameserver <ph name="INPUT_INDEX" /></translation>
+<translation id="6320212353742551423"><ph name="ARCHIVE_TYPE" /> अभिलेख</translation>
 <translation id="6321303798550928047">हात हल्लाउँदै</translation>
 <translation id="6327785803543103246">वेब प्रोक्सीको स्वत:खोज</translation>
 <translation id="6339145975392024142">अमेरिकी अन्तर्राष्ट्रिय (PC)</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_or.xtb b/ui/chromeos/translations/ui_chromeos_strings_or.xtb
index 9103dcb..2520073 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_or.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_or.xtb
@@ -612,6 +612,7 @@
 <translation id="6296410173147755564">ଅବୈଧ PUK</translation>
 <translation id="6312403991423642364">ଅଜଣା ନେଟ୍‌ୱର୍କ ତ୍ରୁଟି</translation>
 <translation id="6317608858038767920">କଷ୍ଟମ୍ ନେମ୍‌ସର୍ଭର୍ <ph name="INPUT_INDEX" /></translation>
+<translation id="6320212353742551423"><ph name="ARCHIVE_TYPE" /> ଆର୍କାଇଭ</translation>
 <translation id="6321303798550928047">ହାତ ହଲାଇବା</translation>
 <translation id="6327785803543103246">ୱେବ୍ ପ୍ରକ୍ସି ଅଟୋଡିସ୍କୋଭରୀ</translation>
 <translation id="6339145975392024142">US ଆନ୍ତର୍ଜାତିକ (PC)</translation>
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 80bdceeb..07b123d8 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -822,7 +822,7 @@
       if (is_linux) {
         public += [ "widget/desktop_aura/desktop_window_tree_host_linux.h" ]
         sources += [
-          "widget/desktop_aura/desktop_screen_linux.cc",
+          "widget/desktop_aura/desktop_screen_ozone_linux.cc",
           "widget/desktop_aura/desktop_window_tree_host_linux.cc",
           "widget/desktop_aura/window_event_filter_linux.cc",
           "widget/desktop_aura/window_event_filter_linux.h",
diff --git a/ui/views/widget/desktop_aura/desktop_screen_linux.cc b/ui/views/widget/desktop_aura/desktop_screen_ozone_linux.cc
similarity index 99%
rename from ui/views/widget/desktop_aura/desktop_screen_linux.cc
rename to ui/views/widget/desktop_aura/desktop_screen_ozone_linux.cc
index e2b3b5a2..8839e76b 100644
--- a/ui/views/widget/desktop_aura/desktop_screen_linux.cc
+++ b/ui/views/widget/desktop_aura/desktop_screen_ozone_linux.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
 #include "base/notreached.h"
 #include "ui/ozone/public/platform_screen.h"
 #include "ui/views/linux_ui/device_scale_factor_observer.h"
 #include "ui/views/linux_ui/linux_ui.h"
+#include "ui/views/widget/desktop_aura/desktop_screen.h"
 #include "ui/views/widget/desktop_aura/desktop_screen_ozone.h"
 
 namespace views {